CommentLuv - Version 2.94.8

Version Description

  • October 5, 2018
  • fixed : a few PHP notice errors
  • fixed : allow commenters to use https:// or http:// in URL field. Previously, only http:// was allowed
  • fixed : After blog domain name changes or SSL site migrations, API URL setting could be incorrect. If this setting is incorrect, we use various methods to ensure the plugin still functions on the frontend.
  • fixed : possible fix for errors when fetching recent posts from commenters when their blog is SSL
  • fixed : using newer plugin-included simplepie library to assist with connecting to various SSL hosts
  • updated : easier for commenters to use by triggering recent posts fetch on textarea focus AND website blur, helps eliminate need to toggle CommentLuv checkbox off/on to trigger a fetch
Download this release

Release Info

Developer bompus
Plugin Icon 128x128 CommentLuv
Version 2.94.8
Comparing to
See all releases

Code changes from version 2.94.7 to 2.94.8

Files changed (46) hide show
  1. changelog.txt +384 -0
  2. commentluv.php +1988 -1912
  3. js/commentluv.js +336 -293
  4. libs/SimpleCluvPie/LICENSE.txt +26 -0
  5. libs/SimpleCluvPie/SimpleCluvPie.txt +1 -0
  6. libs/SimpleCluvPie/autoloader.php +85 -0
  7. libs/SimpleCluvPie/idn/LICENCE +502 -0
  8. libs/SimpleCluvPie/idn/ReadMe.txt +123 -0
  9. libs/SimpleCluvPie/idn/idna_convert.class.php +969 -0
  10. libs/SimpleCluvPie/idn/npdata.ser +1 -0
  11. libs/SimpleCluvPie/library/SimpleCluvPie.php +3274 -0
  12. libs/SimpleCluvPie/library/SimpleCluvPie/Author.php +156 -0
  13. libs/SimpleCluvPie/library/SimpleCluvPie/Cache.php +134 -0
  14. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Base.php +113 -0
  15. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/DB.php +136 -0
  16. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/File.php +164 -0
  17. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Memcache.php +180 -0
  18. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Memcached.php +166 -0
  19. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/MySQL.php +454 -0
  20. libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Redis.php +166 -0
  21. libs/SimpleCluvPie/library/SimpleCluvPie/Caption.php +209 -0
  22. libs/SimpleCluvPie/library/SimpleCluvPie/Category.php +156 -0
  23. libs/SimpleCluvPie/library/SimpleCluvPie/Content/Type/Sniffer.php +331 -0
  24. libs/SimpleCluvPie/library/SimpleCluvPie/Copyright.php +129 -0
  25. libs/SimpleCluvPie/library/SimpleCluvPie/Core.php +56 -0
  26. libs/SimpleCluvPie/library/SimpleCluvPie/Credit.php +155 -0
  27. libs/SimpleCluvPie/library/SimpleCluvPie/Decode/HTML/Entities.php +615 -0
  28. libs/SimpleCluvPie/library/SimpleCluvPie/Enclosure.php +1379 -0
  29. libs/SimpleCluvPie/library/SimpleCluvPie/Exception.php +51 -0
  30. libs/SimpleCluvPie/library/SimpleCluvPie/File.php +306 -0
  31. libs/SimpleCluvPie/library/SimpleCluvPie/HTTP/Parser.php +499 -0
  32. libs/SimpleCluvPie/library/SimpleCluvPie/IRI.php +1257 -0
  33. libs/SimpleCluvPie/library/SimpleCluvPie/Item.php +2977 -0
  34. libs/SimpleCluvPie/library/SimpleCluvPie/Locator.php +429 -0
  35. libs/SimpleCluvPie/library/SimpleCluvPie/Misc.php +2263 -0
  36. libs/SimpleCluvPie/library/SimpleCluvPie/Net/IPv6.php +275 -0
  37. libs/SimpleCluvPie/library/SimpleCluvPie/Parse/Date.php +983 -0
  38. libs/SimpleCluvPie/library/SimpleCluvPie/Parser.php +656 -0
  39. libs/SimpleCluvPie/library/SimpleCluvPie/Rating.php +128 -0
  40. libs/SimpleCluvPie/library/SimpleCluvPie/Registry.php +224 -0
  41. libs/SimpleCluvPie/library/SimpleCluvPie/Restriction.php +154 -0
  42. libs/SimpleCluvPie/library/SimpleCluvPie/Sanitize.php +589 -0
  43. libs/SimpleCluvPie/library/SimpleCluvPie/Source.php +610 -0
  44. libs/SimpleCluvPie/library/SimpleCluvPie/XML/Declaration/Parser.php +361 -0
  45. libs/SimpleCluvPie/library/SimpleCluvPie/gzdecode.php +370 -0
  46. readme.txt +451 -535
changelog.txt ADDED
@@ -0,0 +1,384 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ = 2.94.8 =
2
+ * October 5, 2018
3
+ * fixed : a few PHP notice errors
4
+ * fixed : allow commenters to use https:// or http:// in URL field. Previously, only http:// was allowed
5
+ * fixed : After blog domain name changes or SSL site migrations, API URL setting could be incorrect. If this setting is incorrect, we use various methods to ensure the plugin still functions on the frontend.
6
+ * fixed : possible fix for errors when fetching recent posts from commenters when their blog is SSL
7
+ * fixed : using newer plugin-included simplepie library to assist with connecting to various SSL hosts
8
+ * updated : easier for commenters to use by triggering recent posts fetch on textarea focus AND website blur, helps eliminate need to toggle CommentLuv checkbox off/on to trigger a fetch
9
+
10
+ = 2.94.7 =
11
+ * updated : compatibility
12
+ * updated : no longer encoding to UTF8
13
+
14
+ = 2.94.5 =
15
+ * updated : compatibility
16
+
17
+ = 2.94.4 =
18
+ * added : Thai translation
19
+
20
+ = 2.94.3 =
21
+ * added : swahili translation
22
+
23
+ = 2.94.1 =
24
+ * updated : added message about free 10 week course.
25
+ * updated : compatibility notice
26
+
27
+ = 2.94 =
28
+
29
+ * fixed : undefined index error on display of feed if can't found in settings page
30
+ * added : you can now uncheck the option to use the security nonce for ajax calls (in cases where blogs are using a peristent cache)
31
+
32
+ = 2.93.9 =
33
+
34
+ * updated FAQ
35
+
36
+ = 2.93.8 =
37
+
38
+ *fixed : videos where not showing in popup (server move broke URLs)
39
+ *updated : compatibility declaration
40
+
41
+ = 2.93.6 =
42
+
43
+ *fixed : feed display in settings page allows for non array return
44
+ *fixed : undefined index in ajax processer broke ajax if settings set to show all errors (rare)
45
+
46
+ = 2.93.5 =
47
+
48
+ * added : option to allow disable of utf8 encode on feed (thanks Eli http://www.un-jardin-bio.com for testing)
49
+
50
+ = 2.93.4 =
51
+
52
+ * updated : experimental - force to utf8 characters when outputting feed
53
+ * updated : vietnamese language update
54
+
55
+ = 2.93.3 =
56
+
57
+ * updated : readme now says minimum wp 3.6 required
58
+ * updated : add_removeluv_link now detects if $post is not available (prevents error on dashboard comments)
59
+ * fixed : sidebar for wordpress 3.8 now shows properly (removed width setting on #poststuff div)
60
+ * updated : sidebar facebook widget updated to use comluv.com version
61
+
62
+ = 2.93.2 =
63
+
64
+ * updated : get_user_by_email removed from functions.
65
+
66
+ = 2.93.1 =
67
+
68
+ * updated : prevent notice in admin for $authurl , check it is in $comment before trying to use it
69
+
70
+ = 2.93 =
71
+
72
+ * fixed : removed deprecated .live from javascript
73
+
74
+ = 2.92.9 =
75
+
76
+ * updated : settings page panel for ads
77
+ * updated : compatibility setting
78
+
79
+ = 2.92.8 =
80
+
81
+ * updated : translation for Bengali
82
+ * updated : translation for Turkish
83
+ * added : allow swap of [type] with 'blog post' so old versions that are updated but not modified will look better
84
+
85
+ = 2.92.7 =
86
+
87
+ * fixed : enclose title in cdata tags in send feed file function to prevent invalid xml errors
88
+
89
+ = 2.92.6 =
90
+
91
+ * fixed : special feed was showing special chars for hyphen and quotes in post titles
92
+ * fixed : strip tags from feed before displaying in drop down
93
+
94
+ = 2.92.5 =
95
+
96
+ * fixed : simplepie library changed to use separate class file for File
97
+ * updated : better error reporting with simplepie for sites with undiscovered feeds
98
+
99
+ = 2.92.4 =
100
+
101
+ * updated : make ajax fetch more secure
102
+
103
+ = 2.92.3 =
104
+
105
+ * updated : fetch feed function updated to try 1 more alternative if all else fails
106
+ * fixed : wpdb->prepare notice fix
107
+
108
+ = 2.92.2 =
109
+
110
+ * updated : updated Italian translation (thanks Gianni!)
111
+ * added : Serbian translation (thanks Diana!)
112
+ * updated : version checking to show ionCube status
113
+ * updated : add version number of plugin to version number of register script call
114
+
115
+ = 2.92.1 =
116
+
117
+ * added : ability to allow Jetpack comments to activate. (thought it best to still allow free choice, maybe someone wants the advantage they get with commentluv when they comment on other commentluv blogs?)
118
+
119
+ = 2.92 =
120
+
121
+ * prevent jetpack comments module from being activated so comment is not affected by jetpack plugin upgrades.
122
+ * updated : Italian translation
123
+
124
+ = 2.91.1 =
125
+ * minor mishap with ajax notify signup action. It was in the wrong place!
126
+
127
+ = 2.91 =
128
+ * new changes implimented for author/category urls
129
+ * remove ugly red box for upgrade notice. replace with calming yellow one with a convenient link to update the plugin.
130
+ * fixed : prevent DOING_AJAX from being defined if is already defined
131
+ * updated : clear output buffer before sending feed
132
+ * updated : prevent simplepie deprecated notices from showing when fetching feed if php is set to show them
133
+ * updated : add trailing slash to url for fetching feed (some sites that have errors bork without trailing slash)
134
+ * updated : do first round of effecient action setting so ajax only functions are much better for memory
135
+
136
+ = 2.90.9.9.3 =
137
+ * changed : try no whitespace in send_feed_file
138
+ * changed : send application/atom+xml header before feed file to maybe prevent invalid mime type errors
139
+ * changed : request feed set to feed = atom in fetch_feed
140
+ * updated : can now request author/category and tag posts by using appropriate url in comment form of a commentluv enabled site
141
+
142
+ = 2.90.9.9.2 =
143
+ * added : try to increase memory available to commentluv
144
+ * changed : set encoding to match that of the blog in send_feed_file
145
+
146
+ = 2.90.9.9.1 =
147
+ * fixed : trying new encoding of send_feed_file to match blog encoding
148
+
149
+ = 2.90.9.9 =
150
+ * fixed : trying updated detection routines to be compatible with new WP 3.4 query code
151
+
152
+ = 2.90.9.8 =
153
+ * added : Hungarian Translation
154
+ * added : Vietnamese Translation
155
+ * added : Slovak Translation
156
+ * fixed : send_feed only to send post_type of post
157
+ * updated : fall back to /?feed=rss2 in url for fetch feed if no feed found
158
+ * updated : add query arg to site url when fetching feed so w3 total cache knows not to cache the response
159
+ * updated : user can now choose to delete or spam a comment that has a link but no author url (prevent spammer abuse)
160
+ * updated : Slovak flag fixed
161
+
162
+ = 2.90.9.7 =
163
+ * updated : Italian translation by Gianni
164
+ * added : make wp_query->is_feed = true if commentluv request detected
165
+
166
+ = 2.90.9.6 =
167
+ * added : code to prevent wp_head and wp_footer actions on a commentluv request from other sites
168
+ * fixed : minor translation string bug in __construct
169
+
170
+ = 2.90.9.5 =
171
+ * fixed : upgrading to 3.3 meant it would show the link even if admin set to not show link if no author URL in comment
172
+ * fixed : footer error about invalid argument if minifying set to on
173
+ * fixed : do not show unregistered in info panel if not set to 'registered' for who to show 10 posts
174
+
175
+ = 2.90.9.4 =
176
+ * added : Hebrew translation
177
+ * fixed : do not echo WP 3.0 requirement, use wp_die instead
178
+
179
+ = 2.90.9.3 =
180
+ * fix : another empty src badge bug
181
+ * fix : link not showing in admin page if a setting was enabled
182
+ * added : empty index files in directories to prevent indexing of plugins folders
183
+ * updated : images updated by Byteful Traveller (byteful.com)
184
+
185
+ = 2.90.9.2 =
186
+ * fix : sometimes badge was showing empty src
187
+ * added : Bengali language
188
+ * settings page header
189
+ * modify settings page intro
190
+ * added : prevent links for comments that have had the URL removed
191
+
192
+ = 2.90.9.1 =
193
+ * removed : w3 total cache stuff causes fatal errors on activation. removing all w3 stuff completely
194
+
195
+ = 2.90.9 =
196
+ * added : Danish language
197
+ * fixed : minor problems with some checkbox vars
198
+ * fixed : issue where an empty link might get added to a comment
199
+ * fixed : small bug in settings page that prevented checkbox from being checked for default on if default admin on was unchecked
200
+ * fixed : use `home_url()` instead of deprecated `get_bloginfo('home')` in `send_feed()` function
201
+ * fixed : url value check compatible with iPad which adds a capital letter for the first letter of a form field
202
+
203
+ = 2.90.8.3 =
204
+ * fixed : fixed the error with cl_settings not defined (it was not localizing the script)
205
+
206
+ = 2.90.8.2 =
207
+ * added : french translation
208
+ * fixed : sorry! I messed up the code when I tried to remove notices from happening in debug mode which made some blogs have an error.
209
+
210
+ = 2.90.8.1 =
211
+ * updated italian language (thanks Gianni)
212
+ * fixed : fixed all notices when running in DEBUG mode
213
+ * fixed : default image display in settings page was not showing after resetting settings
214
+
215
+ = 2.90.8 =
216
+ * added : Tamil language
217
+ * added : Ukranian language
218
+ * added : check for home page in detect commentluv request and send back 10 last posts instead of relying on object which my be populated with the contents of a homepage slider
219
+ * added : function to count number of approved comments with luvlink made in the past 14 days
220
+ * added : Latvian language
221
+ * fixed : small issue with Polish language showing weird characters in settings page.
222
+ * updated : Polish translation (thanks Mariusz!)
223
+ * fixed : minor issue with settings page localized js for badge choice in IE
224
+ * added : Romanian language
225
+ * fixed : couple of undefined index warnings showing when on debug mode
226
+ * fixed : error responseText for parseerror should now show the response body
227
+ * added : check for wp_rss function existence before including rss.php to prevent a fatal error if another plugin is including rss.php in every page (eg. energizer plugin)
228
+ * added : Norwegian language
229
+
230
+ = 2.90.7 =
231
+ * added : more detailed error messages to javascript
232
+ * added : update version number in db on activation if existing version is less
233
+ * added : not authorized error in fetch function if nonce check fails
234
+ * added : allow disabling of commentluv request detection (for those getting xml errors when commenting on other sites)
235
+ * added : if w3 total cache active, clear cache on commentluv activation/upgrade.
236
+ * added : German translation
237
+ * added : warning if saving settings with 10 posts only for registered users but registration not enabled
238
+ * added : include note about registration not enabled to drop down list (only for admin to see)
239
+ * added : auto add commentluv to list of useragents to ignore for w3 pagecache
240
+ * bugfix : prevent theme from outputting data before send_feed if commentluv useragent detected
241
+ * added : Persian translation
242
+
243
+ = 2.90.6 =
244
+ * bugfix : causing fatal error on upgrade to 2.90.5 sorry!! It was all my fault
245
+ * bugfix : escape titles of other posts when showing info panel.
246
+ * bugfix : compatibility with W3 total cache
247
+ * removed : attempt at detecting useragent and object buffering to counteract W3 total cache
248
+ * added : detection of headers already sent
249
+ * added : add register link to drop down list if the link is missing and regisration is enabled
250
+ * added : spanish translation
251
+ * change : settings page field for register link set to disabled and descriptive text added
252
+ * change : add random number of seconds up to 1 week to cron time setting on activation to prevent overload on server when plugin update is released
253
+
254
+
255
+ = 2.90.5 =
256
+ * bugfix : send feed function needed to wrap titles in <![CDATA[ ]]> to prevent & from causing xml error (thanks @bienvoyager for testing!)
257
+ * added : use ob_start as early as possible if commentluv useragent detected
258
+ * added : version check with parameters
259
+
260
+ = 2.90.3 =
261
+ * Added some ajax error messages in case of 404 or 500 server errors
262
+ * Added Indonesian language
263
+ * Fixed Malaysian language
264
+ * Tweaked click notification function to be non blocking
265
+
266
+ = 2.90.1 =
267
+ * whole new version rewritten from scratch that makes it standalone.
268
+
269
+ = 2.81.8 =
270
+ * settings page notification block
271
+
272
+ = 2.81.7 =
273
+ * added : Lithuanian translation
274
+ * added : Set nofollow on all links, no links or just unregistered users links
275
+ * fix : xhtml compliance on checkbox (thanks @winkpress)
276
+ * fix : check commentmeta data is an array
277
+
278
+ = 2.81.6 =
279
+ * added : Portuguese (Brazil) translation
280
+ * fixed : added ; to functions in js file
281
+ * added : option to enable compression compatibility for js files and move cl_settings js to footer
282
+ * added : Romanian language
283
+ * added : Arabic language
284
+ * added : Georgian language
285
+
286
+ = 2.81.5 =
287
+ * fixed : commentluv now available on pages too
288
+ * update : change click to hover for showing drop down of last blog posts that were fetched
289
+ * added : Polish translation
290
+ * update : settings page prettifying (hmm perdy!)
291
+ * update : set drop down for last blogs posts event to hover instead of click
292
+
293
+ = 2.81.4 =
294
+ * Fixed : removeluv link in comments admin would result in 404 (thanks @techpatio)
295
+
296
+ = 2.81.3 =
297
+ * Change the way to detect if on a multi site install or not
298
+ * updated one of the badges
299
+
300
+ = 2.81.2 =
301
+ * silly me, put the version number wrong!
302
+ * Set back to default settings if upgrading from less than 2.81
303
+ * Show url field for logged on user if buddypress is active
304
+
305
+ = 2.81.1 =
306
+ * Prevent empty last post from being included. Also included in API
307
+ * Fixed Dutch translation (thanks Rene http://wpwebshop.com)
308
+ * Also have commentluv on pages
309
+ * updated badges to new version (thanks Byteful Traveller)
310
+
311
+ = 2.81 =
312
+ * New style.css format for info panel (thanks @Hishaman)
313
+ * Only show remove luv link for approved comments
314
+ * bug fix : sometimes showed two cluv spans (on beta version comments)
315
+
316
+ = 2.80 =
317
+ * Wordpress 3.0 Compatible
318
+ * Use comments meta table instead of hard coding into the comment content
319
+ * Drastically improved commmunication with API for comment status changes
320
+ * Near 100% accuracy for API to identify members links for info panel
321
+ * New heart icon for registered members. Improves hover rates.
322
+ * Removed depreciated function to clean old style additional data
323
+ * Added link to remove someones luvlink data in the comments admin page
324
+ * Dutch Translation by Rene wppg.me
325
+ * Added comments_array filter to make Thesis behave
326
+ * Added check to see if link already added (WP 3.0 compatibility)
327
+ * thanks to @hishaman for helping the thesis testing
328
+ * Added code to settings manager to prevent viewing outside wordpress (and fixed the typo later, thanks speedforce.org)
329
+
330
+ = 2.7691 =
331
+ * bugfix : choosing a link from an additional url's posts would result in wrong link being included
332
+
333
+ = 2.769 =
334
+ * Modified hidden post fields so only URL and title sent instead of html A href link
335
+ * Modified javascript to take account of new hidden fields.
336
+ * Temporary fix to try and fix 404 on wp-post-comments.php when commentluv enabled for logged out user
337
+ * thanks to @kwbridge @duane_scott @dannybrown @morpheas7887 for testing and feedback!
338
+
339
+ = 2.768 =
340
+ * Added nothing.gif to images (for updated error message from API)
341
+
342
+ = 2.767 =
343
+ * Added conncettimeout to curl call
344
+ * Added warning next to 'use template insert' checkbox in settings page
345
+
346
+ = 2.766 =
347
+ * Check if function has been called before to prevent two links being added.
348
+ * updated images (supplied by http://byteful.com)
349
+
350
+ = 2.765 =
351
+ * Hollys changes. Allow user choice of colour for the info panel background.
352
+
353
+ = 2.764 =
354
+ * Removed json_decode. Some wp2.9 installs were getting errors
355
+
356
+ = 2.763 =
357
+ * Added check for hidden fields display to prevent double instances.
358
+ * Make css file valid
359
+ * Added French translation by Leo http://referenceurfreelance.com
360
+
361
+ = 2.762 =
362
+ * Added permalink as refer variable in ajax calls for better stat collecting since WP started to use paginated comments
363
+ * Added Chinese translation by Denis http://zuoshen.com/
364
+ * Added Hebrew translation by Maor http://www.maorb.info/
365
+ * Added Russian translation by FatCow
366
+ * Updated readme.txt to use new features like changelog
367
+ * Check for http:// in url field before firing (to prevent errors for forms that use js hints in form fields)
368
+
369
+ = 2.761 =
370
+ * 19 Jun 2009 - fix for htmlspecialchars decode causing error in wp < 2.8
371
+
372
+ = 2.76 =
373
+ * 16 Jun 2009 - Bug fix, use_template checkbox not displaying when selected on settings page (breaker). typo in settings page now uses &lt;?php cl\_display\_badge(); ?&gt;
374
+ * added global variable for badgeshown to prevent mulitple instances (template contains function call AND use template check is off)
375
+ * fixed output of prepend html using decode html and stripslashes. Added green background to update settings button.
376
+
377
+ = 2.74 =
378
+ * 14 Jun 2009 - Italian translation added (and fix CR in string on manager page). Thanks go to Gianni Diurno
379
+
380
+ = 2.71 =
381
+ * 13 Jun 2009 - fix php4 from not allowing last string pos (strrpos)
382
+
383
+ = 2.7 =
384
+ * 12 Jun 2009 - small fixes for valid xhtml on images and checkbox . remove identifying .-= / =-. from inserted link on display time.
commentluv.php CHANGED
@@ -1,1913 +1,1989 @@
1
- <?php /* commentluv
2
- Plugin Name: CommentLuv
3
- Plugin URI: http://comluv.com/
4
- Description: Reward your readers by automatically placing a link to their last blog post at the end of their comment. Encourage a community and discover new posts.
5
- Version: 2.94.7
6
- Author: Andy Bailey
7
- Author URI: http://www.commentluv.com
8
- Copyright (C) <2011> <Andy Bailey>
9
-
10
- This program is free software: you can redistribute it and/or modify
11
- it under the terms of the GNU General Public License as published by
12
- the Free Software Foundation, either version 3 of the License, or
13
- (at your option) any later version.
14
-
15
- This program is distributed in the hope that it will be useful,
16
- but WITHOUT ANY WARRANTY; without even the implied warranty of
17
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
- GNU General Public License for more details.
19
-
20
- You should have received a copy of the GNU General Public License
21
- along with this program. If not, see <http://www.gnu.org/licenses/>.
22
- */
23
- if (! class_exists ( 'commentluv' )) {
24
- // let class begin
25
- class commentluv {
26
- //localization domain
27
- var $plugin_domain = 'commentluv';
28
- var $plugin_url;
29
- var $plugin_dir;
30
- var $db_option = 'commentluv_options';
31
- var $version = "2.94.7";
32
- var $slug = 'commentluv-options';
33
- var $localize;
34
- var $is_commentluv_request = false;
35
-
36
- /** commentluv
37
- * This is the constructor, it runs as soon as the class is created
38
- * Use this to set up hooks, filters, menus and language config
39
- */
40
- function __construct() {
41
- global $wp_version, $pagenow, $wp_actions;
42
- $options = $this->get_options();
43
- // try to add jetpack_module_loaded_comments action so it doesn't load
44
- if(!isset($options['allow_jpc'])){
45
- $wp_actions['jetpack_module_loaded_comments'] = 1;
46
- }
47
- // pages where this plugin needs translation
48
- $local_pages = array ('plugins.php', 'options-general.php' );
49
- // check if translation needed on current page
50
- if (in_array ( $pagenow, $local_pages ) || (isset($_GET['page']) && in_array ( $_GET ['page'], $local_pages ))) {
51
- $this->handle_load_domain ();
52
- }
53
- $exit_msg = __( 'CommentLuv requires Wordpress 3.0 or newer.', $this->plugin_domain ) . '<a href="http://codex.wordpress.org/Upgrading_Wordpress">' . __ ( 'Please Update!', $this->plugin_domain ) . '</a>';
54
- // can you dig it?
55
- if (version_compare ( $wp_version, "3.0", "<" )) {
56
- deactivate_plugins(basename(__FILE__)); //deactivate me
57
- wp_die ( $exit_msg ); // no diggedy
58
- }
59
- // activation/deactivation
60
- register_activation_hook(__FILE__, array(&$this,'activation'));
61
- register_deactivation_hook(__FILE__, array(&$this,'deactivation'));
62
- // manual set install and activate, wordpress wont fire the activation hook on auto upgrade plugin
63
- $cl_version = get_option('cl_version');
64
- if($this->version != $cl_version){
65
- $this->install();
66
- $this->activation();
67
- }
68
- // plugin dir and url
69
- $this->plugin_url = trailingslashit ( WP_PLUGIN_URL . '/' . dirname ( plugin_basename ( __FILE__ ) ) );
70
- $this->plugin_dir = dirname(__FILE__);
71
- if(defined('DOING_AJAX') && DOING_AJAX){
72
- add_action ( 'wp_ajax_removeluv', array (&$this, 'ajax_remove_luv') ); // handle the call to the admin-ajax for removing luv
73
- add_action ( 'wp_ajax_notify_signup', array(&$this,'notify_signup')); // ajax handler for settings page subscribe button
74
- add_action ( 'wp_ajax_nopriv_cl_ajax',array(&$this,'do_ajax'));
75
- add_action ( 'wp_ajax_cl_ajax',array(&$this,'do_ajax'));
76
- } else {
77
- add_action ( 'clversion', array (&$this,'check_version') ); // check commentluv version
78
- add_action ( 'init', array (&$this,'init') ); // to register styles and scripts
79
- add_action ( 'admin_init', array (&$this, 'admin_init' ) ); // to register settings group
80
- add_action ( 'admin_menu', array (&$this, 'admin_menu' ) ); // to setup menu link for settings page
81
- add_action ( 'admin_print_scripts-settings_page_commentluv-options', array(&$this,'add_settings_page_script')); // script for settings page ajax function
82
- add_action ( 'admin_print_styles-settings_page_commentluv-options', array(&$this,'add_settings_page_style')); // script for settings page ajax function
83
- add_action ( 'init', array(&$this,'detect_useragent'));
84
- }
85
- // filters
86
- add_filter ( 'cron_schedules', array (&$this, 'cron_schedules') ); // for my own recurrence
87
- add_filter ( 'plugin_action_links', array (&$this, 'plugin_action_link' ), - 10, 2 ); // add a settings page link to the plugin description. use 2 for allowed vars
88
- // add_filter ( 'found_posts', array(&$this,'send_feed'),-1,2); // sends post titles and urls only - deprecated in 2.90.9.9
89
- add_filter ( 'kindergarten_html', array(&$this,'kindergarten_html')); // for cleaning html
90
-
91
- //$this->check_version();
92
- if(!isset($options['enable']) || ( isset($options['enable']) && $options['enable'] != 'no')){
93
- $this->setup_hooks();
94
- }
95
-
96
-
97
- }
98
- /**
99
- * PHP4 constructor
100
- */
101
- function commentluv() {
102
- $this->__construct();
103
- }
104
- /** runs when plugin is activated
105
- * called by register_activation_hook
106
- *
107
- */
108
- function activation(){
109
- // only add if it doesn't exist yet
110
- $sched = wp_next_scheduled('clversion');
111
- if(false === $sched){
112
- // set up cron for version check
113
- $rnd = mt_rand(5,604800);
114
- wp_schedule_event(time() - $rnd,'clfortnightly','clversion');
115
- }
116
- // removed w3 total cache stuff due to Freds updates causing fatal errors
117
- }
118
- /**
119
- * Adds fields to comment area
120
- * called by add_action('comment_form
121
- */
122
- function add_fields(){
123
- global $clbadgeshown;
124
- $options = $this->get_options();
125
- if(!$this->is_enabled()){
126
- return;
127
- }
128
- $author_name = $options['author_name'];
129
- $email_name = $options['email_name'];
130
- $url_name = $options['url_name'];
131
- // handle logged on user
132
- if(is_user_logged_in()){
133
- global $userdata;
134
- get_currentuserinfo();
135
- $author = $userdata->display_name;
136
- $userid = $userdata->ID;
137
- $url = $userdata->user_url;
138
- if(!strstr($url,'http://') && $url != ''){
139
- $url = 'http://'.$url;
140
- }
141
- // check for s2 member pluin, add url from it's custom registration fields
142
- if(defined('WS_PLUGIN__S2MEMBER_VERSION') && isset($userdata->wp_s2member_custom_fields['website'])){
143
- $url = $userdata->wp_s2member_custom_fields['website'];
144
- }
145
- // check for multisite
146
- if(is_multisite()){
147
- if(!$url || $url == 'http://'){
148
- $userbloginfo = get_blogs_of_user($userid,1);
149
- $url = $userbloginfo[1] -> siteurl;
150
- }
151
- }
152
- // final check of url
153
- if($url == 'http://'){
154
- $url = '';
155
- }
156
- // spit out hidden fields
157
- echo '<input type="hidden" id="'.$author_name.'" name="'.$author_name.'" value="'.$author.'"/>';
158
- // if buddypress, don't hide field
159
- if(function_exists('bp_core_setup_globals')){
160
- $input_type = 'text';
161
- } else {
162
- $input_type = 'hidden';
163
- }
164
- echo '<input type="'.$input_type.'" id="'.$url_name.'" name="'.$url_name.'" value="'.$url.'"/>';
165
- }
166
- // add hidden fields for holding information about type,choice,html and request for every user
167
- echo '<input type="hidden" name="cl_post_title" id="cl_post_title"/>';
168
- echo '<input type="hidden" name="cl_post_url" id="cl_post_url"/>';
169
- echo '<input type="hidden" name="cl_prem" id="cl_prem"/>';
170
- // show badge (unless user set to manual insert)
171
- if(($clbadgeshown == false && !isset($options['template_insert'])) || (isset($options['template_insert']) && $options['template_insert'] == '') ){
172
- $this->display_badge();
173
- }
174
- }
175
- function add_footer(){
176
- $minifying = 'off';
177
- extract($this->get_options());
178
- if($minifying != 'on' || !$this->is_enabled()){
179
- return;
180
- }
181
- // from the excellent book wp-ajax (http://www.wpajax.com/)
182
- $data = "var cl_settings = {";
183
- $arr = array();
184
- $vars = $this->localize;
185
- if(is_array($vars)){
186
- foreach ($vars as $key => $value) {
187
- $arr[count($arr)] = $key . " : '" . esc_js($value) . "'";
188
- }
189
- $data .= implode(",",$arr); $data .= "};";
190
- echo "<script type='text/javascript'>\n";
191
- echo "/* <![CDATA[ */\n";
192
- echo $data;
193
- echo "\n/* ]]> */\n";
194
- echo "</script>\n";
195
- }
196
- }
197
- /**
198
- * called by add_filter('comment_row_actions
199
- * adds another link to the comment row in admin for removing the luv link
200
- * @param array $actions - the existing actions
201
- */
202
- function add_removeluv_link($actions){
203
- global $post;
204
- if(!$post){
205
- // must be showing on the dashboard
206
- return $actions;
207
- }
208
- $user_can = current_user_can('edit_posts', $post->ID);
209
- $cid = get_comment_ID();
210
- $data = get_comment_meta($cid,'cl_data');
211
- if($data && is_array($data)){
212
- if($user_can){
213
- $nonce= wp_create_nonce ('removeluv'.get_comment_ID());
214
- $actions['Remove-luv'] = '<a class="removeluv :'.$cid.':'.$nonce.'" href="javascript:">Remove Luv</a>';
215
- }
216
- }
217
- return $actions;
218
- }
219
- /**
220
- * called by add_action('admin_print_scripts-edit-comments.php'
221
- * load the script to handle the removluv link
222
- *
223
- */
224
- function add_removeluv_script(){
225
- wp_enqueue_script ( 'commentluv', $this->plugin_url . 'js/adminremoveluv.js', array ('jquery' ),$this->version );
226
- }
227
- /**
228
- * called by add_action('template_redirect in setup_hooks()
229
- * used to add the commentluv script and localized settings (if not using minifying compatibility)
230
- */
231
- function add_script(){
232
- $minifying = 'off';
233
- $template_insert = false;
234
- $options = $this->get_options();
235
- extract($options);
236
- if(!$this->is_enabled()){
237
- return;
238
- }
239
- wp_enqueue_script('commentluv_script');
240
- $this->localize = array ('name' => $author_name, 'url' => $url_name, 'comment' => $comment_name, 'email' => $email_name,
241
- 'infopanel' => $infopanel, 'default_on' => $default_on, 'default_on_admin' => $default_on_admin,
242
- 'cl_version' => $this->version, 'images' => $this->plugin_url . 'images/', 'api_url' => $api_url,
243
- '_fetch' => wp_create_nonce('fetch'), '_info' => wp_create_nonce('info'),
244
- 'infoback' => $infoback, 'infotext'=>$infotext,'template_insert'=>$template_insert, 'logged_in'=>is_user_logged_in(),
245
- 'refer' => get_permalink(),
246
- 'no_url_message'=>__('Please enter a URL and then click the CommentLuv checkbox if you want to add your last blog post',$this->plugin_domain),
247
- 'no_http_message'=>__('Please use http:// in front of your url',$this->plugin_domain),
248
- 'no_url_logged_in_message'=>__('You need to visit your profile in the dashboard and update your details with your site URL',$this->plugin_domain),
249
- 'no_info_message'=>__('No info was available or an error occured',$this->plugin_domain));
250
- if($minifying != 'on'){
251
- wp_localize_script('commentluv_script','cl_settings',$this->localize);
252
- }
253
-
254
-
255
- }
256
- /**
257
- * called by add_action('wp_print_styles in setup_hooks()
258
- * Used to add the stylesheet for commentluv
259
- */
260
- function add_style(){
261
- if(!$this->is_enabled()){
262
- return;
263
- }
264
- wp_enqueue_style('commentluv_style');
265
- }
266
- /**
267
- * Adds scripts to settings page. Only loads scripts if the settings page is being shown
268
- * Called by add_action('admin_print_scripts-settings_page_commentluv-options'
269
- * use localize so messages in javascript are internationalized
270
- */
271
- function add_settings_page_script (){
272
- wp_enqueue_script ('notify_signup', $this->plugin_url . 'js/notify_signup.js', array('jquery'),$this->version );
273
- wp_localize_script ( 'notify_signup', 'notify_signup_settings', array('wait_message'=>__('Please wait',$this->plugin_domain),'notify_success1' => __('Please check your inbox, an email will be sent to',$this->plugin_domain), 'notify_success2'=>__('in the next few minutes with a confirmation link',$this->plugin_domain), 'notify_fail'=>__('An error happened with the request. Try signing up at the site',$this->plugin_domain),'image_url'=>$this->plugin_url.'images/','default_image'=>'CL91_default.png', 'white'=>'CL91_White.gif','black'=>'CL91_Black.gif','none'=>'nothing.gif'));
274
- wp_enqueue_script('thickbox',null,array('jquery'));
275
- echo "<link rel='stylesheet' href='/".WPINC."/js/thickbox/thickbox.css?ver=20080613' type='text/css' media='all' />\n";
276
- }
277
- /**
278
- * adds the thickbox style to header for commentluv settings page
279
- * called by add_action('admin_print_styles-settings_page_commentluv-options
280
- */
281
- function add_settings_page_style(){
282
- wp_enqueue_style('thickbox');
283
- }
284
- /** admin_init
285
- * This function registers the settings group
286
- * it is called by add_action admin_init
287
- * options in the options page will need to be named using $this->db_option[option]
288
- */
289
- function admin_init(){
290
- // whitelist options
291
- register_setting( 'commentluv_options_group', $this->db_option ,array(&$this,'options_sanitize' ) );
292
- $options = $this->get_options();
293
- //if(isset($options['upgrade'])){
294
- if(isset($options['upgrade']) && version_compare($options['upgrade'],$this->php_version($this->version),'>')){
295
- add_action('admin_notices',array(&$this,'show_upgrade_notice'));
296
- }
297
- }
298
-
299
- /** admin_menu
300
- * This function adds a link to the settings page to the admin menu
301
- * see http://codex.wordpress.org/Adding_Administration_Menus
302
- * it is called by add_action admin_menu
303
- */
304
- function admin_menu(){
305
- if(is_multisite()){
306
- $level = 'manage_options'; // for wpmu sub blog admins
307
- } else {
308
- $level = 'administrator'; // for single blog intalls
309
- }
310
- $menutitle = '<img src="' . $this->plugin_url . 'images/littleheart.gif" alt=""/> CommentLuv';
311
- add_options_page ( 'CommentLuv settings', $menutitle, $level, $this->slug, array (&$this, 'options_page' ) );
312
- }
313
- /**
314
- * ajax handler
315
- * setup by add_action ( 'wp_ajax_removeluv'
316
- * called when remove luv link is clicked in comments edit page
317
- * with POST['action'] of removeluv, receives cid and _wpnonce
318
- */
319
- function ajax_remove_luv(){
320
- // check user is allowed to do this
321
- $nonce=$_REQUEST['_wpnonce'];
322
- $cid = $_REQUEST['cid'];
323
- if (! wp_verify_nonce($nonce, 'removeluv'.$cid) ) die("Epic fail");
324
- // delete meta if comment id sent with request
325
- if($cid){
326
- // get meta and set vars if exists
327
- $cmeta =get_comment_meta($cid,'cl_data','true');
328
- if($cmeta) extract($cmeta);
329
- // delete it and call comluv to tell it what happened
330
- if(delete_comment_meta($cid,'cl_data')){
331
- // can call originator blog here maybe
332
- // return the comment id and status code for js processing to hide luv
333
- echo "$cid*200";
334
- }
335
- } else {
336
- echo '0';
337
- }
338
- exit;
339
- }
340
- /**
341
- * checks for a new version
342
- * called by a cron action
343
- */
344
- function check_version(){
345
- //debugbreak();
346
- $version = $this->php_version($this->version);
347
- $options = $this->get_options();
348
- $url = 'http://version.commentluv.com/';
349
- $name = strip_tags(get_bloginfo('name'));
350
- $description = strip_tags(get_bloginfo('description'));
351
- $ioncube = extension_loaded('ionCube Loader')? 'yes' : 'no';
352
- $numluv = $this->get_numluv();
353
- $dofollow = $options['dofollow'];
354
- $whogets = $options['whogets'];
355
- $body = array('version'=>$version,'enabled'=>$options['enable'],'name'=>$name,'description'=>$description,'avatarmd5'=>md5(strtolower(get_bloginfo('admin_email'))),'numluv'=>$numluv,'dofollow'=>$dofollow,'whogets'=>$whogets,'ioncube'=>$ioncube);
356
- $response = wp_remote_head($url,array('method'=>'POST','body'=>$body));
357
- $latest = $this->php_version(wp_remote_retrieve_header($response,'version'));
358
- $message = wp_remote_retrieve_header($response,'message');
359
- if(version_compare($version,$latest,'<')){
360
- $options['upgrade'] = $latest;
361
- if($message){
362
- $options['upgrade_message'] = apply_filters('kindergarten_html',$message);
363
- }
364
- update_option($this->db_option,$options);
365
- }
366
- }
367
- /**
368
- * called by add_action('comment_post
369
- * runs just after comment has been saved to the database
370
- * will save the luv link to comment meta if it exists
371
- *
372
- * @param int $id - id of the comment
373
- * @param string $commentdata - status of comment
374
- */
375
- function comment_posted($id,$commentdata){
376
- if(isset($_POST['cl_post_url']) && $_POST['cl_post_url'] != '' && isset($_POST['cl_post_title']) && $_POST['cl_post_title'] != ''){
377
- $title = strip_tags($_POST['cl_post_title']);
378
- $link = esc_url($_POST['cl_post_url']);
379
- $options = $this->get_options();
380
- //debugbreak();
381
- // check for spam or delete comment if no author url
382
- // spam or delete comment if no author url depending on user settings
383
- //(for logged out users only because logged in users have no commentdata->comment_author_url)
384
- if(!is_user_logged_in()){
385
- if($options['hide_link_no_url'] == 'spam' && $commentdata->comment_author_url ==''){
386
- $commentdata->comment_approved = 'spam';
387
- $update = wp_update_comment((array)$commentdata);
388
- }
389
- if($options['hide_link_no_url'] == 'delete' && $commentdata->comment_author_url == ''){
390
- wp_delete_comment($id);
391
- return;
392
- }
393
- // check for matching comment
394
- if(!isset($options['hide_link_no_url_match'])){
395
- $options['hide_link_no_url_match'] = 'nothing';
396
- }
397
- $authorurlarr = parse_url($commentdata->comment_author_url);
398
- $linkurlarr = parse_url($link);
399
- if($options['hide_link_no_url_match'] != 'nothing'){
400
- if($authorurlarr['host'] != $linkurlarr['host']){
401
- // link has different domain
402
- if($options['hide_link_no_url_match'] == 'spam'){
403
- $commentdata->comment_approved = 'spam';
404
- $update = wp_update_comment((array)$commentdata);
405
- }
406
- if($options['hide_link_no_url_match'] == 'delete'){
407
- wp_delete_comment($id);
408
- return;
409
- }
410
- }
411
- }
412
- }
413
- $prem = 'p' == $_POST['cl_prem'] ? 'p' : 'u';
414
- $data = array('cl_post_title'=>$title,'cl_post_url'=>$link,'cl_prem'=>$prem);
415
- add_comment_meta($id,'cl_data',$data,'true');
416
- }
417
- }
418
- /**
419
- * add my own recurrence schedule
420
- * called by add_filter('cron_schedules
421
- *
422
- * @param mixed $schedules - the current schedules
423
- */
424
- function cron_schedules($schedules){
425
- $schedules['clfortnightly'] = array(
426
- 'interval' => 1209600,
427
- 'display' => __('Twice Monthly')
428
- );
429
- return $schedules;
430
- }
431
- /** runs when plugin is deactivated
432
- * called by register_deactivation_hook
433
- *
434
- */
435
- function deactivation(){
436
- wp_clear_scheduled_hook('clversion');
437
- }
438
- /**
439
- * detect if request is from a commentluv useragent
440
- * called by add_action('init
441
- *
442
- * ignore if user has set disable_detect in settings
443
- *
444
- * since 2.90.9.9 - add action for template redirect, we do the sending of the special feed there now
445
- */
446
- function detect_useragent(){
447
- $options = $this->get_options();
448
- // dont do anything if detect is disabled
449
- if(isset($_POST['version_check'])){
450
- $this->check_version();
451
- }
452
- if(isset($options['disable_detect']) && $options['disable_detect'] == 'on'){
453
- return;
454
- }
455
- // is this commentluv calling?
456
- if (preg_match("/Commentluv/i", $_SERVER['HTTP_USER_AGENT'])){
457
- $this->is_commentluv_request = true;
458
- ob_start();
459
- if(!isset($options['disable_detect'])){
460
- remove_all_actions('wp_head');
461
- remove_all_actions('wp_footer');
462
- // prevent wordpress.com stats from adding stats script
463
- global $wp_query;
464
- $wp_query->is_feed = true;
465
- // use own function to output feed
466
- add_action('template_redirect',array(&$this,'send_feed_file'),1);
467
- }
468
- }
469
- }
470
- /**
471
- * Called by add_fields or by manual insert
472
- * used to show the badge and extra bits for holding the ajax drop down box
473
- *
474
- */
475
- function display_badge(){
476
- //DebugBreak();
477
- global $clbadgeshown;
478
- $badges = array('default'=>'CL91_default.png','default_image'=>'CL91_default.png','white'=>'CL91_White.gif','black'=>'CL91_Black.gif');
479
- $options = $this->get_options();
480
- if($clbadgeshown == true){
481
- return;
482
- }
483
- // link to commentluv?
484
- $before = '';
485
- $after = '';
486
- // link
487
- if(isset($options['link'])){
488
- $before = '<a href="http://www.commentluv.com" target="_blank" title="'.__('CommentLuv is enabled',$this->plugin_domain).'">';
489
- $after = '</a>';
490
- }
491
- // dropdown choice
492
- if($options['badge_choice'] == 'drop_down'){
493
- if($options['badge_type'] != 'none'){
494
- $imgurl = $this->plugin_url.'images/'.$badges[$options['badge_type']];
495
- }
496
- }
497
- // custom image
498
- if($options['badge_choice'] == 'custom'){
499
- if(isset($options['custom_image_url']) && $options['custom_image_url'] != ''){
500
- if(!strstr($options['custom_image_url'],'http://')){
501
- $imgurl = 'http://'.$options['custom_image_url'];
502
- } else {
503
- $imgurl = $options['custom_image_url'];
504
- }
505
- }
506
- }
507
- // create badge code (if not chosen 'none')
508
- if($options['badge_choice'] == 'drop_down' && $options['badge_type'] == 'none'){
509
- $badgecode = '';
510
- } else {
511
- if(!$imgurl){
512
- $imgurl = $this->plugin_url.'images/'.$badges['default_image'];
513
- }
514
- $badgecode = $before.'<img alt="CommentLuv badge" src="'.$imgurl.'"/>'.$after;
515
- }
516
- // or using text
517
- if($options['badge_choice'] == 'text'){
518
- $badgecode = $before.$options['badge_text'].$after;
519
- }
520
- // default on
521
- $default_on = '';
522
- if($options['default_on'] == 'on'){
523
- $default_on = ' checked="checked"';
524
- if(is_user_logged_in() && current_user_can('manage_options')){
525
- if($options['default_on_admin'] != 'on'){
526
- $default_on = '';
527
- }
528
- }
529
- }
530
- // spit out code
531
- echo '<div id="commentluv"><div id="cl_messages"></div><input type="checkbox" id="doluv" name="doluv"'.$default_on.' /><span id="mylastpost">'.$badgecode.'</span><span id="showmorespan"><img class="clarrow" id="showmore" src="'.$this->plugin_url.'images/down-arrow.gif" alt="'.__('Show more posts',$this->plugin_domain).'" title="'.__('Show more posts',$this->plugin_domain).'" style="display:none;"/></span></div><div id="lastposts" style="display:none;"></div>';
532
- $clbadgeshown = true;
533
- }
534
- /**
535
- * ajax handler.
536
- * called by add_action('wp_ajax_(nopriv_)ajax
537
- * handles all ajax requests, receives 'do' as POST var and calls relevant function
538
- *
539
- */
540
- function do_ajax(){
541
- $oldchecknonce = $_POST['_ajax_nonce'];
542
- $newchecknonce = preg_replace("/[^A-Za-z0-9 ]/", '', $oldchecknonce);
543
- if($oldchecknonce != $newchecknonce){
544
- die('error! nonce malformed');
545
- }
546
- switch($_POST['do']){
547
- case 'fetch' :
548
- $this->fetch_feed();
549
- break;
550
- case 'info' :
551
- $this->do_info();
552
- break;
553
- case 'click' :
554
- $this->do_click();
555
- break;
556
-
557
- }
558
- }
559
- /**
560
- * called by do_ajax
561
- * receives cid and nonce and cl_prem as POST vars
562
- * stores the click in the comment meta
563
- */
564
- function do_click(){
565
- $cid = intval($_POST['cid']);
566
- $nonce = $_POST['_ajax_nonce'];
567
- $url = $_POST['url'];
568
- if(!wp_verify_nonce($nonce,$cid)){
569
- exit;
570
- }
571
- $data = get_comment_meta($cid,'cl_data',true);
572
- if(is_array($data)){
573
- $data['clicks'] = $data['clicks'] + 1;
574
- update_comment_meta($cid,'cl_data',$data);
575
- }
576
- if($_POST['cl_prem'] == 'true'){
577
- $comment = get_commentdata($cid);
578
- $refer = get_permalink($comment['comment_post_ID']);
579
- // set blocking to false because no response required
580
- $response = wp_remote_post($url,array('blocking'=>false,'body'=>array('cl_request'=>'click','refer'=>$refer,'version'=>$this->version)));
581
- }
582
- exit;
583
- }
584
- /**
585
- * called by do_ajax
586
- * receives cl_prem, url and cid as POST vars
587
- * sends back json encoded string for the content of the panel
588
- */
589
- function do_info(){
590
- $options = $this->get_options();
591
- if(isset($options['use_nonce'])){
592
- check_ajax_referer('info');
593
- }
594
- global $wpdb;
595
-
596
- $isreg = false;
597
- $cid = intval($_POST['cid']);
598
- $cl_prem = $_POST['cl_prem'];
599
- $link = $_POST['link'];
600
- // is registered user?
601
- $email = get_comment_author_email($cid);
602
- //$user = get_user_by_email($email);
603
- $user = get_user_by('email',$email);
604
- if($user){
605
- $isreg = true;
606
- }
607
- // get comments and stats
608
- $query = $wpdb->prepare('SELECT m.meta_value, c.comment_post_ID FROM '.$wpdb->comments.' c JOIN '.$wpdb->commentmeta.' m ON c.comment_ID = m.comment_ID WHERE c.comment_approved = 1 AND c.comment_author_email = %s AND m.meta_key = %s ORDER BY c.comment_ID DESC',$email,'cl_data');
609
- $rows = $wpdb->get_results($query);
610
- $num_comments = $wpdb->num_rows;
611
- // get other comments and links left
612
- $appeared_on = array();
613
- $appeared_on_list = array();
614
- $my_other_posts = array();
615
- $my_other_posts_list = array();
616
-
617
- if($rows){
618
- foreach($rows as $row){
619
- $data = unserialize($row->meta_value);
620
- if(!in_array($data['cl_post_url'],$my_other_posts_list) && sizeof($my_other_posts) < 5){
621
- $my_other_posts[] = '<a target="_blank" href="'.$data['cl_post_url'].'">'.esc_js(substr($data['cl_post_title'],0,60)).'</a>';
622
- $my_other_posts_list[] = $data['cl_post_url'];
623
- }
624
- if(!in_array($row->comment_post_ID,$appeared_on_list) && sizeof($appeared_on) < 5){
625
- $appeared_on[] = '<a href="'.get_permalink($row->comment_post_ID).'">'.substr(get_the_title($row->comment_post_ID),0,60).'</a>';
626
- $appeared_on_list[] = $row->comment_post_ID;
627
- }
628
- // stop if both lists at 5
629
- if(count($appeared_on) >= 5 && count($my_other_posts) >= 5){
630
- break;
631
- }
632
- }
633
- }
634
- if(empty($appeared_on)){
635
- $appeared_on[] = __('I have only commented on this post',$this->plugin_domain);
636
- }
637
- if(empty($my_other_posts)){
638
- $my_other_posts[] = '<a>'.__('If I had made more comments on this site, you would see more of my other posts here',$this->plugin_domain).'</a>';
639
- }
640
- // get click count on local site
641
- $data = get_comment_meta($cid,'cl_data',true);
642
- $clickcount = isset($data['clicks']) ? $data['clicks'] : 0;
643
- //DebugBreak();
644
- // prem member, try remote fetch of info if not registered on this blog
645
- if($cl_prem == 'p' && $isreg == false){
646
- $response = wp_remote_post($link,array('body'=>array('cl_request'=>'info','version'=>$this->version,'clickcount'=>$clickcount,'num_comments'=>$num_comments,'appeared_on'=>$appeared_on)));
647
- $enabled = wp_remote_retrieve_header($response,'cl_info');
648
- if($enabled == 'enabled'){
649
- $panel = apply_filters('kindergarten_html',wp_remote_retrieve_body($response));
650
- $json = json_encode(array('panel'=>$panel));
651
- header ( "Content-Type: application/x-javascript; " );
652
- echo $json;
653
- exit;
654
- } else {
655
- $cl_prem = 'u';
656
- }
657
- }
658
- // show registered members panel
659
- if($isreg){
660
- // get users info
661
- $bio = $user->description;
662
- if($bio == ''){
663
- $bio = __('User has not saved a description in their profile page',$this->plugin_domain);
664
- }
665
- $username = $user->display_name;
666
- if(is_multisite()){
667
- $can = 'manage_options';
668
- } else {
669
- $can = 'administrator';
670
- }
671
- // find if user has cap, need to create new user object and use ->has_cap
672
- // from wp 3.1, you can use if(user_can($user,$cap))
673
- $user = new WP_User($user->ID);
674
- if($user->has_cap($can)){
675
- $reg_member = __('is the administrator of this site',$this->plugin_domain);
676
- } else {
677
- $reg_member = __('is a registered member of my site',$this->plugin_domain);
678
- }
679
- $gravatar = '<img src="http://www.gravatar.com/avatar/' . md5 ( strtolower($email) ) . '.jpg" alt="' . $username . '" align="left" />';
680
- $panel = $gravatar . "<p class=\"cl_title\"><span class=\"cl_username\">$username</span> ".$reg_member."</p><p class=\"cl_bio\">$bio</p><p class=\"cl_clicks\"> <span class=\"cl_clicks_count\">$clickcount</span> ".__('Clicks on this link on this comment',$this->plugin_domain)."</p><p class=\"cl_links\">".$num_comments.' '.__('approved comments on this site',$this->plugin_domain).'<br>'.__('Some other posts I have commented on',$this->plugin_domain)."</p><p class=\"cl_links_list\">".implode('<br>',$appeared_on)."</p><p class=\"cl_posts\">".__('Some of my other posts',$this->plugin_domain)."</p><p class=\"cl_posts_list\">".implode('<br>',$my_other_posts)."</p>";
681
- $json = json_encode(array('panel'=>$panel));
682
- header ( "Content-Type: application/x-javascript; " );
683
- echo $json;
684
- exit;
685
- }
686
- // show panel for everyone else
687
- $comment = get_comment($cid);
688
- $msg = '';
689
- $bio= get_comment_author_url($cid);
690
- $name = get_comment_author($cid);
691
- $gravatar = '<img src="http://www.gravatar.com/avatar/' . md5 ( strtolower($email) ) . '.jpg" alt="' . $name . '" align="left" />';
692
- if(get_option('users_can_register') && $options['whogets'] == 'registered'){
693
- $msg = __('has not registered on this site',$this->plugin_domain);
694
- $bio = $options['unreg_user_text_panel'];
695
- }
696
- $panel = $gravatar . "<p class=\"cl_title\">
697
- <span class=\"cl_username\">".$comment->comment_author."</span> ".$msg."</p>
698
- <p class=\"cl_bio\">".$bio."</p>
699
- <p class=\"cl_clicks\"> <span class=\"cl_clicks_count\">$clickcount</span> ".__('Clicks on this link on this comment',$this->plugin_domain)."</p>
700
- <p class=\"cl_links\">".$num_comments.' '.__('approved comments on this site',$this->plugin_domain).
701
- '<br>'.__('Some other posts I have commented on',$this->plugin_domain)."</p>
702
- <p class=\"cl_links_list\">".implode('<br>',$appeared_on)."</p>";
703
- // dont show other links for non registered user to entice them to register
704
- //<p class=\"cl_posts\">".__('Some of my other posts',$this->plugin_domain)."</p>
705
- //<p class=\"cl_posts_list\">".implode('<br>',$my_other_posts)."</p>";
706
- $json = json_encode(array('panel'=>$panel));
707
- header ( "Content-Type: application/x-javascript; " );
708
- echo $json;
709
- exit;
710
- }
711
- /**
712
- * called by add_filter('comments_array
713
- * adds the link to the comments that are to be displayed
714
- * @param mixed $commentarray
715
- */
716
- function do_shortcode($commentarray){
717
- $isadminpage = false;
718
- $options= $this->get_options();
719
- if(!is_array($commentarray)){
720
- // if it's an array then it was called by comments_array filter,
721
- // otherwise it was called by comment_content (admin screen)
722
- // has it been done before?
723
- if(strpos($commentarray,'class="cluv"')){
724
- return $commentarray;
725
- }
726
- // make a fake array of 1 object so below treats the comment_content filter nicely for admin screen
727
- $temparray = array('comment_ID'=>get_comment_ID(),'comment_content'=>$commentarray,'comment_author'=>get_comment_author(), 'comment_author_email'=>get_comment_author_email());
728
- $tempobject = (object) $temparray;
729
- $commentarray = array($tempobject);
730
- $isadminpage = true;
731
- }
732
- // add link to comments (need to do it this way so thesis works with commentluv links, thesis wont use comment_text filter but it does get an array of comments)
733
- $new_commentarray = array();
734
- foreach($commentarray as $comment){
735
- $data = get_comment_meta($comment->comment_ID,'cl_data','true');
736
- $commentcontent = $comment->comment_content;
737
- // luvlink added?
738
- if($data && is_array($data)){
739
- if($data['cl_post_url'] != '' && $data['cl_post_title'] != ''){
740
- // luvlink was saved to meta, dofollow the link?
741
- $nofollow = ' rel="nofollow"';
742
- //$isreg = get_user_by_email($comment->comment_author_email);
743
- $isreg = get_user_by('email',$comment->comment_author_email);
744
- if($options['dofollow'] == 'everybody'){
745
- $nofollow = '';
746
- } elseif ($options['dofollow'] == 'registered' && $isreg){
747
- $nofollow = '';
748
- }
749
- // construct link
750
- $pclass = $data['cl_prem'] == 'p' ? ' p' : '';
751
- $ajaxnonce = wp_create_nonce($comment->comment_ID);
752
- $class = ' class="'.$ajaxnonce.' '.$comment->comment_ID.$pclass.'"';
753
- $luvlink = '<a'.$class.$nofollow.' href="'.$data['cl_post_url'].'">'.$data['cl_post_title'].'</a>';
754
- $search = array ('[name]', '[lastpost]','[type]' );
755
- $replace = array ($comment->comment_author, $luvlink,'blog post' );
756
- $prepend_text = $options ['comment_text'];
757
- $inserted = str_replace ( $search, $replace, $prepend_text );
758
- // check if author has a url. do not add the link if user has set to hide links for comments with no url
759
- $authurl = isset($comment->comment_author_url) ? $comment->comment_author_url : null;
760
- $showlink = true;
761
- if($authurl == '' && isset($options['hide_link_no_url']) && $options['hide_link_no_url'] == 'on'){
762
- $showlink = false;
763
- }
764
- // check link domain matches author url domain
765
- if(!isset($options['hide_link_no_url_match'])){
766
- $options['hide_link_no_url_match'] = 'nothing';
767
- }
768
- $authorurlarr = parse_url($authurl);
769
- $linkurlarr = parse_url($data['cl_post_url']);
770
- if($options['hide_link_no_url_match'] != 'nothing'){
771
- if($authorurlarr['host'] != $linkurlarr['host']){
772
- // link has different domain
773
- if($options['hide_link_no_url_match'] == 'on'){
774
- $showlink = false;
775
- }
776
- }
777
- }
778
- if($showlink){
779
- // construct string to be added to comment
780
- $commentcontent .= "\n<span class=\"cluv\">$inserted";
781
- // prepare heart icon if infopanel is on
782
- $hearticon = '';
783
- if($data['cl_prem'] == 'p' || $isreg) {
784
- // use PLUS heart for members
785
- $hearticon = 'plus';
786
- }
787
- if ($options ['infopanel'] == 'on') {
788
- $commentcontent .= '<span class="heart_tip_box"><img class="heart_tip '.$data['cl_prem'].' '.$comment->comment_ID.'" alt="My Profile" style="border:0" width="16" height="14" src="' . $this->plugin_url . 'images/littleheart'.$hearticon.'.gif"/></span>';
789
- }
790
- $commentcontent.= '</span>';
791
- }
792
- }
793
- }
794
- // store new content in this comments comment_content cell
795
- $comment->comment_content = $commentcontent;
796
- // fill new array with this comment
797
- $new_commentarray[] = $comment;
798
- }
799
- // admin page or public page?
800
- if($isadminpage){
801
- // is being called by comment_text filter so expecting just content
802
- return $commentcontent;
803
- } else {
804
- // called from comments_array filter so expecting array of objects
805
- return $new_commentarray;
806
- }
807
- }
808
- /**
809
- * called by do_ajax())
810
- * takes action when ajax request is made with URL from the comment form
811
- * send back 1 or 10 last posts depending on rules
812
- */
813
- function fetch_feed(){
814
- // check nonce
815
- //debugbreak();
816
- $options = $this->get_options();
817
- if(isset($options['use_nonce'])){
818
- $checknonce = check_ajax_referer('fetch',false,false);
819
- if(!$checknonce){
820
- die(' error! not authorized '.strip_tags($_REQUEST['_ajax_nonce']));
821
- }
822
- }
823
- if(!$_POST['url']){
824
- die('no url');
825
- }
826
- if(!defined('DOING_AJAX')){
827
- define('DOING_AJAX',true);
828
- }
829
- // try to prevent deprecated notices
830
- @ini_set('display_errors',0);
831
- @error_reporting(0);
832
- include_once(ABSPATH.WPINC.'/class-simplepie.php');
833
-
834
- $num = 1;
835
- $url = esc_url($_POST['url']);
836
- $orig_url = $url;
837
- // add trailing slash (can help with some blogs)
838
- if(!strpos($url,'?')){
839
- $url = trailingslashit($url);
840
- }
841
- // fetch 10 last posts?
842
- if((is_user_logged_in() && $options['whogets'] == 'registered') || (!is_user_logged_in() && $options['whogets'] == 'everybody')){
843
- $num = 10;
844
- } elseif($options['whogets'] == 'everybody') {
845
- $num = 10;
846
- } elseif(current_user_can('manage_options')){
847
- $num = 10;
848
- }
849
- // check if request is for the blog we're on
850
- if(strstr($url, home_url())){
851
- //DebugBreak();
852
- $posts = get_posts(array('numberposts'=>10));
853
- $return = array();
854
- $error = '';
855
- if($posts){
856
- foreach($posts as $post){
857
- $return[] = array('type'=>'blog','title'=>htmlspecialchars_decode(strip_tags($post->post_title)),'link'=>get_permalink($post->ID),'p'=>'u');
858
- }
859
- } else {
860
- $error = __('Could not get posts for home blog',$this->plugin_domain);
861
- }
862
- // check for admin only notices to add
863
- $canreg = get_option('users_can_register');
864
- $whogets = $options['whogets'];
865
- if(!$canreg && $whogets == 'registered'){
866
- $return[] = array('type'=>'message','title'=>__('Warning! You have set to show 10 posts for registered users but you have not enabled user registrations on your site. You should change the operational settings in the CommentLuv settings page to show 10 posts for everyone or enable user registrations',$this->plugin_domain),'link'=>'');
867
- }
868
- $response = json_encode(array('error'=>$error,'items'=>$return));
869
- header( "Content-Type: application/json" );
870
- echo $response;
871
- exit;
872
- }
873
- // get simple pie ready
874
- $rss = new SimplePie();
875
- if(!$rss){
876
- die(' error! no simplepie');
877
- }
878
- $rss->set_useragent('Commentluv /'.$this->version.' (Feed Parser; http://www.commentluv.com; Allow like Gecko) Build/20110502' );
879
- $rss->set_feed_url ( add_query_arg(array('commentluv'=>'true'),$url) );
880
- $rss->enable_cache ( FALSE );
881
- // fetch the feed
882
- $rss->init();
883
- $su = $rss->subscribe_url();
884
- $ferror = $rss->error();
885
- // try a fall back and add /?feed=rss2 to the end of url if the found subscribe url hasn't already got it
886
- // also try known blogspot feed location if this is a blogspot url
887
- if($ferror || strstr($ferror,'could not be found') && !strstr($su,'feed')){
888
- unset($rss);
889
- $rss = new SimplePie();
890
- $rss->set_useragent('Commentluv /'.$this->version.' (Feed Parser; http://www.commentluv.com; Allow like Gecko) Build/20110502' );
891
- $rss->enable_cache ( FALSE );
892
- // construct alternate feed url
893
- if(strstr($url,'blogspot')){
894
- $url = trailingslashit($url).'feeds/posts/default/';
895
- } else {
896
- $url = add_query_arg(array('feed'=>'atom'),$url);
897
- }
898
- $rss->set_feed_url($url);
899
- $rss->init();
900
- $ferror = $rss->error();
901
- if($ferror || stripos($ferror,'invalid')){
902
- $suburl = $rss->subscribe_url() ? $rss->subscribe_url() : $orig_url;
903
- unset($rss);
904
- $rss = new SimplePie();
905
- $rss->set_useragent('Commentluv /'.$this->version.' (Feed Parser; http://www.commentluv.com; Allow like Gecko) Build/20110502' );
906
- $rss->enable_cache ( FALSE );
907
- $rss->set_feed_url($orig_url);
908
- $rss->init();
909
- $ferror = $rss->error();
910
- // go back to original URL if error persisted
911
- if(stripos($ferror,'invalid')){
912
- //get raw file to show any errors
913
- @include_once(ABSPATH.WPINC.'/SimplePie/File.php');
914
- if(class_exists('SimplePie_File')){
915
- $rawfile = new SimplePie_File($suburl, $rss->timeout, 5, null, $rss->useragent, $rss->force_fsockopen);
916
- } elseif (class_exists($rss->file_class)){
917
- $rawfile = new $rss->file_class($suburl, $rss->timeout, 5, null, $rss->useragent, $rss->force_fsockopen);
918
- }
919
- if(isset($rawfile->body)){
920
- $rawfile = $rawfile->body;
921
- } else {
922
- $rawfile = __('Raw file could not be found',$this->plugin_domain);
923
- }
924
- }
925
- }
926
- }
927
- $rss->handle_content_type();
928
- $gen = $rss->get_channel_tags('','generator');
929
- $prem_msg = $rss->get_channel_tags('','prem_msg');
930
- $g = $num;
931
- $p = 'u';
932
- $meta = array();
933
- //DebugBreak();
934
- if($gen && strstr($gen[0]['data'],'commentluv')){
935
- $generator = $gen[0]['data'];
936
- $meta['generator'] = $generator;
937
- $pos=stripos($generator,'v=');
938
- if(substr($generator,$pos+2,1)=='3'){
939
- $g=15;
940
- $p='p';
941
- }
942
- }
943
- if($prem_msg){
944
- $prem_msg = $prem_msg[0]['data'];
945
- }
946
- //DebugBreak();
947
- $error = $rss->error();
948
- $meta['used_feed'] = $rss->subscribe_url();
949
- //DebugBreak();
950
- // no error, construct return json
951
- if(!$error){
952
-
953
- $arr = array();
954
-
955
- // save meta
956
- $meta['used_feed'] = $rss->subscribe_url ();
957
-
958
- $feed_items = $rss->get_items();
959
- foreach($feed_items as $item){
960
- //debugbreak();
961
- $type = 'blog';
962
- $itemtags = $item->get_item_tags('','type');
963
- if($itemtags){
964
- $type = $itemtags[0]['data'];
965
- }
966
- $arr[] = array('type'=>$type,'title'=>htmlspecialchars_decode(strip_tags($item->get_title())),'link'=>$item->get_permalink(),'p'=>$p);
967
- $g--;
968
- if($g < 1){
969
- break;
970
- }
971
- }
972
- // add message to unregistered user if set
973
- if(!is_user_logged_in() && $options['unreg_user_text'] && $options['whogets'] != 'everybody' && $p=='u'){
974
- if(get_option('users_can_register')){
975
- $arr[] = array('type'=>'message','title'=>$options['unreg_user_text'],'link'=>'');
976
- if(!strstr($options['unreg_user_text'],'action=register')){
977
- $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
978
- $arr[] = array('type'=>'message','title'=>$register_link,'link'=>'');
979
- }
980
- }
981
- if($options['whogets'] == 'registered' && get_option('users_can_regsiter')){
982
- $arr[] = array('type'=>'message','title'=>__('If you are registered, you need to log in to get 10 posts to choose from',$this->plugin_domain),'link'=>'');
983
- }
984
- }
985
- if($prem_msg){
986
- $arr[] = array('type'=>'alert','title'=>$prem_msg,'link'=>'');
987
- }
988
- $response = json_encode(array('error'=>'','items'=>$arr,'meta'=>$meta));
989
- } else {
990
- // had an error trying to read the feed
991
- $response = json_encode(array('error'=>$error,'meta'=>$meta,'rawfile'=>htmlspecialchars($rawfile)));
992
- }
993
- unset($rss);
994
- header( "Content-Type: application/json" );
995
- echo $response;
996
- exit;
997
- }
998
- /**
999
- * find number of approved comments in the past 14 days to have a commentluv link
1000
- * called in check_version
1001
- * since 2.90.8
1002
- * @return int
1003
- */
1004
- function get_numluv(){
1005
- global $wpdb;
1006
- $query = $wpdb->prepare('SELECT count(*) FROM '.$wpdb->commentmeta.' m JOIN '.$wpdb->comments.' c ON m.comment_id = c.comment_ID WHERE m.meta_key = %s AND c.comment_approved = %s AND c.comment_date > NOW() - INTERVAL 14 DAY','cl_data','1');
1007
- return intval($wpdb->get_var($query));
1008
- }
1009
- /** get_options
1010
- * This function sets default options and handles a reset to default options
1011
- * @param string $reset = 'no' - whether to return default settings
1012
- * return array
1013
- */
1014
- function get_options($reset = 'no') {
1015
- // see if we offer registration incentive
1016
- $register_link = '';
1017
- if(get_option('users_can_register')){
1018
- $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
1019
- }
1020
- // default values
1021
- $this->handle_load_domain ();
1022
- $default = array ('version'=>$this->version,'enable'=>'yes','enable_for'=>'both', 'default_on' => 'on', 'default_on_admin'=>'on',
1023
- 'badge_choice' => 'drop_down', 'badge_type'=>'default', 'link'=>'off','infopanel'=>'on', 'infoback'=>'white', 'infotext'=>'black',
1024
- 'comment_text'=>'[name] '.__('recently posted',$this->plugin_domain).'...[lastpost]', 'whogets'=>'registered', 'dofollow' => 'registered',
1025
- 'unreg_user_text'=>__('If you register as a user on my site, you can get your 10 most recent blog posts to choose from in this box.',$this->plugin_domain).' '.$register_link,
1026
- 'unreg_user_text_panel'=>__('If this user had registered to my site then they could get 10 last posts to choose from when they comment and you would be able to see a list of their recent posts in this panel',$this->plugin_domain),'use_nonce'=>'on',
1027
- 'template_insert'=>'','minifying'=>'','api_url'=>admin_url('admin-ajax.php'),'author_name'=>'author','email_name'=>'email','url_name'=>'url','comment_name'=>'comment',
1028
- 'hide_link_no_url'=>'nothing','hide_link_no_url_match'=>'nothing');
1029
- $options = get_option ( $this->db_option, $default);
1030
- // return the options
1031
- if($reset == 'yes'){
1032
- return $default;
1033
- }
1034
- if(!$options['api_url']){
1035
- $options['api_url'] = admin_url('admin-ajax.php');
1036
- }
1037
- if(!$options['enable']){
1038
- $options['enable'] = 'yes';
1039
- }
1040
-
1041
- return $options;
1042
- }
1043
- /** handle_load_domain
1044
- * This function loads the localization files required for translations
1045
- * It expects there to be a folder called /lang/ in the plugin directory
1046
- * that has all the .mo files
1047
- */
1048
- function handle_load_domain() {
1049
- // get current language
1050
- $locale = get_locale ();
1051
- // locate translation file
1052
- $mofile = WP_PLUGIN_DIR . '/' . plugin_basename ( dirname ( __FILE__ ) ) . '/lang/' . $this->plugin_domain . '-' . $locale . '.mo';
1053
- // load translation
1054
- load_textdomain ( $this->plugin_domain, $mofile );
1055
- }
1056
- /** init
1057
- * This function registers styles and scripts
1058
- */
1059
- function init(){
1060
- wp_register_style( 'commentluv_style',$this->plugin_url.'css/commentluv.css' , $this->version);
1061
- wp_register_script( 'commentluv_script', $this->plugin_url.'js/commentluv.js',array('jquery'),$this->version );
1062
- }
1063
- /** install
1064
- * This function is called when the plugin activation hook is fired when
1065
- * the plugin is first activated or when it is auto updated via admin.
1066
- * use it to make any changes needed for updated version or to add/check
1067
- * new database tables on first install.
1068
- */
1069
- function install(){
1070
- $options = $this->get_options();
1071
- if(!$installed_version = get_option('cl_version')){
1072
- // no installed version yet, set to version that was before big change
1073
- $installed_version = 2.8;
1074
- } else {
1075
- // convert existing version to php type version number
1076
- $installed_version = $this->php_version($installed_version);
1077
- }
1078
- // for version before 2.9
1079
- if(version_compare($installed_version,'2.9','<')){
1080
- // make any changes to this new versions options if needed and update
1081
- update_option($this->db_option,$this->get_options('yes'));
1082
- }
1083
- // new addition to technical settings after 2.90.1 release
1084
- if(version_compare($installed_version,'2.9.0.1','<')){
1085
- $options['api_url'] = admin_url('admin-ajax.php');
1086
- $options['enable'] = 'yes';
1087
- update_option($this->db_option,$options);
1088
- }
1089
- // new check for use_nonce
1090
- if(version_compare($installed_version,'2.94','<')){
1091
- $options['use_nonce'] = 'on';
1092
- update_option($this->db_option,$options);
1093
- }
1094
- // update cl_version in db
1095
- if($this->php_version($this->version) != $installed_version){
1096
- update_option('cl_version',$this->version);
1097
- }
1098
- // has the comment meta table?
1099
- global $wpdb;
1100
- $query = $wpdb->prepare("SHOW tables LIKE %s",$wpdb->commentmeta);
1101
- $dbtable = $wpdb->get_var($query);
1102
- //$o['dbtable'] = $dbtable;
1103
- if(!$dbtable){
1104
- add_action('admin_notices',create_function('','echo "<div class=\"error\">'.__('Your Wordpress install is missing the <strong>wp_commentmeta</strong> table!',$pd).'<br>'.__(' CommentLuv cannot work without this table please see this wordpress forum post to learn how to add one ->',$pd).'<a target=\"_blank\" href=\"http://wordpress.org/support/topic/wp_commentmeta-table-a39xxxx2_blogwp_commentmeta-doesnt-exist?replies=7#post-1378281\">'.__('Missing wp_commentmeta table',$pd).'</a></div>";'));
1105
- }
1106
- }
1107
- /**
1108
- * helper function called by mulitple functions
1109
- * used to determine if commentluv is enabled
1110
- */
1111
- function is_enabled(){
1112
- $options = $this->get_options();
1113
- // see if we need to add here or not
1114
- if(($options['enable_for'] == 'posts' && is_page()) || ($options['enable_for'] == 'pages' && !is_page())){
1115
- return false;
1116
- }
1117
- if($options['enable'] != 'yes'){
1118
- return false;
1119
- }
1120
- return true;
1121
- }
1122
- /**
1123
- * called by apply_filter('kindergarten_html
1124
- * Used to clean $input to only allow a kiddy set of html tags
1125
- *
1126
- * @param string $input - the string to be cleaned
1127
- * @return string
1128
- */
1129
- function kindergarten_html($input){
1130
- $allowedtags = array(
1131
- 'h1' => array(),
1132
- 'br' => array(),
1133
- 'a' => array('href' => array(),'title' => array(),'rel' => array(),'target'=>array(), 'class'=>array()),
1134
- 'small' =>array(),
1135
- 'p' =>array( 'class'=>array()),
1136
- 'strong' => array(),
1137
- 'img' => array('src' => array(),'alt' => array(),'width' => array(),'height' => array(),'align'=> array()),
1138
- 'span' => array('class'=>array())
1139
- );
1140
- return wp_kses($input,$allowedtags);
1141
- }
1142
- /**
1143
- * Ajax handler for the subscribe button on the settings page.
1144
- * called by add_action ( 'wp_ajax_notify_signup'
1145
- */
1146
- function notify_signup(){
1147
- //DebugBreak();
1148
- global $current_user;
1149
- $email = $current_user->user_email;
1150
- $firstname = $current_user->first_name;
1151
- $url = 'http://contact.commentluv.com/subscribe';
1152
- $list = 'pdYIXefvLNL38bE3fDcB3Q';
1153
- // sendy
1154
- if(!$firstname){
1155
- $firstname = $current_user->user_nicename;
1156
- }
1157
- $response = wp_remote_post( $url, array(
1158
- 'method' => 'POST',
1159
- 'timeout' => 45,
1160
- 'redirection' => 5,
1161
- 'httpversion' => '1.0',
1162
- 'blocking' => true,
1163
- 'headers' => array(),
1164
- 'body' => array( 'name' => $firstname, 'email' => $email ,'list'=>$list),
1165
- 'cookies' => array()
1166
- )
1167
- );
1168
- $return = array('success'=>true,'email'=>$email);
1169
- // return response
1170
- $response = json_encode($return);
1171
- // response output
1172
- header( "Content-Type: application/json" );
1173
- echo $response;
1174
- // IMPORTANT: don't forget to "exit"
1175
- exit;
1176
- }
1177
- /** options_sanitize
1178
- * This is the callback function for when the settings get saved, use it to sanitize options
1179
- * it is called by the callback setting of register_setting in admin_init
1180
- * @param mixed $options - the options that were POST'ed
1181
- * return mixed $options
1182
- */
1183
- function options_sanitize($options){
1184
- //DebugBreak();
1185
- $old_options = $this->get_options();
1186
- // if not enabled, only save that so other settings remain unchanged
1187
- if($options['enable'] == 'no'){
1188
- $old_options['enable'] = 'no';
1189
- return $old_options;
1190
- }
1191
- // check for reset
1192
- if(isset($options['reset'])){
1193
- return $this->get_options('yes');
1194
- }
1195
- // if on multisite and this isnt super admin saving,
1196
- // only allow kindergarten html.
1197
- if(is_multisite() && !is_super_admin()){
1198
- foreach($options as $key => $option){
1199
- $options[$key] = apply_filters('kindergarten_html',$option);
1200
- }
1201
- }
1202
- // add error notices if any
1203
- $canreg = get_option('users_can_register');
1204
- if($options['whogets']=='registered' && !$canreg){
1205
- add_settings_error('whogets','whogets',__('Warning! You have set to show 10 posts for registered users but you have not enabled user registrations on your site. You should change the operational settings in the CommentLuv settings page to show 10 posts for everyone or enable user registrations',$this->plugin_domain),'error');
1206
- }
1207
- return $options;
1208
- }
1209
- /**
1210
- * converts a string into a php type version number
1211
- * eg. 2.81.2 will become 2.8.1.2
1212
- * used to prepare a number to be used with version_compare
1213
- *
1214
- * @param mixed $string - the version to be converted to php type version
1215
- * @return string
1216
- */
1217
- function php_version($string){
1218
- if(empty($string)){
1219
- return;
1220
- }
1221
- $version = str_replace('.','',$string);
1222
- $std = array();
1223
- for($i=0; $i < strlen($version); $i++){
1224
- $std[] = $version[$i];
1225
- }
1226
- $php_version = implode('.',$std);
1227
- return $php_version;
1228
- }
1229
- /** commentluv_action
1230
- * This function adds a link to the settings page for the plugin on the plugins listing page
1231
- * it is called by add filter plugin_action_links
1232
- * @param $links - the links being filtered
1233
- * @param $file - the name of the file
1234
- * return array - the new array of links
1235
- */
1236
- function plugin_action_link($links, $file) {
1237
- $this_plugin = plugin_basename ( __FILE__ );
1238
- if ($file == $this_plugin) {
1239
- $links [] = "<a href='options-general.php?page={$this->slug}'>" . __ ( 'Settings', $this->plugin_domain ) . "</a>";
1240
- }
1241
- return $links;
1242
- }
1243
- /**
1244
- * Detects if a commentluv api or plugin is requesting a feed
1245
- * and sends back an xml feed of the post titles and links that were found for the query
1246
- * called by add_filter('found_posts' so we always have the posts found for the requested category/author/tag/ etc
1247
- * @param (int) $foundposts - the number of posts that were found
1248
- * @param (obj) $object - the query object
1249
- * @return $foundposts - need to return this if the request is not from a commentluv api or plugin
1250
- *
1251
- * deprecated in 2.90.9.9 due to new 3.4 wp query code messing up with static homepages.
1252
- * have to use just 10 recent posts, does not detect author or category urls now. (no one uses them!)
1253
- */
1254
- function send_feed($foundposts,$object){
1255
- if(headers_sent() == true){
1256
- return $foundposts;
1257
- }
1258
- $options = $this->get_options();
1259
- // check if detection disabled
1260
- if(isset($options['disable_detect']) && $options['disable_detect'] == 'on'){
1261
- return $foundposts;
1262
- }
1263
- if($this->is_commentluv_request === true){
1264
- // is commentluv useragent (set in init action)
1265
- // get rid of any output (prevents some themes on some hosts from outputting code before commentluv can show xml feed)
1266
- ob_clean();
1267
- }
1268
- $error = false;
1269
- if($foundposts < 1 && ! $object->is_home){
1270
- $error = true;
1271
- }
1272
- $enabled = $options['enable'];
1273
-
1274
- // General checking
1275
- if (preg_match("/Commentluv/i", $_SERVER['HTTP_USER_AGENT'])) {
1276
- if($object->is_home){
1277
- // we're on the home page so just get the last 10 posts (prevents a slider or other featured posts widget from making the object full of the featured posts)'
1278
- wp_reset_query();
1279
- $query = new WP_Query();
1280
- remove_filter('found_posts',array(&$this,'send_feed'),-1,2);
1281
- $object->posts = $query->query('showposts=10&post_type=post');
1282
- }
1283
- $feed = '<?xml version="1.0" encoding="'.get_bloginfo('charset').'" ?>
1284
- <rss version="2.0">
1285
- <channel>
1286
- <title><![CDATA['. get_bloginfo('title') .']]></title>
1287
- <link>'. home_url() .'</link>
1288
- <description><![CDATA['. get_bloginfo('description') .']]></description>
1289
- <language>'.get_bloginfo('language').'</language>
1290
- <generator>commentluv?v='.$this->version.'</generator>
1291
- <commentluv>'.$enabled.'</commentluv>
1292
- <success>'.$error.'</success>';
1293
- if($object->posts){
1294
- foreach($object->posts as $post){
1295
- $feed .= '<item><title><![CDATA['.get_the_title($post->ID).']]></title>
1296
- <link>'.get_permalink($post->ID).'</link>
1297
- <type>blog</type>
1298
- </item>';
1299
- }
1300
- } else {
1301
- $feed .= '<item><title>'.__('No Posts Were Found!',$pd).'</title>
1302
- <link>'.get_permalink($post->ID).'</link>
1303
- </item>';
1304
- }
1305
- $feed .= '</channel></rss>';
1306
- header("Content-Type: application/xml; charset=".get_bloginfo('charset'));
1307
- echo $feed;
1308
- exit;
1309
- }
1310
- return $foundposts;
1311
- }
1312
- /** send back a feed when another commentluv is asking
1313
- * called by add_action(template_redirect) in detect_useragent
1314
- *
1315
- */
1316
- function send_feed_file(){
1317
- // /debugbreak();
1318
- $options = $this->get_options();
1319
- $postquery = array('numberposts'=>10,'post_type'=>'post');
1320
- if(is_category()){
1321
- $cat = get_query_var('cat');
1322
- $postquery['category']=$cat;
1323
- }
1324
- if(is_author()){
1325
- $author = get_query_var('author');
1326
- $postquery['author'] = $author;
1327
- }
1328
- if(is_tag()){
1329
- $tag = get_query_var('tag');
1330
- $postquery['tag'] = $tag;
1331
- }
1332
- $posts = get_posts($postquery);
1333
- $enabled = $this->is_enabled();
1334
- $error = 'false';
1335
- if(sizeof($posts) < 1){
1336
- $error = 'true';
1337
- }
1338
- $feed = '<?xml version="1.0" encoding="'.get_bloginfo('charset').'" ?>'.
1339
- '<rss version="2.0">'.
1340
- '<channel>'.
1341
- '<title><![CDATA['. get_bloginfo('title') .']]></title>'.
1342
- '<link>'. get_bloginfo('url') .'</link>'.
1343
- '<description><![CDATA['. get_bloginfo('description') .']]></description>'.
1344
- '<language>'.get_bloginfo('language').'</language>'.
1345
- '<generator>commentluv?v='.$this->version.'</generator>'.
1346
- '<commentluv>'.$enabled.'</commentluv>'.
1347
- '<success>'.$error.'</success>';
1348
- if(is_array($posts)){
1349
- foreach($posts as $post){
1350
- $title = get_the_title($post->ID);
1351
- //$feed .= '<item><title>'.strip_tags($title).'</title>'.
1352
- $feed .= '<item><title><![CDATA['.$title.']]></title>'.
1353
- '<link>'.get_permalink($post->ID).'</link>'.
1354
- '<type>blog</type>'.
1355
- '</item>';
1356
- }
1357
- } else {
1358
- $feed .= '<item><title>'.__('No Posts Were Found!',$pd).'</title>'.
1359
- '<link>'.get_permalink($post->ID).'</link>'.
1360
- '</item>';
1361
- }
1362
- $feed .= '</channel></rss>';
1363
- ob_end_clean();
1364
- // force utf characters
1365
- if(isset($options['utf8']) && $options['utf8'] == 'on'){
1366
- // do nothing if set to disable utf8 encoding
1367
- } else {
1368
- // $feed = utf8_encode($feed); // removing this for now (2.94.7+)
1369
- }
1370
- header("Content-Type: application/atom+xml; charset=".get_bloginfo('charset'));
1371
- echo $feed;
1372
- exit;
1373
-
1374
- }
1375
- /**
1376
- * called by __construct
1377
- * used to setup hooks and filters for enabled plugin
1378
- */
1379
- function setup_hooks(){
1380
- add_action ( 'comment_form',array(&$this,'add_fields')); // add fields to form
1381
- add_action ( 'wp_print_styles',array(&$this,'add_style')); // add style
1382
- add_action ( 'template_redirect',array(&$this,'add_script')); // add commentluv script
1383
- add_action ( 'admin_print_scripts-edit-comments.php', array (&$this, 'add_removeluv_script') ); // add the removeluv script to admin page
1384
- add_action ( 'wp_footer',array(&$this,'add_footer')); // add localize to footer
1385
-
1386
- add_action ( 'wp_insert_comment', array (&$this, 'comment_posted'),1,2); // add member id and other data to comment meta priority 1, 2 vars
1387
- if(!is_admin()){
1388
- add_filter ( 'comments_array', array (&$this, 'do_shortcode' ), 1 ); // add last blog post data to comment content
1389
- } else {
1390
- add_filter ( 'comment_text', array (&$this, 'do_shortcode' ), 1 ); // add last blog post data to comment content on admin screen
1391
- }
1392
- add_filter ( 'comment_row_actions', array (&$this,'add_removeluv_link')); // adds a link to remove the luv from a comment on the comments admin screen
1393
- }
1394
- /**
1395
- * called by add_action('admin_notices in admin_init()
1396
- * Used to show a notice if there is a new version of CommentLuv available
1397
- */
1398
- function show_upgrade_notice(){
1399
- $options = $this->get_options();
1400
- $update_url = wp_nonce_url('update.php?action=upgrade-plugin&amp;plugin=commentluv%2Fcommentluv.php', 'upgrade-plugin_commentluv/commentluv.php');
1401
- echo '<div id="clupgrade" class="update-nag">';
1402
- if($options['upgrade_message']){
1403
- echo $options['upgrade_message'];
1404
- $details_link = '<br /><a href="'.admin_url().'plugin-install.php?tab=plugin-information&amp;plugin=commentluv&amp;TB_iframe=true&amp;width=640&amp;height=350" class="thickbox" title="commentluv"> View new version details</a>';
1405
- printf( __('%s or <a href="%s">update now</a>.', $this->plugin_domain), $details_link, $update_url ) ;
1406
- } else {
1407
- echo __('There is a new version of Commentluv available, please upgrade by visiting this site',$this->plugin_domain);
1408
- echo '<br><a href="http://www.commentluv.com" target="_blank">www.commentluv.com</a>';
1409
- }
1410
- //echo '<span style="float:right"><a href="'.admin_url('options-general.php?page='.$this->slug.'&dismiss=true').'">'.__('Dismiss notice',$this->plugin_domain).'</a></span>';
1411
- echo '</div>';
1412
- }
1413
-
1414
- /** options_page
1415
- * This function shows the page for saving options
1416
- * it is called by add_options_page
1417
- * You can echo out or use further functions to display admin style widgets here
1418
- */
1419
- function options_page(){
1420
- $o = $this->get_options();
1421
- $dbo = $this->db_option;
1422
- $pd = $this->plugin_domain;
1423
- $badges = array('default_image'=>'CL91_default.png','default'=>'CL91_default.png','white'=>'CL91_White.gif','black'=>'CL91_Black.gif','none'=> 'nothing.gif');
1424
- //DebugBreak();
1425
- // remove notice if requested
1426
- if(isset($_GET['dismiss'])){
1427
- unset($o['upgrade']);
1428
- if(array_key_exists('upgrade_message',$o)){
1429
- unset($o['upgrade_message']);
1430
- }
1431
- update_option($this->db_option,$o);
1432
- echo '<script>jQuery("#clupgrade").hide()</script>';
1433
- }
1434
- ?>
1435
- <div class="wrap">
1436
- <h2><?php _e('CommentLuv Settings v',$this->plugin_domain);?><?php echo $this->version;?></h2>
1437
- <div id="poststuff" style="margin-top:10px; ">
1438
- <div id="mainblock" style="float: left; width:78%">
1439
- <form method="post" action="options.php">
1440
- <?php settings_fields( 'commentluv_options_group' ); // the name given in admin init
1441
- // after here, put all the inputs and text fields needed
1442
- ?>
1443
- <div class="dbx-content">
1444
- <table class="widefat">
1445
- <thead>
1446
- <tr><th scope="col"><?php _e('Important!',$pd);?></th><th><?php _e('Subscription Information',$pd);?></th></tr>
1447
- </thead>
1448
- <tbody>
1449
- <tr>
1450
- <td width="250">
1451
- <h2 style="margin: 0 0 10px 0;"><?php _e('CommentLuv 3.0 Premium is here!',$pd);?> <a style="font-size:0.8em" title="Premium has some excellent features! try it out today. Full 30 day gaurantee" target="_blank" href="http://ql2.me/upgradetopremium">Upgrade to Premium</a></h2>
1452
- <img align="left" src="<?php echo $this->plugin_url;?>images/privacy-guarantee.png"/><?php _e('I promise not to sell your details or send you spam. You will ONLY receive emails about plugin updates and the 10 week free course.',$pd);?>
1453
- </td>
1454
- <td>
1455
- <p><?php _e('Do you like CommentLuv? How about an even better version with much more control over dofollow and some awesome social enticements that will make your posts go viral by offering your readers more choice of posts if they +1, Like or tweet your post? Get CommentLuv Premium Today! Free plugin and 10 week blogging course delivered by email. (10 week course is free of charge,it is no obligation premium content. It was supposed to be a premium product but I decided to give it away for free. (see why in the first email).)',$pd);?></p>
1456
- <?php
1457
- if(isset($o['subscribed'])){
1458
- echo '<div class="submit">'.__('You have already subscribed, if you have not received the verification within 12 hours, please click the button to resend or try the form at',$pd).' <a target="_blank" href="http://www.commentluv.com/">www.commentluv.com</a><br><input style="margin:0 auto; display: block;" type="button" id="cl_notify" value="'.__('Resend Verification',$pd).'"/></div>';
1459
- } else {
1460
- echo '<div class="submit" style=" background-color: green; padding-left: 5px; padding-right: 5px; border-radius: 15px; -moz-border-radius: 15px; text-align: center;"><input style="margin: 0 auto; display:block" id="cl_notify" type="button" name="cl_notify" value="'.__('Click for a special offer!',$pd).'" /></div>';
1461
- }
1462
- ?>
1463
- <div id="notify_message"></div>
1464
- </td>
1465
- </tr>
1466
- <tr>
1467
- <td colspan="2">
1468
- <?php _e('<b>Are you getting targeted by spammers?</b> CommentLuv links are valuable which is why it promotes comments but some nasty spammers try to take advantage of this by leaving spam just to get the link. Don\'t worry, there is answer!... you can get CommentLuv Premium which has advanced anti-spam features which has been proven to almost eliminate spam on users blogs. You can upgrade by clicking the link above. <p><b>Not ready to buy premium yet?</b> that\'s ok too! Why not try GASP which is a lite version of the anti spam plugin that CommentLuv Premium uses. You can get it for FREE by searching for GASP in your "add new" section of your plugins page in your dashboard.',$pd);?>
1469
- </td>
1470
- </tr>
1471
- </tbody>
1472
- </table>
1473
-
1474
-
1475
- <br/>
1476
-
1477
-
1478
- <table class="widefat">
1479
- <thead>
1480
- <tr><th><?php _e('Primary Setting',$pd);?></th><th colspan="3"></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th></tr>
1481
- </thead>
1482
- <tbody>
1483
- <tr>
1484
- <td colspan="2" style="width: 40%; vertical-align: middle; text-align: center; font-size: 1.3em; font-weight: bolder;"><label for="<?php echo $dbo;?>[enable]"><?php _e('Enable CommentLuv?',$pd);?></label></td>
1485
- <td style="width:20%; vertical-align: middle; font-size: 1.3em;"><input class="clenable" type="radio" name="<?php echo $dbo;?>[enable]" value="yes" <?php checked($o['enable'],'yes');?>/><?php _e('Yes',$pd);?></td>
1486
- <td style="width:20%; vertical-align: middle; font-size: 1.3em;"><input class="clenable" type="radio" name="<?php echo $dbo;?>[enable]" value="no" <?php checked($o['enable'],'no');?>/><?php _e('No',$pd);?></td>
1487
- <td style="text-align: center; border: 2px dotted;"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>primarysettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1488
- </tr>
1489
- <tr class="ifenable">
1490
- <td style="text-align: center;" colspan="5">
1491
- <input type="radio" name="<?php echo $dbo;?>[enable_for]" value="posts" <?php checked($o['enable_for'],'posts');?>/><?php _e('On Posts',$pd);?>
1492
- <input style="margin-left: 100px;" type="radio" name="<?php echo $dbo;?>[enable_for]" value="pages" <?php checked($o['enable_for'],'pages');?>/><?php _e('On Pages',$pd);?>
1493
- <input style="margin-left: 100px;" type="radio" name="<?php echo $dbo;?>[enable_for]" value="both" <?php checked($o['enable_for'],'both');?>/><?php _e('On Both',$pd);?>
1494
- </td>
1495
- </tr>
1496
- <tr class="ifenable">
1497
- <td style="text-align: center;" colspan="2">
1498
- <input type="checkbox" name="<?php echo $dbo;?>[default_on]" <?php if(isset($o['default_on'])) checked($o['default_on'],'on');?> value="on"/> <label for="<?php echo $dbo;?>[default_on]"><?php _e('On by default?',$pd);?></label>
1499
- </td>
1500
- <td></td>
1501
- <td style="text-align: center;" colspan="2">
1502
- <input type="checkbox" name="<?php echo $dbo;?>[default_on_admin]" <?php if(isset($o['default_on_admin'])) checked($o['default_on_admin'],'on');?> value="on"/><label for="<?php echo $dbo;?>[default_on_admin]"> <?php _e('On for admin?',$pd);?></label>
1503
- </td>
1504
- </tr>
1505
- </tbody>
1506
- </table>
1507
-
1508
-
1509
- <br>
1510
-
1511
-
1512
- <table class="widefat ifenable display-settings">
1513
- <thead>
1514
- <tr><th><?php _e('Appearance',$pd);?></th><th colspan="3"></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th></tr>
1515
- </thead>
1516
- <tbody>
1517
- <tr>
1518
- <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Badge',$pd);?></label></h3></td>
1519
- <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Custom Image URL',$pd);?></label></h3></td>
1520
- <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Use Text',$pd);?></label></h3></td>
1521
- <td></td>
1522
- <td></td>
1523
- </tr>
1524
- <tr>
1525
- <td>
1526
- <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="drop_down" <?php checked($o['badge_choice'],'drop_down');?>/>
1527
- <select id="badge_type" name="<?php echo $dbo;?>[badge_type]">
1528
- <option value="default_image" <?php selected($o['badge_type'],'default_image');?>><?php _e('Default',$pd);?></option>
1529
- <option value="white" <?php selected($o['badge_type'],'white');?>><?php _e('White',$pd);?></option>
1530
- <option value="black" <?php selected($o['badge_type'],'black');?>><?php _e('Black',$pd);?></option>
1531
- <option value="none" <?php selected($o['badge_type'],'none');?>><?php _e('None',$pd);?></option>
1532
- </select>
1533
-
1534
- <p style="margin: 8px 0px 0px 8px;"><img id="display_badge" style="border: 1px solid #000; padding: 3px;" src="<?php echo $this->plugin_url;?>images/<?php echo $badges[$o['badge_type']];?>"/></p>
1535
- </td>
1536
- <td>
1537
- <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="custom" <?php checked($o['badge_choice'],'custom');?>/>
1538
- <input type="text" name="<?php echo $dbo;?>[custom_image_url]" value="<?php if(isset($o['custom_image_url'])) echo $o['custom_image_url'];?>"/>
1539
- <?php
1540
- if(isset($o['custom_image_url']) && $o['custom_image_url'] != ''){
1541
- // show image
1542
- echo '<p style="margin: 8px 0px 0px 8px;"><img id="custom_badge" style="border: 1px solid #000; padding: 3px;" src="'.$o['custom_image_url'].'"/></p>';
1543
- } ?>
1544
- </td>
1545
- <td>
1546
-
1547
- <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="text" <?php checked($o['badge_choice'],'text');?>/>
1548
- <input type="text" name="<?php echo $dbo;?>[badge_text]" value="<?php if(isset($o['badge_text'])) echo $o['badge_text'];?>"/>
1549
- <p style="margin: 8px 0px 0px 8px;"><input type="checkbox" name="<?php echo $dbo;?>[link]" value="on" <?php if(isset($o['link'])) checked($o['link'],'on');?>/> <label for="<?php echo $dbo;?>[link]"><?php _e('Link to Commentluv?',$pd);?></label>
1550
- </td>
1551
- <td></td>
1552
- <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>appearancesettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1553
- </tr>
1554
-
1555
- <tr>
1556
- <td><br><input type="checkbox" name="<?php echo $dbo;?>[infopanel]" <?php checked($o['infopanel'],'on');?> value="on"/><label for="<?php echo $dbo;?>[infopanel]"> <?php _e('Enable info panel?',$pd);?></label></td>
1557
- <td><label for="<?php echo $dbo;?>[infoback]"><?php _e('Info panel background color',$pd);?></label><br><input type="text" size="6" name="<?php echo $dbo;?>[infoback];?>" value="<?php echo $o['infoback'];?>"/></td>
1558
- <td><label for="<?php echo $dbo;?>[infotext]"><?php _e('Info panel text color',$pd);?></label><br><input type="text" size="6" name="<?php echo $dbo;?>[infotext];?>" value="<?php echo $o['infotext'];?>"/></td>
1559
- <td></td>
1560
- <?php
1561
- $tdstyle = '"border: 1px solid #dfdfdf; vertical-align: middle; text-align: center; background-color: '.$o['infoback'].'"';
1562
- $spanstyle = '"color: '.$o['infotext'].'"';
1563
- ?>
1564
- <td style=<?php echo $tdstyle;?>><span style=<?php echo $spanstyle;?>><?php _e('Example text and background color',$pd);?></span></td>
1565
- </tr>
1566
- </tbody>
1567
- </table>
1568
-
1569
- <br>
1570
-
1571
- <table class="widefat ifenable messages">
1572
- <thead>
1573
- <tr>
1574
- <th colspan="2"><?php _e('Messages',$pd);?></th><th scope="col"></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1575
-
1576
- </tr>
1577
- </thead>
1578
- <tbody>
1579
- <tr>
1580
- <td colspan="2">
1581
- <label for="<?php echo $dbo;?>[comment_text]"><?php _e('Text to be displayed in the comment',$pd);?></label>
1582
- <br><input type="text" style="width: 95%" name="<?php echo $dbo;?>[comment_text]" value="<?php echo $o['comment_text'];?>"/>
1583
- </td>
1584
- <td style="border: 1px dashed #dfdfdf;"><?php _e('[name] = The users name',$this->plugin_domain);?><br><?php _e('[lastpost] = The last blog post link',$this->plugin_domain);?></td>
1585
- <td>&nbsp;</td>
1586
- <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>messagessettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1587
- </tr>
1588
- <tr>
1589
- <td colspan="3">
1590
-
1591
- <?php _e('Message for unregistered user in the drop down box',$pd);?>
1592
- <br>(<?php _e('Message will not be shown if you do not have registrations enabled',$this->plugin_domain);?>)
1593
- <br><textarea rows="5" style="width: 95%" name="<?php echo $dbo;?>[unreg_user_text]"><?php echo $o['unreg_user_text'];?></textarea>
1594
- <?php
1595
- if(get_option('users_can_register')){
1596
- _e('Your register link code',$pd);
1597
- echo '<br>';
1598
- _e('(this will be automatically added if you have not added it yourself to the textarea above)',$pd);
1599
- $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
1600
- echo ' : <input style="width:95%" type="text" value="'.htmlspecialchars($register_link).'" disabled/>';
1601
- }
1602
- ?>
1603
- </td>
1604
- <td colspan="2" style="width:125px;">
1605
- <?php // show warning if registration is not enabled
1606
- if(!get_option('users_can_register')){
1607
- echo '<div style="border: 2px dashed red;">';
1608
- _e('You have NOT set your blog to allow registrations, you can do that in Settings/General',$pd);
1609
- echo ' <a href="'.admin_url('options-general.php').'">'.__('here',$pd).'</a>';
1610
- echo '</div>';
1611
- }
1612
- ?>
1613
- </td>
1614
- </tr>
1615
- <tr>
1616
- <td colspan="3">
1617
- <?php _e('Message for unregistered user in the info panel',$pd);?>
1618
- <br>(<?php _e('Message will not be shown if you do not have registrations enabled',$this->plugin_domain);?>)
1619
- <br><textarea rows="5" style="width:95%;" name="<?php echo $dbo;?>[unreg_user_text_panel]"><?php echo $o['unreg_user_text_panel'];?></textarea>
1620
- </td>
1621
- <td></td>
1622
- <td></td>
1623
- </tr>
1624
- </tbody>
1625
- </table>
1626
-
1627
- <br>
1628
-
1629
- <table class="widefat ifenable operational-settings">
1630
- <thead>
1631
- <tr>
1632
- <th colspan="2"><?php _e('Operational Settings',$pd);?></th><th scope="col"></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1633
-
1634
- </tr>
1635
- </thead>
1636
- <tbody>
1637
- <tr>
1638
- <td colspan="4">
1639
- <?php _e('Who to give 10 last posts to choose from when they comment?',$pd);?>
1640
- <p><input type="radio" name="<?php echo $dbo;?>[whogets]" value="registered" <?php checked($o['whogets'],'registered');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Only Registered Members',$pd);?></label>
1641
- <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[whogets]" value="everybody" <?php checked($o['whogets'],'everybody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Everybody',$pd);?></label>
1642
- <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[whogets]" value="nobody" <?php checked($o['whogets'],'nobody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Nobody',$pd);?></label>
1643
-
1644
- </td>
1645
- <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>operationalsettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1646
- </tr>
1647
- <tr>
1648
- <td colspan="5">
1649
- <?php _e('Whose links should be dofollow?',$pd);?>
1650
- <p><input type="radio" name="<?php echo $dbo;?>[dofollow]" value="registered" <?php checked($o['dofollow'],'registered');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Only Registered Members Links',$pd);?></label>
1651
- <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[dofollow]" value="everybody" <?php checked($o['dofollow'],'everybody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Everybody gets dofollow links',$pd);?></label>
1652
- <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[dofollow]" value="nobody" <?php checked($o['dofollow'],'nobody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Nobody gets dofollow links',$pd);?></label>
1653
- </td>
1654
- </tr>
1655
- </tbody>
1656
- </table>
1657
-
1658
- <br>
1659
-
1660
- <table class="widefat ifenable technical" style="border: 3px solid red">
1661
- <thead>
1662
- <tr>
1663
- <th colspan="2"><?php _e('Technical Settings',$pd);?></th><th scope="col"><span id="opentech" style="color: blue; cursor: pointer;"><?php _e('Click to open technical settings',$pd);?></span></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1664
-
1665
- </tr>
1666
- </thead>
1667
- <tbody id="techbody" style="display:none">
1668
- <tr>
1669
- <td colspan="4">
1670
- <h3><?php _e('Please check the help video for this section before changing settings',$pd);?></h3>
1671
- <?php _e('In most cases, you will NOT need to change the settings in this box unless you have a custom comment form, template or you are using minifying or caching plugins',$pd);?>
1672
- </td>
1673
- <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>technicalsettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1674
- </tr>
1675
- <tr>
1676
- <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Compatibility',$pd);?></td>
1677
- </tr>
1678
- <tr>
1679
- <td colspan="2">
1680
- <input type="checkbox" name="<?php echo $dbo;?>[template_insert]" <?php if(isset($o['template_insert'])) checked($o['template_insert'],'on');?> value="on"/><label for="<?php echo $dbo;?>[template_insert]"> <?php _e('Use manual insert of badge code?',$pd);?></label>
1681
- <br>( <strong>&lt;?php cl_display_badge(); ?&gt;</strong> )
1682
- </td>
1683
- <td>
1684
- <input type="checkbox" name="<?php echo $dbo;?>[minifying]" <?php if(isset($o['minifying'])) checked($o['minifying'],'on');?> value="on"/><label for="<?php echo $dbo;?>[minifying]"> <?php _e('Enable minifying compatibility?',$pd);?></label>
1685
- <br><?php _e('For caching plugins (places localized code in footer)',$pd);?>
1686
- </td>
1687
- <td>
1688
- <input type="checkbox" name="<?php echo $dbo;?>[utf8]" <?php if(isset($o['utf8'])) checked($o['utf8'],'on');?> value="on"/><label for="<?php echo $dbo;?>[utf8]"> <?php _e('Disable UTF8 encoding?',$pd);?></label>
1689
- <br><?php _e('If you are having issues with accents not showing properly',$pd);?>
1690
- </td>
1691
- <td>
1692
- <input type="checkbox" name="<?php echo $dbo;?>[disable_detect]" <?php if(isset($o['disable_detect'])) checked($o['disable_detect'],'on');?> value="on"/><label for="<?php echo $dbo;?>[disable_detect]"> <?php _e('Disable Detection?',$pd);?></label>
1693
- <br><?php _e('For XML errors',$pd);?>
1694
- </td>
1695
- </tr>
1696
- <tr>
1697
- <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('API URL',$pd);?></td>
1698
- </tr>
1699
- <tr>
1700
- <td colspan="4">
1701
- <input type="text" size="60" name="<?php echo $dbo;?>[api_url]" value="<?php echo $o['api_url'];?>"/><label for="<?php echo $dbo;?>[api_url]"> <?php _e('URL to use for API',$pd);?></label>
1702
- </td>
1703
- </tr>
1704
- <tr>
1705
- <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Comment Form Field Values',$pd);?></td>
1706
- </tr>
1707
- <tr>
1708
- <td colspan="2"><?php _e('Authors Name field name',$this->plugin_domain);?></td>
1709
- <td colspan="2"><input type="text" value="<?php echo $o['author_name'];?>" name="<?php echo $dbo;?>[author_name]"/></td>
1710
- <td></td>
1711
- </tr>
1712
- <tr>
1713
- <td colspan="2"><?php _e('Email field name',$this->plugin_domain);?></td>
1714
- <td colspan="2"><input value="<?php echo $o['email_name'];?>" type="text" name="<?php echo $dbo;?>[email_name]"/></td>
1715
- <td></td>
1716
- </tr>
1717
- <tr>
1718
- <td colspan="2"><?php _e('Authors URL field name',$this->plugin_domain);?></td>
1719
- <td colspan="2"><input value="<?php echo $o['url_name'];?>" type="text" name="<?php echo $dbo;?>[url_name]"/></td>
1720
- <td></td>
1721
- </tr>
1722
- <tr>
1723
- <td colspan="2"><?php _e('Comment Text Area name',$this->plugin_domain);?></td>
1724
- <td colspan="2"><input value="<?php echo $o['comment_name'];?>" type="text" name="<?php echo $dbo;?>[comment_name]"/></td>
1725
- <td></td>
1726
- </tr>
1727
- <tr>
1728
- <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Extras',$pd);?></td>
1729
- </tr>
1730
- <tr>
1731
- <td colspan="2">
1732
- <select name="<?php echo $dbo;?>[hide_link_no_url]">
1733
- <option value="nothing" <?php selected($o['hide_link_no_url'],'nothing',true);?>><?php _e('Nothing',$this->plugin_domain);?></option>
1734
- <option value="on" <?php selected($o['hide_link_no_url'],'on',true);?>><?php _e('Hide Link',$this->plugin_domain);?></option>
1735
- <option value="spam" <?php selected($o['hide_link_no_url'],'spam',true);?>><?php _e('Spam Comment',$this->plugin_domain);?></option>
1736
- <option value="delete" <?php selected($o['hide_link_no_url'],'delete',true);?>><?php _e('Delete Comment',$this->plugin_domain);?></option>
1737
- </select>
1738
- <br/><label for="<?php echo $dbo;?>[hide_link_no_url]"><?php _e('Action to take if comment has no Author URL',$this->plugin_domain);?></label>
1739
- <br /><strong>(<?php _e('Prevents spammer abuse',$this->plugin_domain);?>)</strong>
1740
-
1741
- </td>
1742
-
1743
- <td>
1744
- <select name="<?php echo $dbo;?>[hide_link_no_url_match]">
1745
- <option value="nothing" <?php selected($o['hide_link_no_url_match'],'nothing',true);?>><?php _e('Nothing',$this->plugin_domain);?></option>
1746
- <option value="on" <?php selected($o['hide_link_no_url_match'],'on',true);?>><?php _e('Hide Link',$this->plugin_domain);?></option>
1747
- <option value="spam" <?php selected($o['hide_link_no_url_match'],'spam',true);?>><?php _e('Spam Comment',$this->plugin_domain);?></option>
1748
- <option value="delete" <?php selected($o['hide_link_no_url_match'],'delete',true);?>><?php _e('Delete Comment',$this->plugin_domain);?></option>
1749
- </select>
1750
- <br/><label for="<?php echo $dbo;?>[hide_link_no_url_match]"><?php _e('Action to take if link does not match domain of author',$this->plugin_domain);?></label>
1751
- <br /><strong>(<?php _e('Prevents users from adding fake author URLs to get around Akismet',$this->plugin_domain);?>)</strong>
1752
-
1753
- </td>
1754
-
1755
- <td>
1756
- <input type="checkbox" name="<?php echo $dbo;?>[allow_jpc]" <?php if(isset($o['allow_jpc'])) checked($o['allow_jpc'],'on');?> value="on"/><label for="<?php echo $dbo;?>[allow_jpc]"> <?php _e('Allow Jetpack comments module to activate?',$pd);?></label>
1757
- <br>
1758
- <input type="checkbox" name="<?php echo $dbo;?>[use_nonce]" <?php if(isset($o['use_nonce'])) checked($o['use_nonce'],'on');?> value="on"/><label for="<?php echo $dbo;?>[use_nonce]"> <?php _e('Use security nonce for ajax calls? <br>(disable if you get Parsing JSON Request failed. error! not authorized error)',$pd);?></label>
1759
- </td>
1760
- </tr>
1761
- <tr>
1762
- <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Diagnostics Info',$pd);?></td>
1763
- </tr>
1764
- <tr>
1765
- <td colspan="4"><textarea style="width: 99%" rows="5">
1766
- <?php
1767
- $options = $this->get_options();
1768
- $options['version'] = $this->version;
1769
- $options['home_url'] = get_home_url();
1770
- $options['wp_version'] = get_bloginfo('version');
1771
- $options['charset'] = get_bloginfo('charset');
1772
- $options['curl'] = function_exists('curl_init')? 'yes': 'no';
1773
-
1774
- print_r($options);
1775
-
1776
- ?>
1777
- </textarea>
1778
- </td>
1779
- <td>
1780
- <?php _e('You can copy this information and send it to me if I request it',$pd);?>
1781
- </td>
1782
- </tr>
1783
- </tbody>
1784
- </table>
1785
- <p></p>
1786
- <table class="widefat">
1787
- <tr>
1788
- <td>
1789
- <?php
1790
- //debugbreak();
1791
- // twitch ad?
1792
- ?>
1793
- <img src="<?php echo $this->plugin_url;?>images/logo-reveal-twitter-image.jpg"/>
1794
- </td>
1795
- <td>
1796
- <h2>My Alter-ego</h2>
1797
- <p>My new alter-ego is LoonyGeekFun on twitch. Since I was diagnosed with MS I have had to step away from making plugins and software apps so now, I make logos, banners and intro videos for my twitch followers.</p>
1798
- <p>Please <a href="http://twitch.tv/LoonyGeekFun" title="click to visit my twitch channel">Visit My Channel (http://www.twitch.tv/LoonyGeekFun)</a> and get a video or intro done. (Perhaps even a promotional video for your blog, a video for your capture page or even pay to get a sales video!)</p>
1799
- <p>I would love it if you could come along and say hi and that you use commentluv! </p>
1800
- </td>
1801
- </tr>
1802
- </table>
1803
-
1804
- </div>
1805
- <div class="submit"><input class="button-primary" id="clsubmit" type="submit" name="Submit" value="<?php _e('Save Settings',$this->plugin_domain);?>" /></div>
1806
- </form>
1807
- <h3><?php _e('Reset Settings',$this->plugin_domain);?></h3>
1808
- <form method="post" action="options.php">
1809
- <?php settings_fields( 'commentluv_options_group' ); // the name given in admin init
1810
- $javamsg = __('Are you sure you want to reset your settings? Press OK to continue',$this->plugin_domain);
1811
- ?>
1812
- <input type="hidden" name="<?php echo $this->db_option;?>[reset]" value="yes"/>
1813
- <input style="background-color: red;" type="submit" onclick="<?php echo 'if(confirm(\''.$javamsg.'\') != true) { return false; } else { return true; } ';?>" value="<?php _e('Reset',$this->plugin_domain);?>" name="submit"/>
1814
- </form>
1815
-
1816
-
1817
- </div> <!-- end main block div -->
1818
- <div style="float:left">
1819
- <table class="widefat" style="width: 230px; margin-left: 10px;">
1820
- <thead>
1821
- <tr><th scope="col"><?php _e('Plugin Info',$this->plugin_domain);?></th><th>&nbsp;</th></tr>
1822
- </thead>
1823
- <tbody>
1824
- <tr><td colspan="2"><div style="background: url(<?php echo $this->plugin_url;?>images/playbutton.png); text-align: center; font-size: 1.4em; width: 228px; height: 44px; overflow: hidden;"><br><?php _e('Start Here',$this->plugin_domain);?></div><div><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>starthere.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonfront.png"/></a></div></td></tr>
1825
- <tr><td><strong><?php _e('Author',$this->plugin_domain);?>:</strong></td><td>Andy Bailey</td></tr>
1826
- <tr><td><strong><?php _e('Home Page',$this->plugin_domain);?>:</strong></td><td><a title="<?php _e('Visit www.commentluv.com!',$this->plugin_domain);?>" href="http://www.commentluv.com/" target="_blank">commentluv.com</a></td></tr>
1827
- <tr><td><strong><?php _e('Social',$this->plugin_domain);?>:</strong></td><td><a title="Follow CommentLuv on Twitter" href="http://twitter.com/commentluv/" target="_blank"><img src="<?php echo $this->plugin_url;?>images/twitter.png"/></a> <a title="Join me on LinkedIn" href="http://uk.linkedin.com/in/commentluv" target="_blank"><img src="<?php echo $this->plugin_url;?>images/linkedin.png"/></a> <a title="Join me on Facebook" href="http://www.facebook.com/CommentLuv" target="_blank"><img src="<?php echo $this->plugin_url;?>images/facebook.png"/></a></td></tr>
1828
- <tr><td><strong><?php _e('Help',$this->plugin_domain);?>:</strong></td><td><a href="http://support.commentluv.com/" target="_blank"><?php _e('Help Desk',$this->plugin_domain);?></a></td></tr>
1829
- <tr class="alt"><td colspan="2"><?php _e('Do you like this plugin?',$this->plugin_domain);?></td></tr>
1830
- <tr><td colspan="2"><iframe src="http://www.facebook.com/plugins/likebox.php?href=http%3A%2F%2Fwww.facebook.com%2Fpages%2FCommentLuv%2F156438857738200&amp;width=210&amp;colorscheme=light&amp;show_faces=true&amp;stream=false&amp;header=false&amp;height=450" scrolling="no" frameborder="1" style="border:none; overflow:auto; width:210px; height:400px;" allowTransparency="true"></iframe></td></tr>
1831
- <tr class="alt"><td colspan="2"><?php _e('News',$this->plugin_domain);?>:</td></tr>
1832
- <tr><td colspan="2">
1833
- <h3>I Started a twitch channel!</h3>
1834
- <?php // enter twitch details here? ?>
1835
- <a href="http://twitch.tv/loonygeekfun" target="_blank" title="visit my twitch channel!"><img width="200" src="<?php echo $this->plugin_url;?>images/twitch-avatar-new-andy-cartoon.png" alt="http://twitch.tv/loonygeekfun"/></a>
1836
- </td></tr>
1837
- <tr class="alt"><td colspan="2"><?php _e('Thanks to the following for translations',$this->plugin_domain);?>:</td></tr>
1838
- <tr><td><img src="<?php echo $this->plugin_url;?>images/it.png"/> <?php _e('Italian',$this->plugin_domain);?></td><td><a target="_blank" href="http://gidibao.net/">Gianni Diuno</a></td></tr>
1839
- <tr><td><img src="<?php echo $this->plugin_url;?>images/nl.png"/> <?php _e('Dutch',$this->plugin_domain);?></td><td><a target="_blank" href="http://wpwebshop.com/">Rene</a></td></tr>
1840
- <tr><td><img src="<?php echo $this->plugin_url;?>images/pl.png"/> <?php _e('Polish',$this->plugin_domain);?></td><td><a target="_blank" href="http://techformator.pl/">Mariusz Kolacz</a></td></tr>
1841
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ge.png"/> <?php _e('Georgian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.findmyhosting.com">Kasia Ciszewski</a></td></tr>
1842
- <tr><td><img src="<?php echo $this->plugin_url;?>images/lt.png"/> <?php _e('Lithuanian',$this->plugin_domain);?></td><td><a target="_blank" href="http://mantas.malcius.lt/">Mantas Malcius</a></td></tr>
1843
- <tr><td><img src="<?php echo $this->plugin_url;?>images/br.png"/> <?php _e('Portuguese',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.korvo.com.br/">Diego Uczak</a></td></tr>
1844
- <tr><td><img src="<?php echo $this->plugin_url;?>images/my.png"/> <?php _e('Malaysian',$this->plugin_domain);?></td><td><a target="_blank" href="http://ariffshah.com/">Ariff Shah</a></td></tr>
1845
- <tr><td><img src="<?php echo $this->plugin_url;?>images/in.png"/> <?php _e('Hindi',$this->plugin_domain);?></td><td><a target="_blank" href="http://outshinesolutions.com/">Outshine Solutions</a></td></tr>
1846
- <tr><td><img src="<?php echo $this->plugin_url;?>images/id.png"/> <?php _e('Indonesian',$this->plugin_domain);?></td><td><a target="_blank" href="http://rainerflame.com/">Mokhamad Oky</a></td></tr>
1847
- <tr><td><img src="<?php echo $this->plugin_url;?>images/cn.png"/> <?php _e('Chinese (s)',$this->plugin_domain);?></td><td><a target="_blank" href="http://obugs.net/">Third Eye</a></td></tr>
1848
- <tr><td><img src="<?php echo $this->plugin_url;?>images/es.png"/> <?php _e('Spanish',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.activosenred.com/">Valentin Yonte</a></td></tr>
1849
- <tr><td><img src="<?php echo $this->plugin_url;?>images/de.png"/> <?php _e('German',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.cloudliving.de/">Jan Ruehling</a></td></tr>
1850
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ir.png"/> <?php _e('Persian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.3eo.ir/">Amir heydari</a></td></tr>
1851
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ta.png"/> <?php _e('Tamil',$this->plugin_domain);?></td><td><a target="_blank" href="http://technostreak.com/">Tharun</a></td></tr>
1852
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ua.png"/> <?php _e('Ukranian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.designcontest.com/">Alyona Lompar</a></td></tr>
1853
- <tr><td><img src="<?php echo $this->plugin_url;?>images/lv.png"/> <?php _e('Latvian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.yourwebagency.co.uk/">Edgars Bergs</a></td></tr>
1854
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ro.png"/> <?php _e('Romanian',$this->plugin_domain);?></td><td><a target="_blank" href="http://obisnuit.eu/">Manuel Cheta</a></td></tr>
1855
- <tr><td><img src="<?php echo $this->plugin_url;?>images/no.png"/> <?php _e('Norwegian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.drommeland.com/">Hanna</a></td></tr>
1856
- <tr><td><img src="<?php echo $this->plugin_url;?>images/fr.png"/> <?php _e('French',$this->plugin_domain);?></td><td><a target="_blank" href="http://etreheureux.fr/">Jean-Luc Matthys</a></td></tr>
1857
- <tr><td><img src="<?php echo $this->plugin_url;?>images/dk.png"/> <?php _e('Danish',$this->plugin_domain);?></td><td><a target="_blank" href="http://w3blog.dk/">Jimmy Sigenstroem</a></td></tr>
1858
- <tr><td><img src="<?php echo $this->plugin_url;?>images/ru.png"/> <?php _e('Russian',$this->plugin_domain);?></td><td><a target="_blank" href="http://lavo4nik.ru/">Max</a></td></tr>
1859
- <tr><td><img src="<?php echo $this->plugin_url;?>images/bd.png"/> <?php _e('Bengali',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.techmoody.com">Amrik Virdi</a></td></tr>
1860
- <tr><td><img src="<?php echo $this->plugin_url;?>images/il.png"/> <?php _e('Hebrew',$this->plugin_domain);?></td><td><a target="_blank" href="http://makemoneyim.com/">Tobi</a></td></tr>
1861
- <tr><td><img src="<?php echo $this->plugin_url;?>images/vn.png"/> <?php _e('Vietnamese',$this->plugin_domain);?></td><td><a target="_blank" href="http://thegioimanguon.com/">Xman</a></td></tr>
1862
- <tr><td><img src="<?php echo $this->plugin_url;?>images/hu.png"/> <?php _e('Hungarian',$this->plugin_domain);?></td><td><a target="_blank" href="http://no1tutorials.net/">Bruno</a></td></tr>
1863
- <tr><td><img src="<?php echo $this->plugin_url;?>images/sk.png"/> <?php _e('Slovak',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.brozman.sk/blog">Viliam Brozman</a></td></tr>
1864
- <tr><td><img src="<?php echo $this->plugin_url;?>images/rs.png"/> <?php _e('Serbian',$this->plugin_domain);?></td><td><a target="_blank" href="http://wpcouponshop.com/">Diana</a></td></tr>
1865
- <tr><td><img src="<?php echo $this->plugin_url;?>images/tr.png"/> <?php _e('Turkish',$this->plugin_domain);?></td><td><a target="_blank" href="http://hakanertr.wordpress.com/">Hakan</a></td></tr>
1866
- <tr><td><img src="<?php echo $this->plugin_url;?>images/sz.png"/> <?php _e('Swahili',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.purehcgdietdrops.com/blog/">Andrew Mwankiki</a></td></tr>
1867
- <tr><td><img src="<?php echo $this->plugin_url;?>images/th.png"/> <?php _e('Thai',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.martinhurley.com/">Martin Hurley</a></td></tr>
1868
-
1869
-
1870
- <tr><td><img src="<?php echo $this->plugin_url;?>images/sa.png"/> <?php _e('Arabic',$this->plugin_domain);?></td><td><!--<a target="_blank" href="http://www.melzarei.be/">Muhammad Elzarei</a>--></td></tr>
1871
- <tr><td><strong><?php _e('Want your link here?',$this->plugin_domain);?></strong></td><td><a target="_blank" href="http://support.commentluv.com/ticket/knowledgebase.php?article=1"><?php _e('How To Submit A Translation',$this->plugin_domain);?></a></td></tr>
1872
- <tr class="alt"><td colspan="2"><?php _e('Special thanks go to the following',$this->plugin_domain);?>:</td></tr>
1873
- <tr><td><strong><?php _e('CSS Help',$this->plugin_domain);?>:</strong></td><td><a href="http://www.famousbloggers.net" target="_blank">Hesham Zebida</a></td></tr>
1874
- <tr><td><strong><?php _e('Badge GFX',$this->plugin_domain);?>:</strong></td><td><a href="http://byteful.com/" target="_blank">Byteful Travel</a></td></tr>
1875
- </tbody>
1876
- </table>
1877
- </div>
1878
-
1879
-
1880
- </div>
1881
- <div class="clear"></div>
1882
- </div>
1883
- <?php
1884
-
1885
- }
1886
-
1887
-
1888
- } // end class
1889
- } // end if class not exists
1890
- // Let's give commentluv plenty of room to work with
1891
- $mem = abs(intval(@ini_get('memory_limit')));
1892
- if( $mem and $mem < 128 ){
1893
- @ini_set('memory_limit', '128M');
1894
- }
1895
- $clbadgeshown = false;
1896
- // start commentluv class engines
1897
- if (class_exists ( 'commentluv' )) :
1898
- $commentluv = new commentluv ( );
1899
- // confirm warp capability
1900
- if (isset ( $commentluv )) {
1901
- // engage
1902
- register_activation_hook ( __FILE__, array (&$commentluv, 'install' ) );
1903
- }
1904
- endif;
1905
-
1906
- function cl_display_badge(){
1907
- global $commentluv;
1908
- if(isset($commentluv)){
1909
- $commentluv->display_badge();
1910
- }
1911
-
1912
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1913
  ?>
1
+ <?php /* commentluv
2
+ Plugin Name: CommentLuv
3
+ Plugin URI: http://comluv.com/
4
+ Description: Reward your readers by automatically placing a link to their last blog post at the end of their comment. Encourage a community and discover new posts.
5
+ Version: 2.94.8
6
+ Author: Andy Bailey
7
+ Author URI: http://www.commentluv.com
8
+ Copyright (C) <2011> <Andy Bailey>
9
+
10
+ This program is free software: you can redistribute it and/or modify
11
+ it under the terms of the GNU General Public License as published by
12
+ the Free Software Foundation, either version 3 of the License, or
13
+ (at your option) any later version.
14
+
15
+ This program is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ GNU General Public License for more details.
19
+
20
+ You should have received a copy of the GNU General Public License
21
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
22
+ */
23
+ if (! class_exists ( 'commentluv' )) {
24
+ // let class begin
25
+ class commentluv {
26
+ //localization domain
27
+ var $plugin_domain = 'commentluv';
28
+ var $plugin_url;
29
+ var $plugin_dir;
30
+ var $db_option = 'commentluv_options';
31
+ var $version = "2.94.8";
32
+ var $slug = 'commentluv-options';
33
+ var $localize;
34
+ var $is_commentluv_request = false;
35
+
36
+ /** commentluv
37
+ * This is the constructor, it runs as soon as the class is created
38
+ * Use this to set up hooks, filters, menus and language config
39
+ */
40
+ function __construct() {
41
+ global $wp_version, $pagenow, $wp_actions;
42
+ $options = $this->get_options();
43
+ // try to add jetpack_module_loaded_comments action so it doesn't load
44
+ if(!isset($options['allow_jpc'])){
45
+ $wp_actions['jetpack_module_loaded_comments'] = 1;
46
+ }
47
+ // pages where this plugin needs translation
48
+ $local_pages = array ('plugins.php', 'options-general.php' );
49
+ // check if translation needed on current page
50
+ if (in_array ( $pagenow, $local_pages ) || (isset($_GET['page']) && in_array ( $_GET ['page'], $local_pages ))) {
51
+ $this->handle_load_domain ();
52
+ }
53
+ $exit_msg = __( 'CommentLuv requires Wordpress 3.0 or newer.', $this->plugin_domain ) . '<a href="http://codex.wordpress.org/Upgrading_Wordpress">' . __ ( 'Please Update!', $this->plugin_domain ) . '</a>';
54
+ // can you dig it?
55
+ if (version_compare ( $wp_version, "3.0", "<" )) {
56
+ deactivate_plugins(basename(__FILE__)); //deactivate me
57
+ wp_die ( $exit_msg ); // no diggedy
58
+ }
59
+ // activation/deactivation
60
+ register_activation_hook(__FILE__, array(&$this,'activation'));
61
+ register_deactivation_hook(__FILE__, array(&$this,'deactivation'));
62
+ // manual set install and activate, wordpress wont fire the activation hook on auto upgrade plugin
63
+ $cl_version = get_option('cl_version');
64
+ if($this->version != $cl_version){
65
+ $this->install();
66
+ $this->activation();
67
+ }
68
+ // plugin dir and url
69
+ $this->plugin_url = trailingslashit ( WP_PLUGIN_URL . '/' . dirname ( plugin_basename ( __FILE__ ) ) );
70
+ $this->plugin_dir = dirname(__FILE__);
71
+ if(defined('DOING_AJAX') && DOING_AJAX){
72
+ add_action ( 'wp_ajax_removeluv', array (&$this, 'ajax_remove_luv') ); // handle the call to the admin-ajax for removing luv
73
+ add_action ( 'wp_ajax_notify_signup', array(&$this,'notify_signup')); // ajax handler for settings page subscribe button
74
+ add_action ( 'wp_ajax_nopriv_cl_ajax',array(&$this,'do_ajax'));
75
+ add_action ( 'wp_ajax_cl_ajax',array(&$this,'do_ajax'));
76
+ } else {
77
+ add_action ( 'clversion', array (&$this,'check_version') ); // check commentluv version
78
+ add_action ( 'init', array (&$this,'init') ); // to register styles and scripts
79
+ add_action ( 'admin_init', array (&$this, 'admin_init' ) ); // to register settings group
80
+ add_action ( 'admin_menu', array (&$this, 'admin_menu' ) ); // to setup menu link for settings page
81
+ add_action ( 'admin_print_scripts-settings_page_commentluv-options', array(&$this,'add_settings_page_script')); // script for settings page ajax function
82
+ add_action ( 'admin_print_styles-settings_page_commentluv-options', array(&$this,'add_settings_page_style')); // script for settings page ajax function
83
+ add_action ( 'init', array(&$this,'detect_useragent'));
84
+ }
85
+ // filters
86
+ add_filter ( 'cron_schedules', array (&$this, 'cron_schedules') ); // for my own recurrence
87
+ add_filter ( 'plugin_action_links', array (&$this, 'plugin_action_link' ), - 10, 2 ); // add a settings page link to the plugin description. use 2 for allowed vars
88
+ // add_filter ( 'found_posts', array(&$this,'send_feed'),-1,2); // sends post titles and urls only - deprecated in 2.90.9.9
89
+ add_filter ( 'kindergarten_html', array(&$this,'kindergarten_html')); // for cleaning html
90
+
91
+ //$this->check_version();
92
+ if(!isset($options['enable']) || ( isset($options['enable']) && $options['enable'] != 'no')){
93
+ $this->setup_hooks();
94
+ }
95
+
96
+
97
+ }
98
+ /**
99
+ * PHP4 constructor
100
+ */
101
+ function commentluv() {
102
+ $this->__construct();
103
+ }
104
+ /** runs when plugin is activated
105
+ * called by register_activation_hook
106
+ *
107
+ */
108
+ function activation(){
109
+ // only add if it doesn't exist yet
110
+ $sched = wp_next_scheduled('clversion');
111
+ if(false === $sched){
112
+ // set up cron for version check
113
+ $rnd = mt_rand(5,604800);
114
+ wp_schedule_event(time() - $rnd,'clfortnightly','clversion');
115
+ }
116
+ // removed w3 total cache stuff due to Freds updates causing fatal errors
117
+ }
118
+ /**
119
+ * Adds fields to comment area
120
+ * called by add_action('comment_form
121
+ */
122
+ function add_fields(){
123
+ global $clbadgeshown;
124
+ $options = $this->get_options();
125
+ if(!$this->is_enabled()){
126
+ return;
127
+ }
128
+ $author_name = $options['author_name'];
129
+ $email_name = $options['email_name'];
130
+ $url_name = $options['url_name'];
131
+ // handle logged on user
132
+ if(is_user_logged_in()){
133
+ global $userdata;
134
+ get_currentuserinfo();
135
+ $author = $userdata->display_name;
136
+ $userid = $userdata->ID;
137
+ $url = $userdata->user_url;
138
+ if(!strstr($url,'http://') && $url != ''){
139
+ $url = 'http://'.$url;
140
+ }
141
+ // check for s2 member pluin, add url from it's custom registration fields
142
+ if(defined('WS_PLUGIN__S2MEMBER_VERSION') && isset($userdata->wp_s2member_custom_fields['website'])){
143
+ $url = $userdata->wp_s2member_custom_fields['website'];
144
+ }
145
+ // check for multisite
146
+ if(is_multisite()){
147
+ if(!$url || $url == 'http://'){
148
+ $userbloginfo = get_blogs_of_user($userid,1);
149
+ $url = $userbloginfo[1] -> siteurl;
150
+ }
151
+ }
152
+ // final check of url
153
+ if($url == 'http://'){
154
+ $url = '';
155
+ }
156
+ // spit out hidden fields
157
+ echo '<input type="hidden" id="'.$author_name.'" name="'.$author_name.'" value="'.$author.'"/>';
158
+ // if buddypress, don't hide field
159
+ if(function_exists('bp_core_setup_globals')){
160
+ $input_type = 'text';
161
+ } else {
162
+ $input_type = 'hidden';
163
+ }
164
+ echo '<input type="'.$input_type.'" id="'.$url_name.'" name="'.$url_name.'" value="'.$url.'"/>';
165
+ }
166
+ // add hidden fields for holding information about type,choice,html and request for every user
167
+ echo '<input type="hidden" name="cl_post_title" id="cl_post_title"/>';
168
+ echo '<input type="hidden" name="cl_post_url" id="cl_post_url"/>';
169
+ echo '<input type="hidden" name="cl_prem" id="cl_prem"/>';
170
+ // show badge (unless user set to manual insert)
171
+ if(($clbadgeshown == false && !isset($options['template_insert'])) || (isset($options['template_insert']) && $options['template_insert'] == '') ){
172
+ $this->display_badge();
173
+ }
174
+ }
175
+ function add_footer(){
176
+ $minifying = 'off';
177
+ extract($this->get_options());
178
+ if($minifying != 'on' || !$this->is_enabled()){
179
+ return;
180
+ }
181
+ // from the excellent book wp-ajax (http://www.wpajax.com/)
182
+ $data = "var cl_settings = {";
183
+ $arr = array();
184
+ $vars = $this->localize;
185
+ if(is_array($vars)){
186
+ foreach ($vars as $key => $value) {
187
+ $arr[count($arr)] = $key . " : '" . esc_js($value) . "'";
188
+ }
189
+ $data .= implode(",",$arr); $data .= "};";
190
+ echo "<script type='text/javascript'>\n";
191
+ echo "/* <![CDATA[ */\n";
192
+ echo $data;
193
+ echo "\n/* ]]> */\n";
194
+ echo "</script>\n";
195
+ }
196
+ }
197
+ /**
198
+ * called by add_filter('comment_row_actions
199
+ * adds another link to the comment row in admin for removing the luv link
200
+ * @param array $actions - the existing actions
201
+ */
202
+ function add_removeluv_link($actions){
203
+ global $post;
204
+ if(!$post){
205
+ // must be showing on the dashboard
206
+ return $actions;
207
+ }
208
+ $user_can = current_user_can('edit_posts', $post->ID);
209
+ $cid = get_comment_ID();
210
+ $data = get_comment_meta($cid,'cl_data');
211
+ if($data && is_array($data)){
212
+ if($user_can){
213
+ $nonce= wp_create_nonce ('removeluv'.get_comment_ID());
214
+ $actions['Remove-luv'] = '<a class="removeluv :'.$cid.':'.$nonce.'" href="javascript:">Remove Luv</a>';
215
+ }
216
+ }
217
+ return $actions;
218
+ }
219
+ /**
220
+ * called by add_action('admin_print_scripts-edit-comments.php'
221
+ * load the script to handle the removluv link
222
+ *
223
+ */
224
+ function add_removeluv_script(){
225
+ wp_enqueue_script ( 'commentluv', $this->plugin_url . 'js/adminremoveluv.js', array ('jquery' ),$this->version );
226
+ }
227
+ /**
228
+ * called by add_action('template_redirect in setup_hooks()
229
+ * used to add the commentluv script and localized settings (if not using minifying compatibility)
230
+ */
231
+ function add_script(){
232
+ $minifying = 'off';
233
+ $template_insert = false;
234
+ $options = $this->get_options();
235
+ extract($options);
236
+ if(!$this->is_enabled()){
237
+ return;
238
+ }
239
+ wp_enqueue_script('commentluv_script');
240
+ $this->localize = array ('name' => $author_name, 'url' => $url_name, 'comment' => $comment_name, 'email' => $email_name,
241
+ 'infopanel' => $infopanel, 'default_on' => $default_on, 'default_on_admin' => $default_on_admin,
242
+ 'cl_version' => $this->version, 'images' => $this->plugin_url . 'images/',
243
+ 'api_url' => $api_url, 'api_url_alt' => admin_url('admin-ajax.php'),
244
+ '_fetch' => wp_create_nonce('fetch'), '_info' => wp_create_nonce('info'),
245
+ 'infoback' => $infoback, 'infotext'=>$infotext,'template_insert'=>$template_insert, 'logged_in'=>is_user_logged_in(),
246
+ 'refer' => get_permalink(),
247
+ 'no_url_message'=>__('Please enter a URL and then click the CommentLuv checkbox if you want to add your last blog post',$this->plugin_domain),
248
+ 'no_http_message'=>__('Please use http:// in front of your url',$this->plugin_domain),
249
+ 'no_url_logged_in_message'=>__('You need to visit your profile in the dashboard and update your details with your site URL',$this->plugin_domain),
250
+ 'no_info_message'=>__('No info was available or an error occured',$this->plugin_domain));
251
+ if($minifying != 'on'){
252
+ wp_localize_script('commentluv_script','cl_settings',$this->localize);
253
+ }
254
+
255
+
256
+ }
257
+ /**
258
+ * called by add_action('wp_print_styles in setup_hooks()
259
+ * Used to add the stylesheet for commentluv
260
+ */
261
+ function add_style(){
262
+ if(!$this->is_enabled()){
263
+ return;
264
+ }
265
+ wp_enqueue_style('commentluv_style');
266
+ }
267
+ /**
268
+ * Adds scripts to settings page. Only loads scripts if the settings page is being shown
269
+ * Called by add_action('admin_print_scripts-settings_page_commentluv-options'
270
+ * use localize so messages in javascript are internationalized
271
+ */
272
+ function add_settings_page_script (){
273
+ wp_enqueue_script ('notify_signup', $this->plugin_url . 'js/notify_signup.js', array('jquery'),$this->version );
274
+ wp_localize_script ( 'notify_signup', 'notify_signup_settings', array('wait_message'=>__('Please wait',$this->plugin_domain),'notify_success1' => __('Please check your inbox, an email will be sent to',$this->plugin_domain), 'notify_success2'=>__('in the next few minutes with a confirmation link',$this->plugin_domain), 'notify_fail'=>__('An error happened with the request. Try signing up at the site',$this->plugin_domain),'image_url'=>$this->plugin_url.'images/','default_image'=>'CL91_default.png', 'white'=>'CL91_White.gif','black'=>'CL91_Black.gif','none'=>'nothing.gif'));
275
+ wp_enqueue_script('thickbox',null,array('jquery'));
276
+ echo "<link rel='stylesheet' href='/".WPINC."/js/thickbox/thickbox.css?ver=20080613' type='text/css' media='all' />\n";
277
+ }
278
+ /**
279
+ * adds the thickbox style to header for commentluv settings page
280
+ * called by add_action('admin_print_styles-settings_page_commentluv-options
281
+ */
282
+ function add_settings_page_style(){
283
+ wp_enqueue_style('thickbox');
284
+ }
285
+ /** admin_init
286
+ * This function registers the settings group
287
+ * it is called by add_action admin_init
288
+ * options in the options page will need to be named using $this->db_option[option]
289
+ */
290
+ function admin_init(){
291
+ // whitelist options
292
+ register_setting( 'commentluv_options_group', $this->db_option ,array(&$this,'options_sanitize' ) );
293
+ $options = $this->get_options();
294
+ //if(isset($options['upgrade'])){
295
+ if(isset($options['upgrade']) && version_compare($options['upgrade'],$this->php_version($this->version),'>')){
296
+ add_action('admin_notices',array(&$this,'show_upgrade_notice'));
297
+ }
298
+ }
299
+
300
+ /** admin_menu
301
+ * This function adds a link to the settings page to the admin menu
302
+ * see http://codex.wordpress.org/Adding_Administration_Menus
303
+ * it is called by add_action admin_menu
304
+ */
305
+ function admin_menu(){
306
+ if(is_multisite()){
307
+ $level = 'manage_options'; // for wpmu sub blog admins
308
+ } else {
309
+ $level = 'administrator'; // for single blog intalls
310
+ }
311
+ $menutitle = '<img src="' . $this->plugin_url . 'images/littleheart.gif" alt=""/> CommentLuv';
312
+ add_options_page ( 'CommentLuv settings', $menutitle, $level, $this->slug, array (&$this, 'options_page' ) );
313
+ }
314
+ /**
315
+ * ajax handler
316
+ * setup by add_action ( 'wp_ajax_removeluv'
317
+ * called when remove luv link is clicked in comments edit page
318
+ * with POST['action'] of removeluv, receives cid and _wpnonce
319
+ */
320
+ function ajax_remove_luv(){
321
+ // check user is allowed to do this
322
+ $nonce=$_REQUEST['_wpnonce'];
323
+ $cid = $_REQUEST['cid'];
324
+ if (! wp_verify_nonce($nonce, 'removeluv'.$cid) ) die("Epic fail");
325
+ // delete meta if comment id sent with request
326
+ if($cid){
327
+ // get meta and set vars if exists
328
+ $cmeta =get_comment_meta($cid,'cl_data','true');
329
+ if($cmeta) extract($cmeta);
330
+ // delete it and call comluv to tell it what happened
331
+ if(delete_comment_meta($cid,'cl_data')){
332
+ // can call originator blog here maybe
333
+ // return the comment id and status code for js processing to hide luv
334
+ echo "$cid*200";
335
+ }
336
+ } else {
337
+ echo '0';
338
+ }
339
+ exit;
340
+ }
341
+ /**
342
+ * checks for a new version
343
+ * called by a cron action
344
+ */
345
+ function check_version(){
346
+ //debugbreak();
347
+ $version = $this->php_version($this->version);
348
+ $options = $this->get_options();
349
+ $url = 'http://version.commentluv.com/';
350
+ $name = strip_tags(get_bloginfo('name'));
351
+ $description = strip_tags(get_bloginfo('description'));
352
+ $ioncube = extension_loaded('ionCube Loader')? 'yes' : 'no';
353
+ $numluv = $this->get_numluv();
354
+ $dofollow = $options['dofollow'];
355
+ $whogets = $options['whogets'];
356
+ $body = array('version'=>$version,'enabled'=>$options['enable'],'name'=>$name,'description'=>$description,'avatarmd5'=>md5(strtolower(get_bloginfo('admin_email'))),'numluv'=>$numluv,'dofollow'=>$dofollow,'whogets'=>$whogets,'ioncube'=>$ioncube);
357
+ $response = wp_remote_head($url,array('method'=>'POST','body'=>$body));
358
+ $latest = $this->php_version(wp_remote_retrieve_header($response,'version'));
359
+ $message = wp_remote_retrieve_header($response,'message');
360
+ if(version_compare($version,$latest,'<')){
361
+ $options['upgrade'] = $latest;
362
+ if($message){
363
+ $options['upgrade_message'] = apply_filters('kindergarten_html',$message);
364
+ }
365
+ update_option($this->db_option,$options);
366
+ }
367
+ }
368
+ /**
369
+ * called by add_action('comment_post
370
+ * runs just after comment has been saved to the database
371
+ * will save the luv link to comment meta if it exists
372
+ *
373
+ * @param int $id - id of the comment
374
+ * @param string $commentdata - status of comment
375
+ */
376
+ function comment_posted($id,$commentdata){
377
+ if(isset($_POST['cl_post_url']) && $_POST['cl_post_url'] != '' && isset($_POST['cl_post_title']) && $_POST['cl_post_title'] != ''){
378
+ $title = strip_tags($_POST['cl_post_title']);
379
+ $link = esc_url($_POST['cl_post_url']);
380
+ $options = $this->get_options();
381
+ //debugbreak();
382
+ // check for spam or delete comment if no author url
383
+ // spam or delete comment if no author url depending on user settings
384
+ //(for logged out users only because logged in users have no commentdata->comment_author_url)
385
+ if(!is_user_logged_in()){
386
+ if($options['hide_link_no_url'] == 'spam' && $commentdata->comment_author_url ==''){
387
+ $commentdata->comment_approved = 'spam';
388
+ $update = wp_update_comment((array)$commentdata);
389
+ }
390
+ if($options['hide_link_no_url'] == 'delete' && $commentdata->comment_author_url == ''){
391
+ wp_delete_comment($id);
392
+ return;
393
+ }
394
+ // check for matching comment
395
+ if(!isset($options['hide_link_no_url_match'])){
396
+ $options['hide_link_no_url_match'] = 'nothing';
397
+ }
398
+ $authorurlarr = parse_url($commentdata->comment_author_url);
399
+ $linkurlarr = parse_url($link);
400
+ if($options['hide_link_no_url_match'] != 'nothing'){
401
+ if($authorurlarr['host'] != $linkurlarr['host']){
402
+ // link has different domain
403
+ if($options['hide_link_no_url_match'] == 'spam'){
404
+ $commentdata->comment_approved = 'spam';
405
+ $update = wp_update_comment((array)$commentdata);
406
+ }
407
+ if($options['hide_link_no_url_match'] == 'delete'){
408
+ wp_delete_comment($id);
409
+ return;
410
+ }
411
+ }
412
+ }
413
+ }
414
+ $prem = 'p' == $_POST['cl_prem'] ? 'p' : 'u';
415
+ $data = array('cl_post_title'=>$title,'cl_post_url'=>$link,'cl_prem'=>$prem);
416
+ add_comment_meta($id,'cl_data',$data,'true');
417
+ }
418
+ }
419
+ /**
420
+ * add my own recurrence schedule
421
+ * called by add_filter('cron_schedules
422
+ *
423
+ * @param mixed $schedules - the current schedules
424
+ */
425
+ function cron_schedules($schedules){
426
+ $schedules['clfortnightly'] = array(
427
+ 'interval' => 1209600,
428
+ 'display' => __('Twice Monthly')
429
+ );
430
+ return $schedules;
431
+ }
432
+ /** runs when plugin is deactivated
433
+ * called by register_deactivation_hook
434
+ *
435
+ */
436
+ function deactivation(){
437
+ wp_clear_scheduled_hook('clversion');
438
+ }
439
+ /**
440
+ * detect if request is from a commentluv useragent
441
+ * called by add_action('init
442
+ *
443
+ * ignore if user has set disable_detect in settings
444
+ *
445
+ * since 2.90.9.9 - add action for template redirect, we do the sending of the special feed there now
446
+ */
447
+ function detect_useragent(){
448
+ $options = $this->get_options();
449
+ // dont do anything if detect is disabled
450
+ if(isset($_POST['version_check'])){
451
+ $this->check_version();
452
+ }
453
+ if(isset($options['disable_detect']) && $options['disable_detect'] == 'on'){
454
+ return;
455
+ }
456
+ // is this commentluv calling?
457
+ if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/Commentluv/i", $_SERVER['HTTP_USER_AGENT'])){
458
+ $this->is_commentluv_request = true;
459
+ ob_start();
460
+ if(!isset($options['disable_detect'])){
461
+ remove_all_actions('wp_head');
462
+ remove_all_actions('wp_footer');
463
+ // prevent wordpress.com stats from adding stats script
464
+ global $wp_query;
465
+ $wp_query->is_feed = true;
466
+ // use own function to output feed
467
+ add_action('template_redirect',array(&$this,'send_feed_file'),1);
468
+ }
469
+ }
470
+ }
471
+ /**
472
+ * Called by add_fields or by manual insert
473
+ * used to show the badge and extra bits for holding the ajax drop down box
474
+ *
475
+ */
476
+ function display_badge(){
477
+ //DebugBreak();
478
+ global $clbadgeshown;
479
+ $badges = array('default'=>'CL91_default.png','default_image'=>'CL91_default.png','white'=>'CL91_White.gif','black'=>'CL91_Black.gif');
480
+ $options = $this->get_options();
481
+ if($clbadgeshown == true){
482
+ return;
483
+ }
484
+ // link to commentluv?
485
+ $before = '';
486
+ $after = '';
487
+ // link
488
+ if(isset($options['link'])){
489
+ $before = '<a href="http://www.commentluv.com" target="_blank" title="'.__('CommentLuv is enabled',$this->plugin_domain).'">';
490
+ $after = '</a>';
491
+ }
492
+ // dropdown choice
493
+ if($options['badge_choice'] == 'drop_down'){
494
+ if($options['badge_type'] != 'none'){
495
+ $imgurl = $this->plugin_url.'images/'.$badges[$options['badge_type']];
496
+ }
497
+ }
498
+ // custom image
499
+ if($options['badge_choice'] == 'custom'){
500
+ if(isset($options['custom_image_url']) && $options['custom_image_url'] != ''){
501
+ if(!strstr($options['custom_image_url'],'http://')){
502
+ $imgurl = 'http://'.$options['custom_image_url'];
503
+ } else {
504
+ $imgurl = $options['custom_image_url'];
505
+ }
506
+ }
507
+ }
508
+ // create badge code (if not chosen 'none')
509
+ if($options['badge_choice'] == 'drop_down' && $options['badge_type'] == 'none'){
510
+ $badgecode = '';
511
+ } else {
512
+ if(!$imgurl){
513
+ $imgurl = $this->plugin_url.'images/'.$badges['default_image'];
514
+ }
515
+ $badgecode = $before.'<img alt="CommentLuv badge" src="'.$imgurl.'"/>'.$after;
516
+ }
517
+ // or using text
518
+ if($options['badge_choice'] == 'text'){
519
+ $badgecode = $before.$options['badge_text'].$after;
520
+ }
521
+ // default on
522
+ $default_on = '';
523
+ if($options['default_on'] == 'on'){
524
+ $default_on = ' checked="checked"';
525
+ if(is_user_logged_in() && current_user_can('manage_options')){
526
+ if($options['default_on_admin'] != 'on'){
527
+ $default_on = '';
528
+ }
529
+ }
530
+ }
531
+ // spit out code
532
+ echo '<div id="commentluv"><div id="cl_messages"></div><input type="checkbox" id="doluv" name="doluv"'.$default_on.' /><span id="mylastpost">'.$badgecode.'</span><span id="showmorespan"><img class="clarrow" id="showmore" src="'.$this->plugin_url.'images/down-arrow.gif" alt="'.__('Show more posts',$this->plugin_domain).'" title="'.__('Show more posts',$this->plugin_domain).'" style="display:none;"/></span></div><div id="lastposts" style="display:none;"></div>';
533
+ $clbadgeshown = true;
534
+ }
535
+ /**
536
+ * ajax handler.
537
+ * called by add_action('wp_ajax_(nopriv_)ajax
538
+ * handles all ajax requests, receives 'do' as POST var and calls relevant function
539
+ *
540
+ */
541
+ function do_ajax(){
542
+ $oldchecknonce = $_POST['_ajax_nonce'];
543
+ $newchecknonce = preg_replace("/[^A-Za-z0-9 ]/", '', $oldchecknonce);
544
+ if($oldchecknonce != $newchecknonce){
545
+ die('error! nonce malformed');
546
+ }
547
+ switch($_POST['do']){
548
+ case 'fetch' :
549
+ $this->fetch_feed();
550
+ break;
551
+ case 'info' :
552
+ $this->do_info();
553
+ break;
554
+ case 'click' :
555
+ $this->do_click();
556
+ break;
557
+
558
+ }
559
+ }
560
+ /**
561
+ * called by do_ajax
562
+ * receives cid and nonce and cl_prem as POST vars
563
+ * stores the click in the comment meta
564
+ */
565
+ function do_click(){
566
+ $cid = intval($_POST['cid']);
567
+ $nonce = $_POST['_ajax_nonce'];
568
+ $url = $_POST['url'];
569
+ if(!wp_verify_nonce($nonce,$cid)){
570
+ exit;
571
+ }
572
+ $data = get_comment_meta($cid,'cl_data',true);
573
+ if(is_array($data)){
574
+ $data['clicks'] = isset($data['clicks']) ? $data['clicks'] : 0;
575
+ $data['clicks'] = $data['clicks'] + 1;
576
+ update_comment_meta($cid,'cl_data',$data);
577
+ }
578
+ if($_POST['cl_prem'] == 'true'){
579
+ $comment = get_commentdata($cid);
580
+ $refer = get_permalink($comment['comment_post_ID']);
581
+ // set blocking to false because no response required
582
+ $response = wp_remote_post($url,array('blocking'=>false,'body'=>array('cl_request'=>'click','refer'=>$refer,'version'=>$this->version)));
583
+ }
584
+ exit;
585
+ }
586
+ /**
587
+ * called by do_ajax
588
+ * receives cl_prem, url and cid as POST vars
589
+ * sends back json encoded string for the content of the panel
590
+ */
591
+ function do_info(){
592
+ $options = $this->get_options();
593
+ if(isset($options['use_nonce'])){
594
+ check_ajax_referer('info');
595
+ }
596
+ global $wpdb;
597
+
598
+ $isreg = false;
599
+ $cid = intval($_POST['cid']);
600
+ $cl_prem = $_POST['cl_prem'];
601
+ $link = $_POST['link'];
602
+ // is registered user?
603
+ $email = get_comment_author_email($cid);
604
+ //$user = get_user_by_email($email);
605
+ $user = get_user_by('email',$email);
606
+ if($user){
607
+ $isreg = true;
608
+ }
609
+ // get comments and stats
610
+ $query = $wpdb->prepare('SELECT m.meta_value, c.comment_post_ID FROM '.$wpdb->comments.' c JOIN '.$wpdb->commentmeta.' m ON c.comment_ID = m.comment_ID WHERE c.comment_approved = 1 AND c.comment_author_email = %s AND m.meta_key = %s ORDER BY c.comment_ID DESC',$email,'cl_data');
611
+ $rows = $wpdb->get_results($query);
612
+ $num_comments = $wpdb->num_rows;
613
+ // get other comments and links left
614
+ $appeared_on = array();
615
+ $appeared_on_list = array();
616
+ $my_other_posts = array();
617
+ $my_other_posts_list = array();
618
+
619
+ if($rows){
620
+ foreach($rows as $row){
621
+ $data = unserialize($row->meta_value);
622
+ if(!in_array($data['cl_post_url'],$my_other_posts_list) && sizeof($my_other_posts) < 5){
623
+ $my_other_posts[] = '<a target="_blank" href="'.$data['cl_post_url'].'">'.esc_js(substr($data['cl_post_title'],0,60)).'</a>';
624
+ $my_other_posts_list[] = $data['cl_post_url'];
625
+ }
626
+ if(!in_array($row->comment_post_ID,$appeared_on_list) && sizeof($appeared_on) < 5){
627
+ $appeared_on[] = '<a href="'.get_permalink($row->comment_post_ID).'">'.substr(get_the_title($row->comment_post_ID),0,60).'</a>';
628
+ $appeared_on_list[] = $row->comment_post_ID;
629
+ }
630
+ // stop if both lists at 5
631
+ if(count($appeared_on) >= 5 && count($my_other_posts) >= 5){
632
+ break;
633
+ }
634
+ }
635
+ }
636
+ if(empty($appeared_on)){
637
+ $appeared_on[] = __('I have only commented on this post',$this->plugin_domain);
638
+ }
639
+ if(empty($my_other_posts)){
640
+ $my_other_posts[] = '<a>'.__('If I had made more comments on this site, you would see more of my other posts here',$this->plugin_domain).'</a>';
641
+ }
642
+ // get click count on local site
643
+ $data = get_comment_meta($cid,'cl_data',true);
644
+ $clickcount = isset($data['clicks']) ? $data['clicks'] : 0;
645
+ //DebugBreak();
646
+ // prem member, try remote fetch of info if not registered on this blog
647
+ if($cl_prem == 'p' && $isreg == false){
648
+ $response = wp_remote_post($link,array('body'=>array('cl_request'=>'info','version'=>$this->version,'clickcount'=>$clickcount,'num_comments'=>$num_comments,'appeared_on'=>$appeared_on)));
649
+ $enabled = wp_remote_retrieve_header($response,'cl_info');
650
+ if($enabled == 'enabled'){
651
+ $panel = apply_filters('kindergarten_html',wp_remote_retrieve_body($response));
652
+ $json = json_encode(array('panel'=>$panel));
653
+ header ( "Content-Type: application/x-javascript; " );
654
+ echo $json;
655
+ exit;
656
+ } else {
657
+ $cl_prem = 'u';
658
+ }
659
+ }
660
+ // show registered members panel
661
+ if($isreg){
662
+ // get users info
663
+ $bio = $user->description;
664
+ if($bio == ''){
665
+ $bio = __('User has not saved a description in their profile page',$this->plugin_domain);
666
+ }
667
+ $username = $user->display_name;
668
+ if(is_multisite()){
669
+ $can = 'manage_options';
670
+ } else {
671
+ $can = 'administrator';
672
+ }
673
+ // find if user has cap, need to create new user object and use ->has_cap
674
+ // from wp 3.1, you can use if(user_can($user,$cap))
675
+ $user = new WP_User($user->ID);
676
+ if($user->has_cap($can)){
677
+ $reg_member = __('is the administrator of this site',$this->plugin_domain);
678
+ } else {
679
+ $reg_member = __('is a registered member of my site',$this->plugin_domain);
680
+ }
681
+ $gravatar = '<img src="http://www.gravatar.com/avatar/' . md5 ( strtolower($email) ) . '.jpg" alt="' . $username . '" align="left" />';
682
+ $panel = $gravatar . "<p class=\"cl_title\"><span class=\"cl_username\">$username</span> ".$reg_member."</p><p class=\"cl_bio\">$bio</p><p class=\"cl_clicks\"> <span class=\"cl_clicks_count\">$clickcount</span> ".__('Clicks on this link on this comment',$this->plugin_domain)."</p><p class=\"cl_links\">".$num_comments.' '.__('approved comments on this site',$this->plugin_domain).'<br>'.__('Some other posts I have commented on',$this->plugin_domain)."</p><p class=\"cl_links_list\">".implode('<br>',$appeared_on)."</p><p class=\"cl_posts\">".__('Some of my other posts',$this->plugin_domain)."</p><p class=\"cl_posts_list\">".implode('<br>',$my_other_posts)."</p>";
683
+ $json = json_encode(array('panel'=>$panel));
684
+ header ( "Content-Type: application/x-javascript; " );
685
+ echo $json;
686
+ exit;
687
+ }
688
+ // show panel for everyone else
689
+ $comment = get_comment($cid);
690
+ $msg = '';
691
+ $bio= get_comment_author_url($cid);
692
+ $name = get_comment_author($cid);
693
+ $gravatar = '<img src="http://www.gravatar.com/avatar/' . md5 ( strtolower($email) ) . '.jpg" alt="' . $name . '" align="left" />';
694
+ if(get_option('users_can_register') && $options['whogets'] == 'registered'){
695
+ $msg = __('has not registered on this site',$this->plugin_domain);
696
+ $bio = $options['unreg_user_text_panel'];
697
+ }
698
+ $panel = $gravatar . "<p class=\"cl_title\">
699
+ <span class=\"cl_username\">".$comment->comment_author."</span> ".$msg."</p>
700
+ <p class=\"cl_bio\">".$bio."</p>
701
+ <p class=\"cl_clicks\"> <span class=\"cl_clicks_count\">$clickcount</span> ".__('Clicks on this link on this comment',$this->plugin_domain)."</p>
702
+ <p class=\"cl_links\">".$num_comments.' '.__('approved comments on this site',$this->plugin_domain).
703
+ '<br>'.__('Some other posts I have commented on',$this->plugin_domain)."</p>
704
+ <p class=\"cl_links_list\">".implode('<br>',$appeared_on)."</p>";
705
+ // dont show other links for non registered user to entice them to register
706
+ //<p class=\"cl_posts\">".__('Some of my other posts',$this->plugin_domain)."</p>
707
+ //<p class=\"cl_posts_list\">".implode('<br>',$my_other_posts)."</p>";
708
+ $json = json_encode(array('panel'=>$panel));
709
+ header ( "Content-Type: application/x-javascript; " );
710
+ echo $json;
711
+ exit;
712
+ }
713
+ /**
714
+ * called by add_filter('comments_array
715
+ * adds the link to the comments that are to be displayed
716
+ * @param mixed $commentarray
717
+ */
718
+ function do_shortcode($commentarray){
719
+ $isadminpage = false;
720
+ $options= $this->get_options();
721
+ if(!is_array($commentarray)){
722
+ // if it's an array then it was called by comments_array filter,
723
+ // otherwise it was called by comment_content (admin screen)
724
+ // has it been done before?
725
+ if(strpos($commentarray,'class="cluv"')){
726
+ return $commentarray;
727
+ }
728
+ // make a fake array of 1 object so below treats the comment_content filter nicely for admin screen
729
+ $temparray = array('comment_ID'=>get_comment_ID(),'comment_content'=>$commentarray,'comment_author'=>get_comment_author(), 'comment_author_email'=>get_comment_author_email());
730
+ $tempobject = (object) $temparray;
731
+ $commentarray = array($tempobject);
732
+ $isadminpage = true;
733
+ }
734
+ // add link to comments (need to do it this way so thesis works with commentluv links, thesis wont use comment_text filter but it does get an array of comments)
735
+ $new_commentarray = array();
736
+ foreach($commentarray as $comment){
737
+ $data = get_comment_meta($comment->comment_ID,'cl_data','true');
738
+ $commentcontent = $comment->comment_content;
739
+ // luvlink added?
740
+ if($data && is_array($data)){
741
+ if($data['cl_post_url'] != '' && $data['cl_post_title'] != ''){
742
+ // luvlink was saved to meta, dofollow the link?
743
+ $nofollow = ' rel="nofollow"';
744
+ //$isreg = get_user_by_email($comment->comment_author_email);
745
+ $isreg = get_user_by('email',$comment->comment_author_email);
746
+ if($options['dofollow'] == 'everybody'){
747
+ $nofollow = '';
748
+ } elseif ($options['dofollow'] == 'registered' && $isreg){
749
+ $nofollow = '';
750
+ }
751
+ // construct link
752
+ $pclass = $data['cl_prem'] == 'p' ? ' p' : '';
753
+ $ajaxnonce = wp_create_nonce($comment->comment_ID);
754
+ $class = ' class="'.$ajaxnonce.' '.$comment->comment_ID.$pclass.'"';
755
+ $luvlink = '<a'.$class.$nofollow.' href="'.$data['cl_post_url'].'">'.$data['cl_post_title'].'</a>';
756
+ $search = array ('[name]', '[lastpost]','[type]' );
757
+ $replace = array ($comment->comment_author, $luvlink,'blog post' );
758
+ $prepend_text = $options ['comment_text'];
759
+ $inserted = str_replace ( $search, $replace, $prepend_text );
760
+ // check if author has a url. do not add the link if user has set to hide links for comments with no url
761
+ $authurl = isset($comment->comment_author_url) ? $comment->comment_author_url : null;
762
+ $showlink = true;
763
+ if($authurl == '' && isset($options['hide_link_no_url']) && $options['hide_link_no_url'] == 'on'){
764
+ $showlink = false;
765
+ }
766
+ // check link domain matches author url domain
767
+ if(!isset($options['hide_link_no_url_match'])){
768
+ $options['hide_link_no_url_match'] = 'nothing';
769
+ }
770
+ $authorurlarr = parse_url($authurl);
771
+ $linkurlarr = parse_url($data['cl_post_url']);
772
+ if($options['hide_link_no_url_match'] != 'nothing'){
773
+ if($authorurlarr['host'] != $linkurlarr['host']){
774
+ // link has different domain
775
+ if($options['hide_link_no_url_match'] == 'on'){
776
+ $showlink = false;
777
+ }
778
+ }
779
+ }
780
+ if($showlink){
781
+ // construct string to be added to comment
782
+ $commentcontent .= "\n<span class=\"cluv\">$inserted";
783
+ // prepare heart icon if infopanel is on
784
+ $hearticon = '';
785
+ if($data['cl_prem'] == 'p' || $isreg) {
786
+ // use PLUS heart for members
787
+ $hearticon = 'plus';
788
+ }
789
+ if ($options ['infopanel'] == 'on') {
790
+ $commentcontent .= '<span class="heart_tip_box"><img class="heart_tip '.$data['cl_prem'].' '.$comment->comment_ID.'" alt="My Profile" style="border:0" width="16" height="14" src="' . $this->plugin_url . 'images/littleheart'.$hearticon.'.gif"/></span>';
791
+ }
792
+ $commentcontent.= '</span>';
793
+ }
794
+ }
795
+ }
796
+ // store new content in this comments comment_content cell
797
+ $comment->comment_content = $commentcontent;
798
+ // fill new array with this comment
799
+ $new_commentarray[] = $comment;
800
+ }
801
+ // admin page or public page?
802
+ if($isadminpage){
803
+ // is being called by comment_text filter so expecting just content
804
+ return $commentcontent;
805
+ } else {
806
+ // called from comments_array filter so expecting array of objects
807
+ return $new_commentarray;
808
+ }
809
+ }
810
+ /**
811
+ * called by do_ajax())
812
+ * takes action when ajax request is made with URL from the comment form
813
+ * send back 1 or 10 last posts depending on rules
814
+ */
815
+ function fetch_feed() {
816
+ // check nonce
817
+ //debugbreak();
818
+ $options = $this->get_options();
819
+ if(isset($options['use_nonce'])){
820
+ $checknonce = check_ajax_referer('fetch',false,false);
821
+ if(!$checknonce){
822
+ die(' error! not authorized '.strip_tags($_REQUEST['_ajax_nonce']));
823
+ }
824
+ }
825
+ if(!$_POST['url']){
826
+ die('no url');
827
+ }
828
+ if(!defined('DOING_AJAX')){
829
+ define('DOING_AJAX',true);
830
+ }
831
+
832
+ // try to prevent deprecated notices
833
+ @ini_set('display_errors',0);
834
+ @error_reporting(0);
835
+
836
+ $dir = plugin_dir_path(__FILE__);
837
+ include_once($dir.'libs/SimpleCluvPie/autoloader.php');
838
+
839
+ $num = 1;
840
+ $url = esc_url($_POST['url']);
841
+ $orig_url = $url;
842
+ // add trailing slash (can help with some blogs)
843
+ if(!strpos($url,'?')){
844
+ $url = trailingslashit($url);
845
+ }
846
+ // fetch 10 last posts?
847
+ if((is_user_logged_in() && $options['whogets'] == 'registered') || (!is_user_logged_in() && $options['whogets'] == 'everybody')){
848
+ $num = 10;
849
+ } elseif($options['whogets'] == 'everybody') {
850
+ $num = 10;
851
+ } elseif(current_user_can('manage_options')){
852
+ $num = 10;
853
+ }
854
+ // check if request is for the blog we're on
855
+ if(strstr($url, home_url())){
856
+ //DebugBreak();
857
+ $posts = get_posts(array('numberposts'=>10));
858
+ $return = array();
859
+ $error = '';
860
+ if($posts){
861
+ foreach($posts as $post){
862
+ $return[] = array('type'=>'blog','title'=>htmlspecialchars_decode(strip_tags($post->post_title)),'link'=>get_permalink($post->ID),'p'=>'u');
863
+ }
864
+ } else {
865
+ $error = __('Could not get posts for home blog',$this->plugin_domain);
866
+ }
867
+ // check for admin only notices to add
868
+ $canreg = get_option('users_can_register');
869
+ $whogets = $options['whogets'];
870
+ if(!$canreg && $whogets == 'registered'){
871
+ $return[] = array('type'=>'message','title'=>__('Warning! You have set to show 10 posts for registered users but you have not enabled user registrations on your site. You should change the operational settings in the CommentLuv settings page to show 10 posts for everyone or enable user registrations',$this->plugin_domain),'link'=>'');
872
+ }
873
+ $response = json_encode(array('error'=>$error,'items'=>$return));
874
+ header( "Content-Type: application/json" );
875
+ echo $response;
876
+ exit;
877
+ }
878
+
879
+ $rawfile = "n/a";
880
+ $errors = array();
881
+ $rss = false;
882
+ $force_fsockopen = false;
883
+
884
+ function getRss($self, $url, $force_fsockopen) {
885
+ // get simple pie ready
886
+
887
+ $rss = new SimpleCluvPie();
888
+ if (!$rss) {
889
+ die('error! no simplecluvpie');
890
+ }
891
+
892
+ $curl_options = array();
893
+
894
+ $version = curl_version();
895
+ $version = $version["version_number"];
896
+ $goodcurl = ($version >= 467456);
897
+
898
+ if ($version >= 467456 && $version < 468736) {
899
+ $curl_options[CURLOPT_SSLVERSION] = 1; // Enforce TLSv1
900
+ }
901
+
902
+ if (isset($_POST["debugcluv"])) {
903
+ $debug = $_POST["debugcluv"];
904
+
905
+ if (isset($debug["curl_sslversion"])) {
906
+ $curl_options[CURLOPT_SSLVERSION] = $debug["curl_sslversion"];
907
+ }
908
+
909
+ if (isset($debug["curl_sslciphers"])) {
910
+ $curl_options[CURLOPT_SSL_CIPHER_LIST] = $debug["curl_sslciphers"];
911
+ }
912
+
913
+ // CURLOPT_SSLVERSION 0 = DEFAULT, 1 = TLSv1, 2 = SSLv2, 3 = SSLv3
914
+ // may also be able to set CIPHER LIST = "TLSv1"
915
+ // SET SSLVERSION = 0 AND CIPHER LIST = "DEFAULT:!SSLv2:!SSLv3" // TLSv1.2
916
+ // SET SSLVERSION = 1 AND CIPHER LIST = "HIGH:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK" // if ($goodcurl) { connected via TLSv1, TLSv1.1 or TLSv1.2 } else { TLSv1 }
917
+ // if ($goodcurl === false) - SET SSLVERSION = 0 AND CIPHER LIST = "HIGH:!aNULL:!eNULL:!EXPORT:!DSS:!DES:!RC4:!3DES:!MD5:!PSK" // SSLv3, maybe TLSv1.1, TLSv1.2 very unlikely
918
+ // SET SSLVERSION = 0 AND CIPHER LIST = "DEFAULT" // SSLv3 or with weak ciphers
919
+
920
+ ob_start(); // prevent headers already sent error
921
+ var_dump(array("curl_options" => $curl_options));
922
+ }
923
+
924
+ $rss->set_useragent('Commentluv /'.$self->version.' (Feed Parser; http://www.commentluv.com; Allow like Gecko) Build/20110502' );
925
+ $rss->enable_cache ( FALSE );
926
+ $rss->force_fsockopen($force_fsockopen);
927
+ $rss->set_feed_url($url);
928
+ $rss->set_curl_options($curl_options);
929
+ $rss->init();
930
+
931
+ return $rss;
932
+ }
933
+
934
+ unset($rss);
935
+ $newUrl = add_query_arg(array('commentluv'=>'true'), $url);
936
+ $rss = getRss($this, $newUrl, $force_fsockopen);
937
+
938
+ $ferror = $rss->error();
939
+ if ($ferror) { $errors[] = $ferror; }
940
+
941
+ if ($ferror && stristr($ferror, 'cURL error') !== false) {
942
+ // usually an SSL error due to older cURL version, so have SimpleCluvPie try fsockopen method instead
943
+ $force_fsockopen = true;
944
+
945
+ unset($rss);
946
+ $newUrl = add_query_arg(array('commentluv'=>'true'), $url);
947
+ $rss = getRss($this, $newUrl, $force_fsockopen);
948
+
949
+ $ferror = $rss->error();
950
+ if ($ferror) { $errors[] = $ferror; }
951
+ }
952
+
953
+ $su = $rss->subscribe_url();
954
+
955
+ // try a fall back and add /?feed=rss2 to the end of url if the found subscribe url hasn't already got it
956
+ // also try known blogspot feed location if this is a blogspot url
957
+ if ($ferror || strstr($ferror,'could not be found') && !strstr($su,'feed')) {
958
+ // construct alternate feed url
959
+ if (strstr($url,'blogspot')) {
960
+ $url = trailingslashit($url).'feeds/posts/default/';
961
+ } else {
962
+ $url = add_query_arg(array('feed'=>'atom'),$url);
963
+ }
964
+
965
+ unset($rss);
966
+ $rss = getRss($this, $url, $force_fsockopen);
967
+
968
+ $ferror = $rss->error();
969
+ if ($ferror) { $errors[] = $ferror; }
970
+
971
+ if ($ferror || stripos($ferror,'invalid')) {
972
+ $suburl = $rss->subscribe_url() ? $rss->subscribe_url() : $orig_url;
973
+
974
+ unset($rss);
975
+ $rss = getRss($this, $orig_url, $force_fsockopen);
976
+
977
+ $ferror = $rss->error();
978
+ if ($ferror) { $errors[] = $ferror; }
979
+
980
+ // go back to original URL if error persisted
981
+ if (stripos($ferror,'invalid')) {
982
+ // get raw file to show any errors
983
+
984
+ if (class_exists('SimpleCluvPie_File')) {
985
+ $rawfile = new SimpleCluvPie_File($suburl, $rss->timeout, 5, null, $rss->useragent, $rss->force_fsockopen);
986
+ } elseif (class_exists($rss->file_class)) {
987
+ $rawfile = new $rss->file_class($suburl, $rss->timeout, 5, null, $rss->useragent, $rss->force_fsockopen);
988
+ }
989
+ if (isset($rawfile->body)) {
990
+ $rawfile = $rawfile->body;
991
+ } else {
992
+ $rawfile = __('Raw file could not be found',$this->plugin_domain);
993
+ }
994
+ }
995
+ }
996
+ }
997
+
998
+ $rss->handle_content_type();
999
+ $gen = $rss->get_channel_tags('','generator');
1000
+ $prem_msg = $rss->get_channel_tags('','prem_msg');
1001
+ $g = $num;
1002
+ $p = 'u';
1003
+ $meta = array();
1004
+ //DebugBreak();
1005
+ if($gen && strstr($gen[0]['data'],'commentluv')){
1006
+ $generator = $gen[0]['data'];
1007
+ $meta['generator'] = $generator;
1008
+ $pos=stripos($generator,'v=');
1009
+ if(substr($generator,$pos+2,1)=='3'){
1010
+ $g=15;
1011
+ $p='p';
1012
+ }
1013
+ }
1014
+ if($prem_msg){
1015
+ $prem_msg = $prem_msg[0]['data'];
1016
+ }
1017
+ //DebugBreak();
1018
+ $error = $rss->error();
1019
+ $meta['used_feed'] = $rss->subscribe_url();
1020
+ //DebugBreak();
1021
+ // no error, construct return json
1022
+ if(!$error){
1023
+
1024
+ $arr = array();
1025
+
1026
+ // save meta
1027
+ $meta['used_feed'] = $rss->subscribe_url ();
1028
+
1029
+ $feed_items = $rss->get_items();
1030
+ foreach($feed_items as $item){
1031
+ //debugbreak();
1032
+ $type = 'blog';
1033
+ $itemtags = $item->get_item_tags('','type');
1034
+ if($itemtags){
1035
+ $type = $itemtags[0]['data'];
1036
+ }
1037
+ $arr[] = array('type'=>$type,'title'=>htmlspecialchars_decode(strip_tags($item->get_title())),'link'=>$item->get_permalink(),'p'=>$p);
1038
+ $g--;
1039
+ if($g < 1){
1040
+ break;
1041
+ }
1042
+ }
1043
+ // add message to unregistered user if set
1044
+ if(!is_user_logged_in() && $options['unreg_user_text'] && $options['whogets'] != 'everybody' && $p=='u'){
1045
+ if(get_option('users_can_register')){
1046
+ $arr[] = array('type'=>'message','title'=>$options['unreg_user_text'],'link'=>'');
1047
+ if(!strstr($options['unreg_user_text'],'action=register')){
1048
+ $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
1049
+ $arr[] = array('type'=>'message','title'=>$register_link,'link'=>'');
1050
+ }
1051
+ }
1052
+ if($options['whogets'] == 'registered' && get_option('users_can_regsiter')){
1053
+ $arr[] = array('type'=>'message','title'=>__('If you are registered, you need to log in to get 10 posts to choose from',$this->plugin_domain),'link'=>'');
1054
+ }
1055
+ }
1056
+ if($prem_msg){
1057
+ $arr[] = array('type'=>'alert','title'=>$prem_msg,'link'=>'');
1058
+ }
1059
+ $response = json_encode(array('error'=>'','items'=>$arr,'meta'=>$meta));
1060
+ } else {
1061
+ // had an error trying to read the feed
1062
+
1063
+ // return all errors, since they can be helpful in debugging
1064
+ $errors[] = $error;
1065
+ $error = implode(" <br /> ", $errors);
1066
+
1067
+ $response = json_encode(array('error'=>$error,'meta'=>$meta,'rawfile'=>htmlspecialchars($rawfile)));
1068
+ }
1069
+ unset($rss);
1070
+ header( "Content-Type: application/json" );
1071
+ echo $response;
1072
+ exit;
1073
+ }
1074
+ /**
1075
+ * find number of approved comments in the past 14 days to have a commentluv link
1076
+ * called in check_version
1077
+ * since 2.90.8
1078
+ * @return int
1079
+ */
1080
+ function get_numluv(){
1081
+ global $wpdb;
1082
+ $query = $wpdb->prepare('SELECT count(*) FROM '.$wpdb->commentmeta.' m JOIN '.$wpdb->comments.' c ON m.comment_id = c.comment_ID WHERE m.meta_key = %s AND c.comment_approved = %s AND c.comment_date > NOW() - INTERVAL 14 DAY','cl_data','1');
1083
+ return intval($wpdb->get_var($query));
1084
+ }
1085
+ /** get_options
1086
+ * This function sets default options and handles a reset to default options
1087
+ * @param string $reset = 'no' - whether to return default settings
1088
+ * return array
1089
+ */
1090
+ function get_options($reset = 'no') {
1091
+ // see if we offer registration incentive
1092
+ $register_link = '';
1093
+ if(get_option('users_can_register')){
1094
+ $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
1095
+ }
1096
+ // default values
1097
+ $this->handle_load_domain ();
1098
+ $default = array ('version'=>$this->version,'enable'=>'yes','enable_for'=>'both', 'default_on' => 'on', 'default_on_admin'=>'on',
1099
+ 'badge_choice' => 'drop_down', 'badge_type'=>'default', 'link'=>'off','infopanel'=>'on', 'infoback'=>'white', 'infotext'=>'black',
1100
+ 'comment_text'=>'[name] '.__('recently posted',$this->plugin_domain).'...[lastpost]', 'whogets'=>'registered', 'dofollow' => 'registered',
1101
+ 'unreg_user_text'=>__('If you register as a user on my site, you can get your 10 most recent blog posts to choose from in this box.',$this->plugin_domain).' '.$register_link,
1102
+ 'unreg_user_text_panel'=>__('If this user had registered to my site then they could get 10 last posts to choose from when they comment and you would be able to see a list of their recent posts in this panel',$this->plugin_domain),'use_nonce'=>'on',
1103
+ 'template_insert'=>'','minifying'=>'','api_url'=>admin_url('admin-ajax.php'),'author_name'=>'author','email_name'=>'email','url_name'=>'url','comment_name'=>'comment',
1104
+ 'hide_link_no_url'=>'nothing','hide_link_no_url_match'=>'nothing');
1105
+ $options = get_option ( $this->db_option, $default);
1106
+ // return the options
1107
+ if($reset == 'yes'){
1108
+ return $default;
1109
+ }
1110
+ if(!$options['api_url']){
1111
+ $options['api_url'] = admin_url('admin-ajax.php');
1112
+ }
1113
+ if(!$options['enable']){
1114
+ $options['enable'] = 'yes';
1115
+ }
1116
+
1117
+ return $options;
1118
+ }
1119
+ /** handle_load_domain
1120
+ * This function loads the localization files required for translations
1121
+ * It expects there to be a folder called /lang/ in the plugin directory
1122
+ * that has all the .mo files
1123
+ */
1124
+ function handle_load_domain() {
1125
+ // get current language
1126
+ $locale = get_locale ();
1127
+ // locate translation file
1128
+ $mofile = WP_PLUGIN_DIR . '/' . plugin_basename ( dirname ( __FILE__ ) ) . '/lang/' . $this->plugin_domain . '-' . $locale . '.mo';
1129
+ // load translation
1130
+ load_textdomain ( $this->plugin_domain, $mofile );
1131
+ }
1132
+ /** init
1133
+ * This function registers styles and scripts
1134
+ */
1135
+ function init(){
1136
+ wp_register_style( 'commentluv_style',$this->plugin_url.'css/commentluv.css' , $this->version);
1137
+ wp_register_script( 'commentluv_script', $this->plugin_url.'js/commentluv.js',array('jquery'),$this->version );
1138
+ }
1139
+ /** install
1140
+ * This function is called when the plugin activation hook is fired when
1141
+ * the plugin is first activated or when it is auto updated via admin.
1142
+ * use it to make any changes needed for updated version or to add/check
1143
+ * new database tables on first install.
1144
+ */
1145
+ function install(){
1146
+ $options = $this->get_options();
1147
+ if(!$installed_version = get_option('cl_version')){
1148
+ // no installed version yet, set to version that was before big change
1149
+ $installed_version = 2.8;
1150
+ } else {
1151
+ // convert existing version to php type version number
1152
+ $installed_version = $this->php_version($installed_version);
1153
+ }
1154
+ // for version before 2.9
1155
+ if(version_compare($installed_version,'2.9','<')){
1156
+ // make any changes to this new versions options if needed and update
1157
+ update_option($this->db_option,$this->get_options('yes'));
1158
+ }
1159
+ // new addition to technical settings after 2.90.1 release
1160
+ if(version_compare($installed_version,'2.9.0.1','<')){
1161
+ $options['api_url'] = admin_url('admin-ajax.php');
1162
+ $options['enable'] = 'yes';
1163
+ update_option($this->db_option,$options);
1164
+ }
1165
+ // new check for use_nonce
1166
+ if(version_compare($installed_version,'2.94','<')){
1167
+ $options['use_nonce'] = 'on';
1168
+ update_option($this->db_option,$options);
1169
+ }
1170
+ // update cl_version in db
1171
+ if($this->php_version($this->version) != $installed_version){
1172
+ update_option('cl_version',$this->version);
1173
+ }
1174
+ // has the comment meta table?
1175
+ global $wpdb;
1176
+ $query = $wpdb->prepare("SHOW tables LIKE %s",$wpdb->commentmeta);
1177
+ $dbtable = $wpdb->get_var($query);
1178
+ //$o['dbtable'] = $dbtable;
1179
+ if(!$dbtable){
1180
+ add_action('admin_notices',create_function('','echo "<div class=\"error\">'.__('Your Wordpress install is missing the <strong>wp_commentmeta</strong> table!',$pd).'<br>'.__(' CommentLuv cannot work without this table please see this wordpress forum post to learn how to add one ->',$pd).'<a target=\"_blank\" href=\"http://wordpress.org/support/topic/wp_commentmeta-table-a39xxxx2_blogwp_commentmeta-doesnt-exist?replies=7#post-1378281\">'.__('Missing wp_commentmeta table',$pd).'</a></div>";'));
1181
+ }
1182
+ }
1183
+ /**
1184
+ * helper function called by mulitple functions
1185
+ * used to determine if commentluv is enabled
1186
+ */
1187
+ function is_enabled(){
1188
+ $options = $this->get_options();
1189
+ // see if we need to add here or not
1190
+ if(($options['enable_for'] == 'posts' && is_page()) || ($options['enable_for'] == 'pages' && !is_page())){
1191
+ return false;
1192
+ }
1193
+ if($options['enable'] != 'yes'){
1194
+ return false;
1195
+ }
1196
+ return true;
1197
+ }
1198
+ /**
1199
+ * called by apply_filter('kindergarten_html
1200
+ * Used to clean $input to only allow a kiddy set of html tags
1201
+ *
1202
+ * @param string $input - the string to be cleaned
1203
+ * @return string
1204
+ */
1205
+ function kindergarten_html($input){
1206
+ $allowedtags = array(
1207
+ 'h1' => array(),
1208
+ 'br' => array(),
1209
+ 'a' => array('href' => array(),'title' => array(),'rel' => array(),'target'=>array(), 'class'=>array()),
1210
+ 'small' =>array(),
1211
+ 'p' =>array( 'class'=>array()),
1212
+ 'strong' => array(),
1213
+ 'img' => array('src' => array(),'alt' => array(),'width' => array(),'height' => array(),'align'=> array()),
1214
+ 'span' => array('class'=>array())
1215
+ );
1216
+ return wp_kses($input,$allowedtags);
1217
+ }
1218
+ /**
1219
+ * Ajax handler for the subscribe button on the settings page.
1220
+ * called by add_action ( 'wp_ajax_notify_signup'
1221
+ */
1222
+ function notify_signup(){
1223
+ //DebugBreak();
1224
+ global $current_user;
1225
+ $email = $current_user->user_email;
1226
+ $firstname = $current_user->first_name;
1227
+ $url = 'http://contact.commentluv.com/subscribe';
1228
+ $list = 'pdYIXefvLNL38bE3fDcB3Q';
1229
+ // sendy
1230
+ if(!$firstname){
1231
+ $firstname = $current_user->user_nicename;
1232
+ }
1233
+ $response = wp_remote_post( $url, array(
1234
+ 'method' => 'POST',
1235
+ 'timeout' => 45,
1236
+ 'redirection' => 5,
1237
+ 'httpversion' => '1.0',
1238
+ 'blocking' => true,
1239
+ 'headers' => array(),
1240
+ 'body' => array( 'name' => $firstname, 'email' => $email ,'list'=>$list),
1241
+ 'cookies' => array()
1242
+ )
1243
+ );
1244
+ $return = array('success'=>true,'email'=>$email);
1245
+ // return response
1246
+ $response = json_encode($return);
1247
+ // response output
1248
+ header( "Content-Type: application/json" );
1249
+ echo $response;
1250
+ // IMPORTANT: don't forget to "exit"
1251
+ exit;
1252
+ }
1253
+ /** options_sanitize
1254
+ * This is the callback function for when the settings get saved, use it to sanitize options
1255
+ * it is called by the callback setting of register_setting in admin_init
1256
+ * @param mixed $options - the options that were POST'ed
1257
+ * return mixed $options
1258
+ */
1259
+ function options_sanitize($options){
1260
+ //DebugBreak();
1261
+ $old_options = $this->get_options();
1262
+ // if not enabled, only save that so other settings remain unchanged
1263
+ if($options['enable'] == 'no'){
1264
+ $old_options['enable'] = 'no';
1265
+ return $old_options;
1266
+ }
1267
+ // check for reset
1268
+ if(isset($options['reset'])){
1269
+ return $this->get_options('yes');
1270
+ }
1271
+ // if on multisite and this isnt super admin saving,
1272
+ // only allow kindergarten html.
1273
+ if(is_multisite() && !is_super_admin()){
1274
+ foreach($options as $key => $option){
1275
+ $options[$key] = apply_filters('kindergarten_html',$option);
1276
+ }
1277
+ }
1278
+ // add error notices if any
1279
+ $canreg = get_option('users_can_register');
1280
+ if($options['whogets']=='registered' && !$canreg){
1281
+ add_settings_error('whogets','whogets',__('Warning! You have set to show 10 posts for registered users but you have not enabled user registrations on your site. You should change the operational settings in the CommentLuv settings page to show 10 posts for everyone or enable user registrations',$this->plugin_domain),'error');
1282
+ }
1283
+ return $options;
1284
+ }
1285
+ /**
1286
+ * converts a string into a php type version number
1287
+ * eg. 2.81.2 will become 2.8.1.2
1288
+ * used to prepare a number to be used with version_compare
1289
+ *
1290
+ * @param mixed $string - the version to be converted to php type version
1291
+ * @return string
1292
+ */
1293
+ function php_version($string){
1294
+ if(empty($string)){
1295
+ return;
1296
+ }
1297
+ $version = str_replace('.','',$string);
1298
+ $std = array();
1299
+ for($i=0; $i < strlen($version); $i++){
1300
+ $std[] = $version[$i];
1301
+ }
1302
+ $php_version = implode('.',$std);
1303
+ return $php_version;
1304
+ }
1305
+ /** commentluv_action
1306
+ * This function adds a link to the settings page for the plugin on the plugins listing page
1307
+ * it is called by add filter plugin_action_links
1308
+ * @param $links - the links being filtered
1309
+ * @param $file - the name of the file
1310
+ * return array - the new array of links
1311
+ */
1312
+ function plugin_action_link($links, $file) {
1313
+ $this_plugin = plugin_basename ( __FILE__ );
1314
+ if ($file == $this_plugin) {
1315
+ $links [] = "<a href='options-general.php?page={$this->slug}'>" . __ ( 'Settings', $this->plugin_domain ) . "</a>";
1316
+ }
1317
+ return $links;
1318
+ }
1319
+ /**
1320
+ * Detects if a commentluv api or plugin is requesting a feed
1321
+ * and sends back an xml feed of the post titles and links that were found for the query
1322
+ * called by add_filter('found_posts' so we always have the posts found for the requested category/author/tag/ etc
1323
+ * @param (int) $foundposts - the number of posts that were found
1324
+ * @param (obj) $object - the query object
1325
+ * @return $foundposts - need to return this if the request is not from a commentluv api or plugin
1326
+ *
1327
+ * deprecated in 2.90.9.9 due to new 3.4 wp query code messing up with static homepages.
1328
+ * have to use just 10 recent posts, does not detect author or category urls now. (no one uses them!)
1329
+ */
1330
+ function send_feed($foundposts,$object){
1331
+ if(headers_sent() == true){
1332
+ return $foundposts;
1333
+ }
1334
+ $options = $this->get_options();
1335
+ // check if detection disabled
1336
+ if(isset($options['disable_detect']) && $options['disable_detect'] == 'on'){
1337
+ return $foundposts;
1338
+ }
1339
+ if($this->is_commentluv_request === true){
1340
+ // is commentluv useragent (set in init action)
1341
+ // get rid of any output (prevents some themes on some hosts from outputting code before commentluv can show xml feed)
1342
+ ob_clean();
1343
+ }
1344
+ $error = false;
1345
+ if($foundposts < 1 && ! $object->is_home){
1346
+ $error = true;
1347
+ }
1348
+ $enabled = $options['enable'];
1349
+
1350
+ // General checking
1351
+ if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match("/Commentluv/i", $_SERVER['HTTP_USER_AGENT'])) {
1352
+ if($object->is_home){
1353
+ // we're on the home page so just get the last 10 posts (prevents a slider or other featured posts widget from making the object full of the featured posts)'
1354
+ wp_reset_query();
1355
+ $query = new WP_Query();
1356
+ remove_filter('found_posts',array(&$this,'send_feed'),-1,2);
1357
+ $object->posts = $query->query('showposts=10&post_type=post');
1358
+ }
1359
+ $feed = '<?xml version="1.0" encoding="'.get_bloginfo('charset').'" ?>
1360
+ <rss version="2.0">
1361
+ <channel>
1362
+ <title><![CDATA['. get_bloginfo('title') .']]></title>
1363
+ <link>'. home_url() .'</link>
1364
+ <description><![CDATA['. get_bloginfo('description') .']]></description>
1365
+ <language>'.get_bloginfo('language').'</language>
1366
+ <generator>commentluv?v='.$this->version.'</generator>
1367
+ <commentluv>'.$enabled.'</commentluv>
1368
+ <success>'.$error.'</success>';
1369
+ if($object->posts){
1370
+ foreach($object->posts as $post){
1371
+ $feed .= '<item><title><![CDATA['.get_the_title($post->ID).']]></title>
1372
+ <link>'.get_permalink($post->ID).'</link>
1373
+ <type>blog</type>
1374
+ </item>';
1375
+ }
1376
+ } else {
1377
+ $feed .= '<item><title>'.__('No Posts Were Found!',$pd).'</title>
1378
+ <link>'.get_permalink($post->ID).'</link>
1379
+ </item>';
1380
+ }
1381
+ $feed .= '</channel></rss>';
1382
+ header("Content-Type: application/xml; charset=".get_bloginfo('charset'));
1383
+ echo $feed;
1384
+ exit;
1385
+ }
1386
+ return $foundposts;
1387
+ }
1388
+ /** send back a feed when another commentluv is asking
1389
+ * called by add_action(template_redirect) in detect_useragent
1390
+ *
1391
+ */
1392
+ function send_feed_file(){
1393
+ // /debugbreak();
1394
+ $options = $this->get_options();
1395
+ $postquery = array('numberposts'=>10,'post_type'=>'post');
1396
+ if(is_category()){
1397
+ $cat = get_query_var('cat');
1398
+ $postquery['category']=$cat;
1399
+ }
1400
+ if(is_author()){
1401
+ $author = get_query_var('author');
1402
+ $postquery['author'] = $author;
1403
+ }
1404
+ if(is_tag()){
1405
+ $tag = get_query_var('tag');
1406
+ $postquery['tag'] = $tag;
1407
+ }
1408
+ $posts = get_posts($postquery);
1409
+ $enabled = $this->is_enabled();
1410
+ $error = 'false';
1411
+ if(sizeof($posts) < 1){
1412
+ $error = 'true';
1413
+ }
1414
+ $feed = '<?xml version="1.0" encoding="'.get_bloginfo('charset').'" ?>'.
1415
+ '<rss version="2.0">'.
1416
+ '<channel>'.
1417
+ '<title><![CDATA['. get_bloginfo('title') .']]></title>'.
1418
+ '<link>'. get_bloginfo('url') .'</link>'.
1419
+ '<description><![CDATA['. get_bloginfo('description') .']]></description>'.
1420
+ '<language>'.get_bloginfo('language').'</language>'.
1421
+ '<generator>commentluv?v='.$this->version.'</generator>'.
1422
+ '<commentluv>'.$enabled.'</commentluv>'.
1423
+ '<success>'.$error.'</success>';
1424
+ if(is_array($posts)){
1425
+ foreach($posts as $post){
1426
+ $title = get_the_title($post->ID);
1427
+ //$feed .= '<item><title>'.strip_tags($title).'</title>'.
1428
+ $feed .= '<item><title><![CDATA['.$title.']]></title>'.
1429
+ '<link>'.get_permalink($post->ID).'</link>'.
1430
+ '<type>blog</type>'.
1431
+ '</item>';
1432
+ }
1433
+ } else {
1434
+ $feed .= '<item><title>'.__('No Posts Were Found!',$pd).'</title>'.
1435
+ '<link>'.get_permalink($post->ID).'</link>'.
1436
+ '</item>';
1437
+ }
1438
+ $feed .= '</channel></rss>';
1439
+ ob_end_clean();
1440
+ // force utf characters
1441
+ if(isset($options['utf8']) && $options['utf8'] == 'on'){
1442
+ // do nothing if set to disable utf8 encoding
1443
+ } else {
1444
+ // $feed = utf8_encode($feed); // removing this for now (2.94.7+)
1445
+ }
1446
+ header("Content-Type: application/atom+xml; charset=".get_bloginfo('charset'));
1447
+ echo $feed;
1448
+ exit;
1449
+
1450
+ }
1451
+ /**
1452
+ * called by __construct
1453
+ * used to setup hooks and filters for enabled plugin
1454
+ */
1455
+ function setup_hooks(){
1456
+ add_action ( 'comment_form',array(&$this,'add_fields')); // add fields to form
1457
+ add_action ( 'wp_print_styles',array(&$this,'add_style')); // add style
1458
+ add_action ( 'template_redirect',array(&$this,'add_script')); // add commentluv script
1459
+ add_action ( 'admin_print_scripts-edit-comments.php', array (&$this, 'add_removeluv_script') ); // add the removeluv script to admin page
1460
+ add_action ( 'wp_footer',array(&$this,'add_footer')); // add localize to footer
1461
+
1462
+ add_action ( 'wp_insert_comment', array (&$this, 'comment_posted'),1,2); // add member id and other data to comment meta priority 1, 2 vars
1463
+ if(!is_admin()){
1464
+ add_filter ( 'comments_array', array (&$this, 'do_shortcode' ), 1 ); // add last blog post data to comment content
1465
+ } else {
1466
+ add_filter ( 'comment_text', array (&$this, 'do_shortcode' ), 1 ); // add last blog post data to comment content on admin screen
1467
+ }
1468
+ add_filter ( 'comment_row_actions', array (&$this,'add_removeluv_link')); // adds a link to remove the luv from a comment on the comments admin screen
1469
+ }
1470
+ /**
1471
+ * called by add_action('admin_notices in admin_init()
1472
+ * Used to show a notice if there is a new version of CommentLuv available
1473
+ */
1474
+ function show_upgrade_notice(){
1475
+ $options = $this->get_options();
1476
+ $update_url = wp_nonce_url('update.php?action=upgrade-plugin&amp;plugin=commentluv%2Fcommentluv.php', 'upgrade-plugin_commentluv/commentluv.php');
1477
+ echo '<div id="clupgrade" class="update-nag">';
1478
+ if($options['upgrade_message']){
1479
+ echo $options['upgrade_message'];
1480
+ $details_link = '<br /><a href="'.admin_url().'plugin-install.php?tab=plugin-information&amp;plugin=commentluv&amp;TB_iframe=true&amp;width=640&amp;height=350" class="thickbox" title="commentluv"> View new version details</a>';
1481
+ printf( __('%s or <a href="%s">update now</a>.', $this->plugin_domain), $details_link, $update_url ) ;
1482
+ } else {
1483
+ echo __('There is a new version of Commentluv available, please upgrade by visiting this site',$this->plugin_domain);
1484
+ echo '<br><a href="http://www.commentluv.com" target="_blank">www.commentluv.com</a>';
1485
+ }
1486
+ //echo '<span style="float:right"><a href="'.admin_url('options-general.php?page='.$this->slug.'&dismiss=true').'">'.__('Dismiss notice',$this->plugin_domain).'</a></span>';
1487
+ echo '</div>';
1488
+ }
1489
+
1490
+ /** options_page
1491
+ * This function shows the page for saving options
1492
+ * it is called by add_options_page
1493
+ * You can echo out or use further functions to display admin style widgets here
1494
+ */
1495
+ function options_page(){
1496
+ $o = $this->get_options();
1497
+ $dbo = $this->db_option;
1498
+ $pd = $this->plugin_domain;
1499
+ $badges = array('default_image'=>'CL91_default.png','default'=>'CL91_default.png','white'=>'CL91_White.gif','black'=>'CL91_Black.gif','none'=> 'nothing.gif');
1500
+ //DebugBreak();
1501
+ // remove notice if requested
1502
+ if(isset($_GET['dismiss'])){
1503
+ unset($o['upgrade']);
1504
+ if(array_key_exists('upgrade_message',$o)){
1505
+ unset($o['upgrade_message']);
1506
+ }
1507
+ update_option($this->db_option,$o);
1508
+ echo '<script>jQuery("#clupgrade").hide()</script>';
1509
+ }
1510
+ ?>
1511
+ <div class="wrap">
1512
+ <h2><?php _e('CommentLuv Settings v',$this->plugin_domain);?><?php echo $this->version;?></h2>
1513
+ <div id="poststuff" style="margin-top:10px; ">
1514
+ <div id="mainblock" style="float: left; width:78%">
1515
+ <form method="post" action="options.php">
1516
+ <?php settings_fields( 'commentluv_options_group' ); // the name given in admin init
1517
+ // after here, put all the inputs and text fields needed
1518
+ ?>
1519
+ <div class="dbx-content">
1520
+ <table class="widefat">
1521
+ <thead>
1522
+ <tr><th scope="col"><?php _e('Important!',$pd);?></th><th><?php _e('Subscription Information',$pd);?></th></tr>
1523
+ </thead>
1524
+ <tbody>
1525
+ <tr>
1526
+ <td width="250">
1527
+ <h2 style="margin: 0 0 10px 0;"><?php _e('CommentLuv 3.0 Premium is here!',$pd);?> <a style="font-size:0.8em" title="Premium has some excellent features! try it out today. Full 30 day gaurantee" target="_blank" href="http://ql2.me/upgradetopremium">Upgrade to Premium</a></h2>
1528
+ <img align="left" src="<?php echo $this->plugin_url;?>images/privacy-guarantee.png"/><?php _e('I promise not to sell your details or send you spam. You will ONLY receive emails about plugin updates and the 10 week free course.',$pd);?>
1529
+ </td>
1530
+ <td>
1531
+ <p><?php _e('Do you like CommentLuv? How about an even better version with much more control over dofollow and some awesome social enticements that will make your posts go viral by offering your readers more choice of posts if they +1, Like or tweet your post? Get CommentLuv Premium Today! Free plugin and 10 week blogging course delivered by email. (10 week course is free of charge,it is no obligation premium content. It was supposed to be a premium product but I decided to give it away for free. (see why in the first email).)',$pd);?></p>
1532
+ <?php
1533
+ if(isset($o['subscribed'])){
1534
+ echo '<div class="submit">'.__('You have already subscribed, if you have not received the verification within 12 hours, please click the button to resend or try the form at',$pd).' <a target="_blank" href="http://www.commentluv.com/">www.commentluv.com</a><br><input style="margin:0 auto; display: block;" type="button" id="cl_notify" value="'.__('Resend Verification',$pd).'"/></div>';
1535
+ } else {
1536
+ echo '<div class="submit" style=" background-color: green; padding-left: 5px; padding-right: 5px; border-radius: 15px; -moz-border-radius: 15px; text-align: center;"><input style="margin: 0 auto; display:block" id="cl_notify" type="button" name="cl_notify" value="'.__('Click for a special offer!',$pd).'" /></div>';
1537
+ }
1538
+ ?>
1539
+ <div id="notify_message"></div>
1540
+ </td>
1541
+ </tr>
1542
+ <tr>
1543
+ <td colspan="2">
1544
+ <?php _e('<b>Are you getting targeted by spammers?</b> CommentLuv links are valuable which is why it promotes comments but some nasty spammers try to take advantage of this by leaving spam just to get the link. Don\'t worry, there is answer!... you can get CommentLuv Premium which has advanced anti-spam features which has been proven to almost eliminate spam on users blogs. You can upgrade by clicking the link above. <p><b>Not ready to buy premium yet?</b> that\'s ok too! Why not try GASP which is a lite version of the anti spam plugin that CommentLuv Premium uses. You can get it for FREE by searching for GASP in your "add new" section of your plugins page in your dashboard.',$pd);?>
1545
+ </td>
1546
+ </tr>
1547
+ </tbody>
1548
+ </table>
1549
+
1550
+
1551
+ <br/>
1552
+
1553
+
1554
+ <table class="widefat">
1555
+ <thead>
1556
+ <tr><th><?php _e('Primary Setting',$pd);?></th><th colspan="3"></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th></tr>
1557
+ </thead>
1558
+ <tbody>
1559
+ <tr>
1560
+ <td colspan="2" style="width: 40%; vertical-align: middle; text-align: center; font-size: 1.3em; font-weight: bolder;"><label for="<?php echo $dbo;?>[enable]"><?php _e('Enable CommentLuv?',$pd);?></label></td>
1561
+ <td style="width:20%; vertical-align: middle; font-size: 1.3em;"><input class="clenable" type="radio" name="<?php echo $dbo;?>[enable]" value="yes" <?php checked($o['enable'],'yes');?>/><?php _e('Yes',$pd);?></td>
1562
+ <td style="width:20%; vertical-align: middle; font-size: 1.3em;"><input class="clenable" type="radio" name="<?php echo $dbo;?>[enable]" value="no" <?php checked($o['enable'],'no');?>/><?php _e('No',$pd);?></td>
1563
+ <td style="text-align: center; border: 2px dotted;"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>primarysettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1564
+ </tr>
1565
+ <tr class="ifenable">
1566
+ <td style="text-align: center;" colspan="5">
1567
+ <input type="radio" name="<?php echo $dbo;?>[enable_for]" value="posts" <?php checked($o['enable_for'],'posts');?>/><?php _e('On Posts',$pd);?>
1568
+ <input style="margin-left: 100px;" type="radio" name="<?php echo $dbo;?>[enable_for]" value="pages" <?php checked($o['enable_for'],'pages');?>/><?php _e('On Pages',$pd);?>
1569
+ <input style="margin-left: 100px;" type="radio" name="<?php echo $dbo;?>[enable_for]" value="both" <?php checked($o['enable_for'],'both');?>/><?php _e('On Both',$pd);?>
1570
+ </td>
1571
+ </tr>
1572
+ <tr class="ifenable">
1573
+ <td style="text-align: center;" colspan="2">
1574
+ <input type="checkbox" name="<?php echo $dbo;?>[default_on]" <?php if(isset($o['default_on'])) checked($o['default_on'],'on');?> value="on"/> <label for="<?php echo $dbo;?>[default_on]"><?php _e('On by default?',$pd);?></label>
1575
+ </td>
1576
+ <td></td>
1577
+ <td style="text-align: center;" colspan="2">
1578
+ <input type="checkbox" name="<?php echo $dbo;?>[default_on_admin]" <?php if(isset($o['default_on_admin'])) checked($o['default_on_admin'],'on');?> value="on"/><label for="<?php echo $dbo;?>[default_on_admin]"> <?php _e('On for admin?',$pd);?></label>
1579
+ </td>
1580
+ </tr>
1581
+ </tbody>
1582
+ </table>
1583
+
1584
+
1585
+ <br>
1586
+
1587
+
1588
+ <table class="widefat ifenable display-settings">
1589
+ <thead>
1590
+ <tr><th><?php _e('Appearance',$pd);?></th><th colspan="3"></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th></tr>
1591
+ </thead>
1592
+ <tbody>
1593
+ <tr>
1594
+ <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Badge',$pd);?></label></h3></td>
1595
+ <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Custom Image URL',$pd);?></label></h3></td>
1596
+ <td><h3><label for="<?php echo $dbo;?>[badge_choice]"><?php _e('Use Text',$pd);?></label></h3></td>
1597
+ <td></td>
1598
+ <td></td>
1599
+ </tr>
1600
+ <tr>
1601
+ <td>
1602
+ <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="drop_down" <?php checked($o['badge_choice'],'drop_down');?>/>
1603
+ <select id="badge_type" name="<?php echo $dbo;?>[badge_type]">
1604
+ <option value="default_image" <?php selected($o['badge_type'],'default_image');?>><?php _e('Default',$pd);?></option>
1605
+ <option value="white" <?php selected($o['badge_type'],'white');?>><?php _e('White',$pd);?></option>
1606
+ <option value="black" <?php selected($o['badge_type'],'black');?>><?php _e('Black',$pd);?></option>
1607
+ <option value="none" <?php selected($o['badge_type'],'none');?>><?php _e('None',$pd);?></option>
1608
+ </select>
1609
+
1610
+ <p style="margin: 8px 0px 0px 8px;"><img id="display_badge" style="border: 1px solid #000; padding: 3px;" src="<?php echo $this->plugin_url;?>images/<?php echo $badges[$o['badge_type']];?>"/></p>
1611
+ </td>
1612
+ <td>
1613
+ <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="custom" <?php checked($o['badge_choice'],'custom');?>/>
1614
+ <input type="text" name="<?php echo $dbo;?>[custom_image_url]" value="<?php if(isset($o['custom_image_url'])) echo $o['custom_image_url'];?>"/>
1615
+ <?php
1616
+ if(isset($o['custom_image_url']) && $o['custom_image_url'] != ''){
1617
+ // show image
1618
+ echo '<p style="margin: 8px 0px 0px 8px;"><img id="custom_badge" style="border: 1px solid #000; padding: 3px;" src="'.$o['custom_image_url'].'"/></p>';
1619
+ } ?>
1620
+ </td>
1621
+ <td>
1622
+
1623
+ <input type="radio" class="radio" name="<?php echo $dbo;?>[badge_choice]" value="text" <?php checked($o['badge_choice'],'text');?>/>
1624
+ <input type="text" name="<?php echo $dbo;?>[badge_text]" value="<?php if(isset($o['badge_text'])) echo $o['badge_text'];?>"/>
1625
+ <p style="margin: 8px 0px 0px 8px;"><input type="checkbox" name="<?php echo $dbo;?>[link]" value="on" <?php if(isset($o['link'])) checked($o['link'],'on');?>/> <label for="<?php echo $dbo;?>[link]"><?php _e('Link to Commentluv?',$pd);?></label>
1626
+ </td>
1627
+ <td></td>
1628
+ <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>appearancesettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1629
+ </tr>
1630
+
1631
+ <tr>
1632
+ <td><br><input type="checkbox" name="<?php echo $dbo;?>[infopanel]" <?php checked($o['infopanel'],'on');?> value="on"/><label for="<?php echo $dbo;?>[infopanel]"> <?php _e('Enable info panel?',$pd);?></label></td>
1633
+ <td><label for="<?php echo $dbo;?>[infoback]"><?php _e('Info panel background color',$pd);?></label><br><input type="text" size="6" name="<?php echo $dbo;?>[infoback];?>" value="<?php echo $o['infoback'];?>"/></td>
1634
+ <td><label for="<?php echo $dbo;?>[infotext]"><?php _e('Info panel text color',$pd);?></label><br><input type="text" size="6" name="<?php echo $dbo;?>[infotext];?>" value="<?php echo $o['infotext'];?>"/></td>
1635
+ <td></td>
1636
+ <?php
1637
+ $tdstyle = '"border: 1px solid #dfdfdf; vertical-align: middle; text-align: center; background-color: '.$o['infoback'].'"';
1638
+ $spanstyle = '"color: '.$o['infotext'].'"';
1639
+ ?>
1640
+ <td style=<?php echo $tdstyle;?>><span style=<?php echo $spanstyle;?>><?php _e('Example text and background color',$pd);?></span></td>
1641
+ </tr>
1642
+ </tbody>
1643
+ </table>
1644
+
1645
+ <br>
1646
+
1647
+ <table class="widefat ifenable messages">
1648
+ <thead>
1649
+ <tr>
1650
+ <th colspan="2"><?php _e('Messages',$pd);?></th><th scope="col"></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1651
+
1652
+ </tr>
1653
+ </thead>
1654
+ <tbody>
1655
+ <tr>
1656
+ <td colspan="2">
1657
+ <label for="<?php echo $dbo;?>[comment_text]"><?php _e('Text to be displayed in the comment',$pd);?></label>
1658
+ <br><input type="text" style="width: 95%" name="<?php echo $dbo;?>[comment_text]" value="<?php echo $o['comment_text'];?>"/>
1659
+ </td>
1660
+ <td style="border: 1px dashed #dfdfdf;"><?php _e('[name] = The users name',$this->plugin_domain);?><br><?php _e('[lastpost] = The last blog post link',$this->plugin_domain);?></td>
1661
+ <td>&nbsp;</td>
1662
+ <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>messagessettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1663
+ </tr>
1664
+ <tr>
1665
+ <td colspan="3">
1666
+
1667
+ <?php _e('Message for unregistered user in the drop down box',$pd);?>
1668
+ <br>(<?php _e('Message will not be shown if you do not have registrations enabled',$this->plugin_domain);?>)
1669
+ <br><textarea rows="5" style="width: 95%" name="<?php echo $dbo;?>[unreg_user_text]"><?php echo $o['unreg_user_text'];?></textarea>
1670
+ <?php
1671
+ if(get_option('users_can_register')){
1672
+ _e('Your register link code',$pd);
1673
+ echo '<br>';
1674
+ _e('(this will be automatically added if you have not added it yourself to the textarea above)',$pd);
1675
+ $register_link = apply_filters('register','<a href="' . site_url('wp-login.php?action=register', 'login') . '">' . __('Register') . '</a>');
1676
+ echo ' : <input style="width:95%" type="text" value="'.htmlspecialchars($register_link).'" disabled/>';
1677
+ }
1678
+ ?>
1679
+ </td>
1680
+ <td colspan="2" style="width:125px;">
1681
+ <?php // show warning if registration is not enabled
1682
+ if(!get_option('users_can_register')){
1683
+ echo '<div style="border: 2px dashed red;">';
1684
+ _e('You have NOT set your blog to allow registrations, you can do that in Settings/General',$pd);
1685
+ echo ' <a href="'.admin_url('options-general.php').'">'.__('here',$pd).'</a>';
1686
+ echo '</div>';
1687
+ }
1688
+ ?>
1689
+ </td>
1690
+ </tr>
1691
+ <tr>
1692
+ <td colspan="3">
1693
+ <?php _e('Message for unregistered user in the info panel',$pd);?>
1694
+ <br>(<?php _e('Message will not be shown if you do not have registrations enabled',$this->plugin_domain);?>)
1695
+ <br><textarea rows="5" style="width:95%;" name="<?php echo $dbo;?>[unreg_user_text_panel]"><?php echo $o['unreg_user_text_panel'];?></textarea>
1696
+ </td>
1697
+ <td></td>
1698
+ <td></td>
1699
+ </tr>
1700
+ </tbody>
1701
+ </table>
1702
+
1703
+ <br>
1704
+
1705
+ <table class="widefat ifenable operational-settings">
1706
+ <thead>
1707
+ <tr>
1708
+ <th colspan="2"><?php _e('Operational Settings',$pd);?></th><th scope="col"></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1709
+
1710
+ </tr>
1711
+ </thead>
1712
+ <tbody>
1713
+ <tr>
1714
+ <td colspan="4">
1715
+ <?php _e('Who to give 10 last posts to choose from when they comment?',$pd);?>
1716
+ <p><input type="radio" name="<?php echo $dbo;?>[whogets]" value="registered" <?php checked($o['whogets'],'registered');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Only Registered Members',$pd);?></label>
1717
+ <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[whogets]" value="everybody" <?php checked($o['whogets'],'everybody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Everybody',$pd);?></label>
1718
+ <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[whogets]" value="nobody" <?php checked($o['whogets'],'nobody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Nobody',$pd);?></label>
1719
+
1720
+ </td>
1721
+ <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>operationalsettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1722
+ </tr>
1723
+ <tr>
1724
+ <td colspan="5">
1725
+ <?php _e('Whose links should be dofollow?',$pd);?>
1726
+ <p><input type="radio" name="<?php echo $dbo;?>[dofollow]" value="registered" <?php checked($o['dofollow'],'registered');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Only Registered Members Links',$pd);?></label>
1727
+ <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[dofollow]" value="everybody" <?php checked($o['dofollow'],'everybody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Everybody gets dofollow links',$pd);?></label>
1728
+ <input style="margin-left: 25px;" type="radio" name="<?php echo $dbo;?>[dofollow]" value="nobody" <?php checked($o['dofollow'],'nobody');?>/> <label for="<?php echo $dbo;?>[whogets]"><?php _e('Nobody gets dofollow links',$pd);?></label>
1729
+ </td>
1730
+ </tr>
1731
+ </tbody>
1732
+ </table>
1733
+
1734
+ <br>
1735
+
1736
+ <table class="widefat ifenable technical" style="border: 3px solid red">
1737
+ <thead>
1738
+ <tr>
1739
+ <th colspan="2"><?php _e('Technical Settings',$pd);?></th><th scope="col"><span id="opentech" style="color: blue; cursor: pointer;"><?php _e('Click to open technical settings',$pd);?></span></th><th></th><th style="text-align: center;"><?php _e('Help Video',$pd);?></th>
1740
+
1741
+ </tr>
1742
+ </thead>
1743
+ <tbody id="techbody" style="display:none">
1744
+ <tr>
1745
+ <td colspan="4">
1746
+ <h3><?php _e('Please check the help video for this section before changing settings',$pd);?></h3>
1747
+ <?php _e('In most cases, you will NOT need to change the settings in this box unless you have a custom comment form, template or you are using minifying or caching plugins',$pd);?>
1748
+ </td>
1749
+ <td style="text-align: center; border: 2px dotted; width:125px"><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>technicalsettings.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonsmall.png"/></a></td>
1750
+ </tr>
1751
+ <tr>
1752
+ <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Compatibility',$pd);?></td>
1753
+ </tr>
1754
+ <tr>
1755
+ <td colspan="2">
1756
+ <input type="checkbox" name="<?php echo $dbo;?>[template_insert]" <?php if(isset($o['template_insert'])) checked($o['template_insert'],'on');?> value="on"/><label for="<?php echo $dbo;?>[template_insert]"> <?php _e('Use manual insert of badge code?',$pd);?></label>
1757
+ <br>( <strong>&lt;?php cl_display_badge(); ?&gt;</strong> )
1758
+ </td>
1759
+ <td>
1760
+ <input type="checkbox" name="<?php echo $dbo;?>[minifying]" <?php if(isset($o['minifying'])) checked($o['minifying'],'on');?> value="on"/><label for="<?php echo $dbo;?>[minifying]"> <?php _e('Enable minifying compatibility?',$pd);?></label>
1761
+ <br><?php _e('For caching plugins (places localized code in footer)',$pd);?>
1762
+ </td>
1763
+ <td>
1764
+ <input type="checkbox" name="<?php echo $dbo;?>[utf8]" <?php if(isset($o['utf8'])) checked($o['utf8'],'on');?> value="on"/><label for="<?php echo $dbo;?>[utf8]"> <?php _e('Disable UTF8 encoding?',$pd);?></label>
1765
+ <br><?php _e('If you are having issues with accents not showing properly',$pd);?>
1766
+ </td>
1767
+ <td>
1768
+ <input type="checkbox" name="<?php echo $dbo;?>[disable_detect]" <?php if(isset($o['disable_detect'])) checked($o['disable_detect'],'on');?> value="on"/><label for="<?php echo $dbo;?>[disable_detect]"> <?php _e('Disable Detection?',$pd);?></label>
1769
+ <br><?php _e('For XML errors',$pd);?>
1770
+ </td>
1771
+ </tr>
1772
+ <tr>
1773
+ <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('API URL',$pd);?></td>
1774
+ </tr>
1775
+ <tr>
1776
+ <td colspan="4">
1777
+ <input type="text" size="60" name="<?php echo $dbo;?>[api_url]" value="<?php echo $o['api_url'];?>"/><label for="<?php echo $dbo;?>[api_url]"> <?php _e('URL to use for API',$pd);?></label>
1778
+ </td>
1779
+ </tr>
1780
+ <tr>
1781
+ <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Comment Form Field Values',$pd);?></td>
1782
+ </tr>
1783
+ <tr>
1784
+ <td colspan="2"><?php _e('Authors Name field name',$this->plugin_domain);?></td>
1785
+ <td colspan="2"><input type="text" value="<?php echo $o['author_name'];?>" name="<?php echo $dbo;?>[author_name]"/></td>
1786
+ <td></td>
1787
+ </tr>
1788
+ <tr>
1789
+ <td colspan="2"><?php _e('Email field name',$this->plugin_domain);?></td>
1790
+ <td colspan="2"><input value="<?php echo $o['email_name'];?>" type="text" name="<?php echo $dbo;?>[email_name]"/></td>
1791
+ <td></td>
1792
+ </tr>
1793
+ <tr>
1794
+ <td colspan="2"><?php _e('Authors URL field name',$this->plugin_domain);?></td>
1795
+ <td colspan="2"><input value="<?php echo $o['url_name'];?>" type="text" name="<?php echo $dbo;?>[url_name]"/></td>
1796
+ <td></td>
1797
+ </tr>
1798
+ <tr>
1799
+ <td colspan="2"><?php _e('Comment Text Area name',$this->plugin_domain);?></td>
1800
+ <td colspan="2"><input value="<?php echo $o['comment_name'];?>" type="text" name="<?php echo $dbo;?>[comment_name]"/></td>
1801
+ <td></td>
1802
+ </tr>
1803
+ <tr>
1804
+ <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Extras',$pd);?></td>
1805
+ </tr>
1806
+ <tr>
1807
+ <td colspan="2">
1808
+ <select name="<?php echo $dbo;?>[hide_link_no_url]">
1809
+ <option value="nothing" <?php selected($o['hide_link_no_url'],'nothing',true);?>><?php _e('Nothing',$this->plugin_domain);?></option>
1810
+ <option value="on" <?php selected($o['hide_link_no_url'],'on',true);?>><?php _e('Hide Link',$this->plugin_domain);?></option>
1811
+ <option value="spam" <?php selected($o['hide_link_no_url'],'spam',true);?>><?php _e('Spam Comment',$this->plugin_domain);?></option>
1812
+ <option value="delete" <?php selected($o['hide_link_no_url'],'delete',true);?>><?php _e('Delete Comment',$this->plugin_domain);?></option>
1813
+ </select>
1814
+ <br/><label for="<?php echo $dbo;?>[hide_link_no_url]"><?php _e('Action to take if comment has no Author URL',$this->plugin_domain);?></label>
1815
+ <br /><strong>(<?php _e('Prevents spammer abuse',$this->plugin_domain);?>)</strong>
1816
+
1817
+ </td>
1818
+
1819
+ <td>
1820
+ <select name="<?php echo $dbo;?>[hide_link_no_url_match]">
1821
+ <option value="nothing" <?php selected($o['hide_link_no_url_match'],'nothing',true);?>><?php _e('Nothing',$this->plugin_domain);?></option>
1822
+ <option value="on" <?php selected($o['hide_link_no_url_match'],'on',true);?>><?php _e('Hide Link',$this->plugin_domain);?></option>
1823
+ <option value="spam" <?php selected($o['hide_link_no_url_match'],'spam',true);?>><?php _e('Spam Comment',$this->plugin_domain);?></option>
1824
+ <option value="delete" <?php selected($o['hide_link_no_url_match'],'delete',true);?>><?php _e('Delete Comment',$this->plugin_domain);?></option>
1825
+ </select>
1826
+ <br/><label for="<?php echo $dbo;?>[hide_link_no_url_match]"><?php _e('Action to take if link does not match domain of author',$this->plugin_domain);?></label>
1827
+ <br /><strong>(<?php _e('Prevents users from adding fake author URLs to get around Akismet',$this->plugin_domain);?>)</strong>
1828
+
1829
+ </td>
1830
+
1831
+ <td>
1832
+ <input type="checkbox" name="<?php echo $dbo;?>[allow_jpc]" <?php if(isset($o['allow_jpc'])) checked($o['allow_jpc'],'on');?> value="on"/><label for="<?php echo $dbo;?>[allow_jpc]"> <?php _e('Allow Jetpack comments module to activate?',$pd);?></label>
1833
+ <br>
1834
+ <input type="checkbox" name="<?php echo $dbo;?>[use_nonce]" <?php if(isset($o['use_nonce'])) checked($o['use_nonce'],'on');?> value="on"/><label for="<?php echo $dbo;?>[use_nonce]"> <?php _e('Use security nonce for ajax calls? <br>(disable if you get Parsing JSON Request failed. error! not authorized error)',$pd);?></label>
1835
+ </td>
1836
+ </tr>
1837
+ <tr>
1838
+ <td style="background-color: #dfdfdf; text-align: center; font-weight: bolder;" colspan="5"><?php _e('Diagnostics Info',$pd);?></td>
1839
+ </tr>
1840
+ <tr>
1841
+ <td colspan="4"><textarea style="width: 99%" rows="5">
1842
+ <?php
1843
+ $options = $this->get_options();
1844
+ $options['version'] = $this->version;
1845
+ $options['home_url'] = get_home_url();
1846
+ $options['wp_version'] = get_bloginfo('version');
1847
+ $options['charset'] = get_bloginfo('charset');
1848
+ $options['curl'] = function_exists('curl_init')? 'yes': 'no';
1849
+
1850
+ print_r($options);
1851
+
1852
+ ?>
1853
+ </textarea>
1854
+ </td>
1855
+ <td>
1856
+ <?php _e('You can copy this information and send it to me if I request it',$pd);?>
1857
+ </td>
1858
+ </tr>
1859
+ </tbody>
1860
+ </table>
1861
+ <p></p>
1862
+ <table class="widefat">
1863
+ <tr>
1864
+ <td>
1865
+ <?php
1866
+ //debugbreak();
1867
+ // twitch ad?
1868
+ ?>
1869
+ <img src="<?php echo $this->plugin_url;?>images/logo-reveal-twitter-image.jpg"/>
1870
+ </td>
1871
+ <td>
1872
+ <h2>My Alter-ego</h2>
1873
+ <p>My new alter-ego is LoonyGeekFun on twitch. Since I was diagnosed with MS I have had to step away from making plugins and software apps so now, I make logos, banners and intro videos for my twitch followers.</p>
1874
+ <p>Please <a href="http://twitch.tv/LoonyGeekFun" title="click to visit my twitch channel">Visit My Channel (http://www.twitch.tv/LoonyGeekFun)</a> and get a video or intro done. (Perhaps even a promotional video for your blog, a video for your capture page or even pay to get a sales video!)</p>
1875
+ <p>I would love it if you could come along and say hi and that you use commentluv! </p>
1876
+ </td>
1877
+ </tr>
1878
+ </table>
1879
+
1880
+ </div>
1881
+ <div class="submit"><input class="button-primary" id="clsubmit" type="submit" name="Submit" value="<?php _e('Save Settings',$this->plugin_domain);?>" /></div>
1882
+ </form>
1883
+ <h3><?php _e('Reset Settings',$this->plugin_domain);?></h3>
1884
+ <form method="post" action="options.php">
1885
+ <?php settings_fields( 'commentluv_options_group' ); // the name given in admin init
1886
+ $javamsg = __('Are you sure you want to reset your settings? Press OK to continue',$this->plugin_domain);
1887
+ ?>
1888
+ <input type="hidden" name="<?php echo $this->db_option;?>[reset]" value="yes"/>
1889
+ <input style="background-color: red;" type="submit" onclick="<?php echo 'if(confirm(\''.$javamsg.'\') != true) { return false; } else { return true; } ';?>" value="<?php _e('Reset',$this->plugin_domain);?>" name="submit"/>
1890
+ </form>
1891
+
1892
+
1893
+ </div> <!-- end main block div -->
1894
+ <div style="float:left">
1895
+ <table class="widefat" style="width: 230px; margin-left: 10px;">
1896
+ <thead>
1897
+ <tr><th scope="col"><?php _e('Plugin Info',$this->plugin_domain);?></th><th>&nbsp;</th></tr>
1898
+ </thead>
1899
+ <tbody>
1900
+ <tr><td colspan="2"><div style="background: url(<?php echo $this->plugin_url;?>images/playbutton.png); text-align: center; font-size: 1.4em; width: 228px; height: 44px; overflow: hidden;"><br><?php _e('Start Here',$this->plugin_domain);?></div><div><a onclick="return false;" href="<?php echo $this->plugin_url . 'videos/'; ?>starthere.php?KeepThis=true&amp;TB_iframe=true&amp;height=355&width=545" class="thickbox"><img src="<?php echo $this->plugin_url;?>images/playbuttonfront.png"/></a></div></td></tr>
1901
+ <tr><td><strong><?php _e('Author',$this->plugin_domain);?>:</strong></td><td>Andy Bailey</td></tr>
1902
+ <tr><td><strong><?php _e('Home Page',$this->plugin_domain);?>:</strong></td><td><a title="<?php _e('Visit www.commentluv.com!',$this->plugin_domain);?>" href="http://www.commentluv.com/" target="_blank">commentluv.com</a></td></tr>
1903
+ <tr><td><strong><?php _e('Social',$this->plugin_domain);?>:</strong></td><td><a title="Follow CommentLuv on Twitter" href="http://twitter.com/commentluv/" target="_blank"><img src="<?php echo $this->plugin_url;?>images/twitter.png"/></a> <a title="Join me on LinkedIn" href="http://uk.linkedin.com/in/commentluv" target="_blank"><img src="<?php echo $this->plugin_url;?>images/linkedin.png"/></a> <a title="Join me on Facebook" href="http://www.facebook.com/CommentLuv" target="_blank"><img src="<?php echo $this->plugin_url;?>images/facebook.png"/></a></td></tr>
1904
+ <tr><td><strong><?php _e('Help',$this->plugin_domain);?>:</strong></td><td><a href="http://support.commentluv.com/" target="_blank"><?php _e('Help Desk',$this->plugin_domain);?></a></td></tr>
1905
+ <tr class="alt"><td colspan="2"><?php _e('Do you like this plugin?',$this->plugin_domain);?></td></tr>
1906
+ <tr><td colspan="2"><iframe src="http://www.facebook.com/plugins/likebox.php?href=http%3A%2F%2Fwww.facebook.com%2Fpages%2FCommentLuv%2F156438857738200&amp;width=210&amp;colorscheme=light&amp;show_faces=true&amp;stream=false&amp;header=false&amp;height=450" scrolling="no" frameborder="1" style="border:none; overflow:auto; width:210px; height:400px;" allowTransparency="true"></iframe></td></tr>
1907
+ <tr class="alt"><td colspan="2"><?php _e('News',$this->plugin_domain);?>:</td></tr>
1908
+ <tr><td colspan="2">
1909
+ <h3>I Started a twitch channel!</h3>
1910
+ <?php // enter twitch details here? ?>
1911
+ <a href="http://twitch.tv/loonygeekfun" target="_blank" title="visit my twitch channel!"><img width="200" src="<?php echo $this->plugin_url;?>images/twitch-avatar-new-andy-cartoon.png" alt="http://twitch.tv/loonygeekfun"/></a>
1912
+ </td></tr>
1913
+ <tr class="alt"><td colspan="2"><?php _e('Thanks to the following for translations',$this->plugin_domain);?>:</td></tr>
1914
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/it.png"/> <?php _e('Italian',$this->plugin_domain);?></td><td><a target="_blank" href="http://gidibao.net/">Gianni Diuno</a></td></tr>
1915
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/nl.png"/> <?php _e('Dutch',$this->plugin_domain);?></td><td><a target="_blank" href="http://wpwebshop.com/">Rene</a></td></tr>
1916
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/pl.png"/> <?php _e('Polish',$this->plugin_domain);?></td><td><a target="_blank" href="http://techformator.pl/">Mariusz Kolacz</a></td></tr>
1917
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ge.png"/> <?php _e('Georgian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.findmyhosting.com">Kasia Ciszewski</a></td></tr>
1918
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/lt.png"/> <?php _e('Lithuanian',$this->plugin_domain);?></td><td><a target="_blank" href="http://mantas.malcius.lt/">Mantas Malcius</a></td></tr>
1919
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/br.png"/> <?php _e('Portuguese',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.korvo.com.br/">Diego Uczak</a></td></tr>
1920
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/my.png"/> <?php _e('Malaysian',$this->plugin_domain);?></td><td><a target="_blank" href="http://ariffshah.com/">Ariff Shah</a></td></tr>
1921
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/in.png"/> <?php _e('Hindi',$this->plugin_domain);?></td><td><a target="_blank" href="http://outshinesolutions.com/">Outshine Solutions</a></td></tr>
1922
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/id.png"/> <?php _e('Indonesian',$this->plugin_domain);?></td><td><a target="_blank" href="http://rainerflame.com/">Mokhamad Oky</a></td></tr>
1923
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/cn.png"/> <?php _e('Chinese (s)',$this->plugin_domain);?></td><td><a target="_blank" href="http://obugs.net/">Third Eye</a></td></tr>
1924
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/es.png"/> <?php _e('Spanish',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.activosenred.com/">Valentin Yonte</a></td></tr>
1925
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/de.png"/> <?php _e('German',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.cloudliving.de/">Jan Ruehling</a></td></tr>
1926
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ir.png"/> <?php _e('Persian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.3eo.ir/">Amir heydari</a></td></tr>
1927
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ta.png"/> <?php _e('Tamil',$this->plugin_domain);?></td><td><a target="_blank" href="http://technostreak.com/">Tharun</a></td></tr>
1928
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ua.png"/> <?php _e('Ukranian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.designcontest.com/">Alyona Lompar</a></td></tr>
1929
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/lv.png"/> <?php _e('Latvian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.yourwebagency.co.uk/">Edgars Bergs</a></td></tr>
1930
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ro.png"/> <?php _e('Romanian',$this->plugin_domain);?></td><td><a target="_blank" href="http://obisnuit.eu/">Manuel Cheta</a></td></tr>
1931
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/no.png"/> <?php _e('Norwegian',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.drommeland.com/">Hanna</a></td></tr>
1932
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/fr.png"/> <?php _e('French',$this->plugin_domain);?></td><td><a target="_blank" href="http://etreheureux.fr/">Jean-Luc Matthys</a></td></tr>
1933
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/dk.png"/> <?php _e('Danish',$this->plugin_domain);?></td><td><a target="_blank" href="http://w3blog.dk/">Jimmy Sigenstroem</a></td></tr>
1934
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/ru.png"/> <?php _e('Russian',$this->plugin_domain);?></td><td><a target="_blank" href="http://lavo4nik.ru/">Max</a></td></tr>
1935
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/bd.png"/> <?php _e('Bengali',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.techmoody.com">Amrik Virdi</a></td></tr>
1936
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/il.png"/> <?php _e('Hebrew',$this->plugin_domain);?></td><td><a target="_blank" href="http://makemoneyim.com/">Tobi</a></td></tr>
1937
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/vn.png"/> <?php _e('Vietnamese',$this->plugin_domain);?></td><td><a target="_blank" href="http://thegioimanguon.com/">Xman</a></td></tr>
1938
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/hu.png"/> <?php _e('Hungarian',$this->plugin_domain);?></td><td><a target="_blank" href="http://no1tutorials.net/">Bruno</a></td></tr>
1939
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/sk.png"/> <?php _e('Slovak',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.brozman.sk/blog">Viliam Brozman</a></td></tr>
1940
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/rs.png"/> <?php _e('Serbian',$this->plugin_domain);?></td><td><a target="_blank" href="http://wpcouponshop.com/">Diana</a></td></tr>
1941
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/tr.png"/> <?php _e('Turkish',$this->plugin_domain);?></td><td><a target="_blank" href="http://hakanertr.wordpress.com/">Hakan</a></td></tr>
1942
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/sz.png"/> <?php _e('Swahili',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.purehcgdietdrops.com/blog/">Andrew Mwankiki</a></td></tr>
1943
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/th.png"/> <?php _e('Thai',$this->plugin_domain);?></td><td><a target="_blank" href="http://www.martinhurley.com/">Martin Hurley</a></td></tr>
1944
+
1945
+
1946
+ <tr><td><img src="<?php echo $this->plugin_url;?>images/sa.png"/> <?php _e('Arabic',$this->plugin_domain);?></td><td><!--<a target="_blank" href="http://www.melzarei.be/">Muhammad Elzarei</a>--></td></tr>
1947
+ <tr><td><strong><?php _e('Want your link here?',$this->plugin_domain);?></strong></td><td><a target="_blank" href="http://support.commentluv.com/ticket/knowledgebase.php?article=1"><?php _e('How To Submit A Translation',$this->plugin_domain);?></a></td></tr>
1948
+ <tr class="alt"><td colspan="2"><?php _e('Special thanks go to the following',$this->plugin_domain);?>:</td></tr>
1949
+ <tr><td><strong><?php _e('CSS Help',$this->plugin_domain);?>:</strong></td><td><a href="http://www.famousbloggers.net" target="_blank">Hesham Zebida</a></td></tr>
1950
+ <tr><td><strong><?php _e('Badge GFX',$this->plugin_domain);?>:</strong></td><td><a href="http://byteful.com/" target="_blank">Byteful Travel</a></td></tr>
1951
+ </tbody>
1952
+ </table>
1953
+ </div>
1954
+
1955
+
1956
+ </div>
1957
+ <div class="clear"></div>
1958
+ </div>
1959
+ <?php
1960
+
1961
+ }
1962
+
1963
+
1964
+ } // end class
1965
+ } // end if class not exists
1966
+ // Let's give commentluv plenty of room to work with
1967
+ $mem = abs(intval(@ini_get('memory_limit')));
1968
+ if( $mem and $mem < 128 ){
1969
+ @ini_set('memory_limit', '128M');
1970
+ }
1971
+ $clbadgeshown = false;
1972
+ // start commentluv class engines
1973
+ if (class_exists ( 'commentluv' )) :
1974
+ $commentluv = new commentluv ( );
1975
+ // confirm warp capability
1976
+ if (isset ( $commentluv )) {
1977
+ // engage
1978
+ register_activation_hook ( __FILE__, array (&$commentluv, 'install' ) );
1979
+ }
1980
+ endif;
1981
+
1982
+ function cl_display_badge(){
1983
+ global $commentluv;
1984
+ if(isset($commentluv)){
1985
+ $commentluv->display_badge();
1986
+ }
1987
+
1988
+ }
1989
  ?>
js/commentluv.js CHANGED
@@ -1,293 +1,336 @@
1
- // commentluv 2.92.8
2
- jQuery(document).ready(function(){
3
- // get the form object and fields
4
- var formObj = jQuery('#cl_post_title').parents('form');
5
- var urlObj = cl_settings['urlObj'] = jQuery("input[name='" + cl_settings['url'] + "']",formObj);
6
- var comObj = cl_settings['comObj'] = jQuery("textarea[name='" + cl_settings['comment'] + "']",formObj);
7
- var autObj = jQuery("input[name='" + cl_settings['name'] + "']",formObj);
8
- var emaObj = jQuery("input[name='" + cl_settings['email'] + "']",formObj);
9
- // setup localized object with temporary vars
10
- cl_settings['url_value'] = urlObj.val();
11
- cl_settings['fired'] = 'no';
12
- // set event listener for textarea focus
13
- comObj.focus(function(){
14
- cl_dostuff();
15
- });
16
- // set the event listener for the click of the checkbox
17
- jQuery('#doluv').click(function(){
18
- jQuery('#lastposts').hide();
19
- if(jQuery(this).is(":checked")){
20
- // was unchecked, now is checked
21
- jQuery('#mylastpost').fadeTo("fast",1);
22
- cl_settings['fired'] = 'no';
23
- cl_dostuff();
24
- } else {
25
- // was checked, user unchecked it so empty hidden fields in form
26
- jQuery('input[name="cl_post_title"]').val("");
27
- jQuery('input[name="cl_post_url"]').val("");
28
- jQuery('#mylastpost').fadeTo("slow",0.3);
29
- jQuery('#lastposts').empty();
30
- }
31
- });
32
- // click event for last blog post link
33
- jQuery('.cluv a').click(function(){
34
- var data = jQuery(this).attr('class').split(' ');
35
- // store click count
36
- jQuery.ajax({
37
- url: cl_settings['api_url'],
38
- type: 'POST',
39
- data: {'action': 'cl_ajax','cid': data[1],'_ajax_nonce':data[0],'cl_prem':jQuery(this).hasClass('p'),'url': jQuery(this).attr('href'),'do':'click'}
40
- });
41
- jQuery(this).attr('target','_blank');
42
- return true;
43
- });
44
- // hover event on heart
45
- if(cl_settings['infopanel'] == "on"){
46
- jQuery('.heart_tip_box').mouseenter(heart_big);
47
- }
48
- // hide/show showmore
49
- jQuery(document.body).click(function(){
50
- if(cl_settings['lastposts'] == 'showing'){
51
- jQuery('#lastposts').slideUp('',function(){cl_settings['lastposts'] = 'not'});
52
- }
53
- });
54
- jQuery('#showmorespan img').click(function(){
55
- if(cl_settings['lastposts'] == 'not'){
56
- jQuery('#lastposts').slideDown('',function(){cl_settings['lastposts'] = 'showing'});
57
- }
58
- });
59
- // clear hidden inputs on load
60
- jQuery('#cl_post_title,#cl_post_url,#cl_prem').val('');
61
- // set click on anywhere closes info box
62
- jQuery(document).click(heart_small);
63
- // add info panel to page
64
- jQuery("body").append('<span id="heart_tip_big" style="display: none;position:absolute; z-index: 1001; background-color: ' + cl_settings['infoback'] + '; color: ' + cl_settings['infotext'] + '; width: 62px;"></span>');
65
- // hover over to see raw file wrapper open
66
- //jQuery('.rawfilewrap').live('hover',function(){
67
- jQuery('#commentluv').on('hover','.rawfilewrap',function(){
68
- jQuery('.rawfile').toggle();
69
- });
70
-
71
- });
72
-
73
- /**
74
- * checks everything is in place for doing stuff
75
- * returns string 'ok' if, um, ok
76
- */
77
- function cl_docheck(){
78
- // checkbox check
79
- if(!jQuery('#doluv').is(':checked')){
80
- return 'not checked';
81
- }
82
- var url = cl_settings['urlObj'];
83
- var msg = jQuery('#cl_messages');
84
- msg.empty();
85
- url.removeClass('cl_error');
86
- // logged in user?
87
- var nourlmessage = cl_settings['no_url_message'];
88
- if(cl_settings['logged_in'] == '1'){
89
- nourlmessage = cl_settings['no_url_logged_in_message'];
90
- } else {
91
- // check if fb connect is active
92
- if(!cl_settings['urlObj'].is(':visible') && typeof FB != 'undefined'){
93
- var invisurl = cl_settings['urlObj'].remove();
94
- var invismsg = jQuery('#cl_messages').remove();
95
- cl_settings['comObj'].after('<br><span id="invisurl">').after(invismsg);
96
- jQuery('#invisurl').append('URL ').after(invisurl).append('</span>');
97
- }
98
-
99
- }
100
- // check that there is a value in the url field
101
- if(url.val().length > 1){
102
- // is value just http:// ?
103
- if(url.val().toLowerCase() == 'http://'){
104
- url.addClass('cl_error');
105
- cl_message(nourlmessage);
106
- return;
107
- }
108
- // is the http:// missing?
109
- if(url.val().toLowerCase().substring(0,7) != 'http://'){
110
- url.addClass('cl_error');
111
- cl_message(cl_settings['no_http_message']);
112
- return;
113
- }
114
- } else {
115
- // there is no value
116
- url.addClass('cl_error');
117
- cl_message(nourlmessage);
118
- return;
119
- }
120
- // if we are here, all is cool mon
121
- return 'ok';
122
- }
123
- /**
124
- * tries to fetch last blog posts for a url
125
- */
126
- function cl_dostuff(){
127
- if(cl_docheck() != 'ok'){
128
- return;
129
- }
130
- var url = cl_settings['urlObj'];
131
- if(cl_settings['fired'] == 'yes'){
132
- // already fired, fire again if current url is different to last fired
133
- if(url.val() == cl_settings['url_value']){
134
- return;
135
- }
136
- jQuery('#lastposts,#mylastpost').empty();
137
- }
138
- // fire the request to admin
139
- jQuery('#cl_messages').append('<img src="' + cl_settings['images'] + 'loader.gif' + '"/>').show();
140
- jQuery.ajax({
141
- url: cl_settings['api_url'],
142
- type: 'post',
143
- dataType: 'json',
144
- data: {'url':url.val(),'action':'cl_ajax','do':'fetch','_ajax_nonce':cl_settings._fetch},
145
- success: function(data){
146
- if(data.error == ''){
147
- // no error, fill up lastposts div with items returned
148
- jQuery('#cl_messages').empty().hide();
149
- jQuery.each(data.items,function(j,item){
150
- var title = item.title;
151
- var link = item.link;
152
- var count = '';
153
- jQuery('#lastposts').append('<span id="' + item.link + '" class="choosepost ' + item.type + '">' + title + '</span>');
154
- });
155
- // setup first link and hidden fields
156
- jQuery('#mylastpost').html('<a href="' + data.items[0].link +'"> ' + data.items[0]['title'] + '</a>').fadeIn(1000);
157
- jQuery('#cl_post_title').val(data.items[0].title);
158
- jQuery('#cl_post_url').val(data.items[0].link);
159
- jQuery('#cl_prem').val(data.items[0].p);
160
- // setup look and show dropdown
161
- jQuery('span.message').css({'backgroundColor':'#efefef','color':'black'});
162
- jQuery('#showmorespan img').show();
163
- if(cl_settings['comObj'].width() > jQuery('#commentluv').width()){
164
- var dropdownwidth = jQuery('#commentluv').width();
165
- } else {
166
- var dropdownwidth = jQuery(cl_settings['comObj']).width();
167
- }
168
- jQuery('#lastposts').css('width',dropdownwidth).slideDown('',function(){ cl_settings['lastposts'] = 'showing'});
169
- // bind click action
170
- jQuery('.choosepost:not(.message)').click(function(){
171
- jQuery('#cl_post_title').val(jQuery(this).text());
172
- jQuery('#cl_post_url').val(jQuery(this).attr('id'));
173
- jQuery('#mylastpost').html('<a href="' + jQuery(this).attr('id') +'"> ' + jQuery(this).text() + '</a>').fadeIn(1000);
174
- });
175
- } else {
176
- if(typeof(data.rawfile) == 'undefined'){
177
- data.rawfile = 'no raw data sent back';
178
- }
179
- cl_message(data.error,data.rawfile);
180
- }
181
- },
182
- error: function(x,e){
183
- jQuery('#cl_messages img').remove();
184
- if(x.status==0){
185
- if(cl_settings['api_url'].indexOf('https') == 0){
186
- cl_message('This blog has set the api url to use https , the commentluv technical settings need to be changed for the API url to use http');
187
- } else {
188
- cl_message('It appears that you are offline or another error occured contacting the API url, have you set it to use www or missed the www off the api url?? check the technical settings and add or remove www from the api url.');
189
- }
190
-
191
- }else if(x.status==404){
192
- cl_message('API URL not found.');
193
- }else if(x.status==500){
194
- cl_message('Internal Server Error.' + x.responseText);
195
- }else if(e=='parsererror'){
196
- cl_message('Error.\nParsing JSON Request failed.' + x.responseText);
197
- }else if(e=='timeout'){
198
- cl_message('Request Time out.');
199
- }else {
200
- cl_message('Unknow Error. ' + x.statusText + ' ' + x.responseText);
201
- }
202
- }
203
- });
204
- // save what url used and that we checked already
205
- cl_settings['fired'] = 'yes';
206
- cl_settings['url_value'] = url.val();
207
-
208
- }
209
- /**
210
- * adds a message to tell the user something in the cl_message div and then slides it down
211
- * @param string message - the message to show
212
- */
213
- function cl_message(message,rawfile){
214
- jQuery('#cl_messages').empty().hide().text(message).slideDown();
215
- if(typeof(rawfile) != 'undefined'){
216
- jQuery('#cl_messages').append('<div class="rawfilewrap"><p>Hover your mouse here to see the data that CommentLuv got back from your site..<br />If you see a warning or other error message then that might help you locate the problem (maybe another plugin is spitting out an error?)</p><div class="rawfile"><pre>'+rawfile+'</pre></div></div>');
217
- }
218
- }
219
- function heart_big(e){
220
- // get url and data from link
221
- linkspan = jQuery(this).parents(".cluv");
222
- var link = jQuery(linkspan).find("a:first").attr("href");
223
- var linkdata = jQuery('img',this).attr('class').split(' ');
224
-
225
- // prepare call to admin
226
- var url = cl_settings['api_url'];
227
- var data = {'action':'cl_ajax','cid':linkdata[2],'cl_prem':linkdata[1],'link': link,'do':'info','_ajax_nonce':cl_settings._info};
228
- cl_prem = linkdata[1];
229
- // set up position
230
- var position = jQuery(this).offset();
231
- var windowwidth = jQuery(window).width();
232
- windowheight = jQuery(window).height();
233
- var xpos = position.left;
234
- ypos = position.top;
235
- if(xpos + 350 > windowwidth){
236
- xpos = windowwidth - 370;
237
- if(xpos < 0) xpos = 0;
238
- }
239
-
240
- // setup panel and show with loading background image
241
- jQuery('#heart_tip_big').empty().css({'left':xpos + "px", 'top' :ypos + "px" });
242
- jQuery('#heart_tip_big').css("width","350px");
243
- jQuery('#heart_tip_big').addClass("finalbig").show().addClass('cl_ajax');
244
- // has this been shown before on this page?
245
- if(typeof cl_settings[linkdata[2]] != 'undefined'){
246
- fill_panel(cl_settings[linkdata[2]]);
247
- return;
248
- }
249
- // execute call to admin
250
- jQuery.ajax({
251
- url: cl_settings['api_url'],
252
- type: 'post',
253
- data: data,
254
- dataType: 'json',
255
- success : function(data){
256
- if(typeof(data) == 'object' && jQuery('#heart_tip_big').is(':visible')){
257
- // acceptable response, populate panel
258
- cl_settings[linkdata[2]] = data.panel;
259
- fill_panel(data.panel);
260
- } else {
261
- jQuery('#heart_tip_big').removeClass('cl_ajax').html(cl_settings['no_info_message']);
262
- }
263
- jQuery('#heart_tip_big').mouseleave(heart_small);
264
- }
265
- });
266
- }
267
-
268
- function fill_panel(html){
269
- jQuery('#heart_tip_big').removeClass('cl_ajax').html(html).show();
270
- if(cl_prem == 'p'){
271
- jQuery('#heart_tip_big p.cl_title').css('backgroundColor',cl_settings['infoback']);
272
- }
273
- // move panel if it extends below window
274
- var ely = ypos - jQuery(document).scrollTop();
275
- var poph = jQuery('#heart_tip_big').height() + 20;
276
- if(ely + poph > windowheight){
277
- var invis = poph - (windowheight - ely);
278
- ypos -= invis;
279
- if(ypos < 0) ypos = 0;
280
- jQuery('#heart_tip_big').css('top',ypos);
281
- }
282
- return;
283
- }
284
-
285
- function heart_small(){
286
- if(!jQuery('body').find('.cl_ajax').is(':visible')){
287
- jQuery("body").find("#heart_tip_big").empty().hide();
288
- }
289
-
290
- }
291
- function do_nowt(){
292
- return;
293
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // commentluv 2.94.8
2
+ jQuery(document).ready(function(){
3
+ // get the form object and fields
4
+ var formObj = jQuery('#cl_post_title').parents('form');
5
+ var urlObj = cl_settings['urlObj'] = jQuery("input[name='" + cl_settings['url'] + "']",formObj);
6
+ var comObj = cl_settings['comObj'] = jQuery("textarea[name='" + cl_settings['comment'] + "']",formObj);
7
+ var autObj = jQuery("input[name='" + cl_settings['name'] + "']",formObj);
8
+ var emaObj = jQuery("input[name='" + cl_settings['email'] + "']",formObj);
9
+ // setup localized object with temporary vars
10
+ cl_settings['url_value'] = urlObj.val();
11
+ cl_settings['fired'] = 'no';
12
+
13
+ // set event listener for textarea focus
14
+ comObj.focus(cl_dostuff);
15
+
16
+ // set event listener for url blur
17
+ urlObj.blur(cl_dostuff);
18
+
19
+ // set the event listener for the click of the checkbox
20
+ jQuery('#doluv').click(function(){
21
+ jQuery('#lastposts').hide();
22
+ if(jQuery(this).is(":checked")){
23
+ // was unchecked, now is checked
24
+ jQuery('#mylastpost').fadeTo("fast",1);
25
+ cl_settings['fired'] = 'no';
26
+ cl_dostuff();
27
+ } else {
28
+ // was checked, user unchecked it so empty hidden fields in form
29
+ jQuery('input[name="cl_post_title"]').val("");
30
+ jQuery('input[name="cl_post_url"]').val("");
31
+ jQuery('#mylastpost').fadeTo("slow",0.3);
32
+ jQuery('#lastposts').empty();
33
+ }
34
+ });
35
+ // click event for last blog post link
36
+ jQuery('.cluv a').click(function(){
37
+ var data = jQuery(this).attr('class').split(' ');
38
+ // store click count
39
+ cl_try_ajax({
40
+ type: 'POST',
41
+ data: {'action': 'cl_ajax','cid': data[1],'_ajax_nonce':data[0],'cl_prem':jQuery(this).hasClass('p'),'url': jQuery(this).attr('href'),'do':'click'}
42
+ });
43
+ jQuery(this).attr('target','_blank');
44
+ return true;
45
+ });
46
+ // hover event on heart
47
+ if(cl_settings['infopanel'] == "on"){
48
+ jQuery('.heart_tip_box').mouseenter(heart_big);
49
+ }
50
+ // hide/show showmore
51
+ jQuery(document.body).click(function(){
52
+ if(cl_settings['lastposts'] == 'showing'){
53
+ jQuery('#lastposts').slideUp('',function(){cl_settings['lastposts'] = 'not'});
54
+ }
55
+ });
56
+ jQuery('#showmorespan img').click(function(){
57
+ if(cl_settings['lastposts'] == 'not'){
58
+ jQuery('#lastposts').slideDown('',function(){cl_settings['lastposts'] = 'showing'});
59
+ }
60
+ });
61
+ // clear hidden inputs on load
62
+ jQuery('#cl_post_title,#cl_post_url,#cl_prem').val('');
63
+ // set click on anywhere closes info box
64
+ jQuery(document).click(heart_small);
65
+ // add info panel to page
66
+ jQuery("body").append('<span id="heart_tip_big" style="display: none;position:absolute; z-index: 1001; background-color: ' + cl_settings['infoback'] + '; color: ' + cl_settings['infotext'] + '; width: 62px;"></span>');
67
+
68
+ // hover over to see raw file wrapper open
69
+ jQuery('#commentluv').on('mouseover', '.rawfilewrap', function() {
70
+ jQuery('.rawfile').show();
71
+ });
72
+
73
+ jQuery('#commentluv').on('mouseout', '.rawfilewrap', function() {
74
+ jQuery('.rawfile').hide();
75
+ });
76
+ });
77
+
78
+ /**
79
+ * checks everything is in place for doing stuff
80
+ * returns string 'ok' if, um, ok
81
+ */
82
+ function cl_docheck() {
83
+ // checkbox check
84
+ if(!jQuery('#doluv').is(':checked')){
85
+ return 'not checked';
86
+ }
87
+ var url = cl_settings['urlObj'];
88
+ var msg = jQuery('#cl_messages');
89
+ msg.hide();
90
+ url.removeClass('cl_error');
91
+ // logged in user?
92
+ var nourlmessage = cl_settings['no_url_message'];
93
+ if(cl_settings['logged_in'] == '1'){
94
+ nourlmessage = cl_settings['no_url_logged_in_message'];
95
+ } else {
96
+ // check if fb connect is active
97
+ if(!cl_settings['urlObj'].is(':visible') && typeof FB != 'undefined'){
98
+ var invisurl = cl_settings['urlObj'].remove();
99
+ var invismsg = msg.remove();
100
+ cl_settings['comObj'].after('<br><span id="invisurl">').after(invismsg);
101
+ jQuery('#invisurl').append('URL ').after(invisurl).append('</span>');
102
+ }
103
+
104
+ }
105
+ // check that there is a value in the url field
106
+ if(url.val().length > 1){
107
+ var urlLower = url.val().toLowerCase();
108
+
109
+ // is value just http:// ?
110
+ if (urlLower == 'http://' || urlLower == 'https://') {
111
+ url.addClass('cl_error');
112
+ cl_message(nourlmessage);
113
+ return;
114
+ }
115
+ // is the http:// missing?
116
+ if (urlLower.substring(0,7) != 'http://' && urlLower.substring(0,8) != 'https://') {
117
+ url.addClass('cl_error');
118
+ cl_message(cl_settings['no_http_message']);
119
+ return;
120
+ }
121
+ } else {
122
+ // there is no value
123
+ url.addClass('cl_error');
124
+ cl_message(nourlmessage);
125
+ return;
126
+ }
127
+ // if we are here, all is cool mon
128
+ return 'ok';
129
+ }
130
+
131
+ /**
132
+ * tries various methods to get request through to admin-ajax url
133
+ */
134
+ function cl_try_ajax(args) {
135
+ args.origError = args.origError || args.error || function() {};
136
+
137
+ args.lastError = args.lastError || undefined;
138
+ args.url = args.url || cl_settings['api_url'];
139
+ if (window.location.protocol === 'https:' && args.url.indexOf('http:') === 0) {
140
+ // we were trying to ajax http://, but our current window is https://, so backend would likely also be https://
141
+ // an https to http ajax request is impossible based on CORS spec
142
+ args.url = args.url.replace(/^http:/, 'https:');
143
+ }
144
+
145
+ if (args.lastError !== undefined && args.url === args.lastUrl) {
146
+ return args.origError(args.lastError.x, args.lastError.e);
147
+ }
148
+
149
+ args.error = function(x, e) {
150
+ args.lastError = { x : x, e : e };
151
+ args.lastUrl = args.url;
152
+ args.url = cl_settings['api_url_alt'] || cl_settings['api_url'];
153
+
154
+ // try again
155
+ cl_try_ajax(args);
156
+ };
157
+
158
+ return jQuery.ajax(args);
159
+ };
160
+
161
+ /**
162
+ * tries to fetch last blog posts for a url
163
+ */
164
+ function cl_dostuff(){
165
+ if (cl_docheck() != 'ok') {
166
+ return;
167
+ }
168
+
169
+ var msg = jQuery('#cl_messages');
170
+
171
+ var url = cl_settings['urlObj'];
172
+ if (cl_settings['fired'] == 'yes') {
173
+ // already fired, fire again if current url is different to last fired
174
+ if (url.val() == cl_settings['url_value']) {
175
+ msg.show();
176
+ return;
177
+ }
178
+ jQuery('#lastposts,#mylastpost').empty();
179
+ }
180
+
181
+ // fire the request to admin
182
+ msg.append('<img src="' + cl_settings['images'] + 'loader.gif' + '"/>').show();
183
+
184
+ cl_try_ajax({
185
+ type: 'post',
186
+ dataType: 'json',
187
+ data: {'url':url.val(),'action':'cl_ajax','do':'fetch','_ajax_nonce':cl_settings._fetch},
188
+ success: function(data){
189
+ if(data.error == ''){
190
+ // no error, fill up lastposts div with items returned
191
+ msg.empty().hide();
192
+ jQuery.each(data.items,function(j,item){
193
+ var title = item.title;
194
+ var link = item.link;
195
+ var count = '';
196
+ jQuery('#lastposts').append('<span id="' + item.link + '" class="choosepost ' + item.type + '">' + title + '</span>');
197
+ });
198
+ // setup first link and hidden fields
199
+ jQuery('#mylastpost').html('<a href="' + data.items[0].link +'"> ' + data.items[0]['title'] + '</a>').fadeIn(1000);
200
+ jQuery('#cl_post_title').val(data.items[0].title);
201
+ jQuery('#cl_post_url').val(data.items[0].link);
202
+ jQuery('#cl_prem').val(data.items[0].p);
203
+ // setup look and show dropdown
204
+ jQuery('span.message').css({'backgroundColor':'#efefef','color':'black'});
205
+ jQuery('#showmorespan img').show();
206
+ if(cl_settings['comObj'].width() > jQuery('#commentluv').width()){
207
+ var dropdownwidth = jQuery('#commentluv').width();
208
+ } else {
209
+ var dropdownwidth = jQuery(cl_settings['comObj']).width();
210
+ }
211
+ jQuery('#lastposts').css('width',dropdownwidth).slideDown('',function(){ cl_settings['lastposts'] = 'showing'});
212
+ // bind click action
213
+ jQuery('.choosepost:not(.message)').click(function(){
214
+ jQuery('#cl_post_title').val(jQuery(this).text());
215
+ jQuery('#cl_post_url').val(jQuery(this).attr('id'));
216
+ jQuery('#mylastpost').html('<a href="' + jQuery(this).attr('id') +'"> ' + jQuery(this).text() + '</a>').fadeIn(1000);
217
+ });
218
+ } else {
219
+ if(typeof(data.rawfile) == 'undefined'){
220
+ data.rawfile = 'no raw data sent back';
221
+ }
222
+ cl_message(data.error,data.rawfile);
223
+ }
224
+ },
225
+ error: function(x,e){
226
+ msg.find('img').remove();
227
+
228
+ if(x.status==0){
229
+ if(cl_settings['api_url'].indexOf('https') == 0){
230
+ cl_message('This blog has set the api url to use https , the commentluv technical settings need to be changed for the API url to use http');
231
+ } else {
232
+ cl_message('It appears that you are offline or another error occured contacting the API url, have you set it to use www or missed the www off the api url?? check the technical settings and add or remove www from the api url.');
233
+ }
234
+
235
+ }else if(x.status==404){
236
+ cl_message('API URL not found.');
237
+ }else if(x.status==500){
238
+ cl_message('Internal Server Error.' + x.responseText);
239
+ }else if(e=='parsererror'){
240
+ cl_message('Error.\nParsing JSON Request failed.' + x.responseText);
241
+ }else if(e=='timeout'){
242
+ cl_message('Request Time out.');
243
+ }else {
244
+ cl_message('Unknown Error. ' + x.statusText + ' ' + x.responseText);
245
+ }
246
+ }
247
+ });
248
+
249
+ // save what url used and that we checked already
250
+ cl_settings['fired'] = 'yes';
251
+ cl_settings['url_value'] = url.val();
252
+
253
+ }
254
+ /**
255
+ * adds a message to tell the user something in the cl_message div and then slides it down
256
+ * @param string message - the message to show
257
+ */
258
+ function cl_message(message,rawfile){
259
+ jQuery('#cl_messages').empty().hide().html(message).slideDown();
260
+ if(typeof(rawfile) != 'undefined'){
261
+ jQuery('#cl_messages').append('<div class="rawfilewrap"><p>Hover your mouse here to see the data that CommentLuv got back from your site..<br />If you see a warning or other error message then that might help you locate the problem (maybe another plugin is spitting out an error?)</p><div class="rawfile"><pre>'+rawfile+'</pre></div></div>');
262
+ }
263
+ }
264
+ function heart_big(e){
265
+ // get url and data from link
266
+ linkspan = jQuery(this).parents(".cluv");
267
+ var link = jQuery(linkspan).find("a:first").attr("href");
268
+ var linkdata = jQuery('img',this).attr('class').split(' ');
269
+
270
+ // prepare call to admin
271
+ var data = {'action':'cl_ajax','cid':linkdata[2],'cl_prem':linkdata[1],'link': link,'do':'info','_ajax_nonce':cl_settings._info};
272
+ cl_prem = linkdata[1];
273
+ // set up position
274
+ var position = jQuery(this).offset();
275
+ var windowwidth = jQuery(window).width();
276
+ windowheight = jQuery(window).height();
277
+ var xpos = position.left;
278
+ ypos = position.top;
279
+ if(xpos + 350 > windowwidth){
280
+ xpos = windowwidth - 370;
281
+ if(xpos < 0) xpos = 0;
282
+ }
283
+
284
+ // setup panel and show with loading background image
285
+ jQuery('#heart_tip_big').empty().css({'left':xpos + "px", 'top' :ypos + "px" });
286
+ jQuery('#heart_tip_big').css("width","350px");
287
+ jQuery('#heart_tip_big').addClass("finalbig").show().addClass('cl_ajax');
288
+ // has this been shown before on this page?
289
+ if(typeof cl_settings[linkdata[2]] != 'undefined'){
290
+ fill_panel(cl_settings[linkdata[2]]);
291
+ return;
292
+ }
293
+ // execute call to admin
294
+ cl_try_ajax({
295
+ type: 'post',
296
+ data: data,
297
+ dataType: 'json',
298
+ success : function(data){
299
+ if(typeof(data) == 'object' && jQuery('#heart_tip_big').is(':visible')){
300
+ // acceptable response, populate panel
301
+ cl_settings[linkdata[2]] = data.panel;
302
+ fill_panel(data.panel);
303
+ } else {
304
+ jQuery('#heart_tip_big').removeClass('cl_ajax').html(cl_settings['no_info_message']);
305
+ }
306
+ jQuery('#heart_tip_big').mouseleave(heart_small);
307
+ }
308
+ });
309
+ }
310
+
311
+ function fill_panel(html){
312
+ jQuery('#heart_tip_big').removeClass('cl_ajax').html(html).show();
313
+ if(cl_prem == 'p'){
314
+ jQuery('#heart_tip_big p.cl_title').css('backgroundColor',cl_settings['infoback']);
315
+ }
316
+ // move panel if it extends below window
317
+ var ely = ypos - jQuery(document).scrollTop();
318
+ var poph = jQuery('#heart_tip_big').height() + 20;
319
+ if(ely + poph > windowheight){
320
+ var invis = poph - (windowheight - ely);
321
+ ypos -= invis;
322
+ if(ypos < 0) ypos = 0;
323
+ jQuery('#heart_tip_big').css('top',ypos);
324
+ }
325
+ return;
326
+ }
327
+
328
+ function heart_small(){
329
+ if(!jQuery('body').find('.cl_ajax').is(':visible')){
330
+ jQuery("body").find("#heart_tip_big").empty().hide();
331
+ }
332
+
333
+ }
334
+ function do_nowt(){
335
+ return;
336
+ }
libs/SimpleCluvPie/LICENSE.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2004-2007, Ryan Parman and Geoffrey Sneddon.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification, are
5
+ permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this list of
8
+ conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice, this list
11
+ of conditions and the following disclaimer in the documentation and/or other materials
12
+ provided with the distribution.
13
+
14
+ * Neither the name of the SimplePie Team nor the names of its contributors may be used
15
+ to endorse or promote products derived from this software without specific prior
16
+ written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
19
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
21
+ AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ POSSIBILITY OF SUCH DAMAGE.
libs/SimpleCluvPie/SimpleCluvPie.txt ADDED
@@ -0,0 +1 @@
 
1
+ Mass replaced SimplePie with SimpleCluvPie to prevent colliding with other plugins/wp
libs/SimpleCluvPie/autoloader.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ // autoloader
46
+ spl_autoload_register(array(new SimpleCluvPie_Autoloader(), 'autoload'));
47
+
48
+ if (!class_exists('SimpleCluvPie'))
49
+ {
50
+ trigger_error('Autoloader not registered properly', E_USER_ERROR);
51
+ }
52
+
53
+ /**
54
+ * Autoloader class
55
+ *
56
+ * @package SimpleCluvPie
57
+ * @subpackage API
58
+ */
59
+ class SimpleCluvPie_Autoloader
60
+ {
61
+ /**
62
+ * Constructor
63
+ */
64
+ public function __construct()
65
+ {
66
+ $this->path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library';
67
+ }
68
+
69
+ /**
70
+ * Autoloader
71
+ *
72
+ * @param string $class The name of the class to attempt to load.
73
+ */
74
+ public function autoload($class)
75
+ {
76
+ // Only load the class if it starts with "SimpleCluvPie"
77
+ if (strpos($class, 'SimpleCluvPie') !== 0)
78
+ {
79
+ return;
80
+ }
81
+
82
+ $filename = $this->path . DIRECTORY_SEPARATOR . str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
83
+ include $filename;
84
+ }
85
+ }
libs/SimpleCluvPie/idn/LICENCE ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 2.1, February 1999
3
+
4
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ [This is the first released version of the Lesser GPL. It also counts
10
+ as the successor of the GNU Library Public License, version 2, hence
11
+ the version number 2.1.]
12
+
13
+ Preamble
14
+
15
+ The licenses for most software are designed to take away your
16
+ freedom to share and change it. By contrast, the GNU General Public
17
+ Licenses are intended to guarantee your freedom to share and change
18
+ free software--to make sure the software is free for all its users.
19
+
20
+ This license, the Lesser General Public License, applies to some
21
+ specially designated software packages--typically libraries--of the
22
+ Free Software Foundation and other authors who decide to use it. You
23
+ can use it too, but we suggest you first think carefully about whether
24
+ this license or the ordinary General Public License is the better
25
+ strategy to use in any particular case, based on the explanations below.
26
+
27
+ When we speak of free software, we are referring to freedom of use,
28
+ not price. Our General Public Licenses are designed to make sure that
29
+ you have the freedom to distribute copies of free software (and charge
30
+ for this service if you wish); that you receive source code or can get
31
+ it if you want it; that you can change the software and use pieces of
32
+ it in new free programs; and that you are informed that you can do
33
+ these things.
34
+
35
+ To protect your rights, we need to make restrictions that forbid
36
+ distributors to deny you these rights or to ask you to surrender these
37
+ rights. These restrictions translate to certain responsibilities for
38
+ you if you distribute copies of the library or if you modify it.
39
+
40
+ For example, if you distribute copies of the library, whether gratis
41
+ or for a fee, you must give the recipients all the rights that we gave
42
+ you. You must make sure that they, too, receive or can get the source
43
+ code. If you link other code with the library, you must provide
44
+ complete object files to the recipients, so that they can relink them
45
+ with the library after making changes to the library and recompiling
46
+ it. And you must show them these terms so they know their rights.
47
+
48
+ We protect your rights with a two-step method: (1) we copyright the
49
+ library, and (2) we offer you this license, which gives you legal
50
+ permission to copy, distribute and/or modify the library.
51
+
52
+ To protect each distributor, we want to make it very clear that
53
+ there is no warranty for the free library. Also, if the library is
54
+ modified by someone else and passed on, the recipients should know
55
+ that what they have is not the original version, so that the original
56
+ author's reputation will not be affected by problems that might be
57
+ introduced by others.
58
+
59
+ Finally, software patents pose a constant threat to the existence of
60
+ any free program. We wish to make sure that a company cannot
61
+ effectively restrict the users of a free program by obtaining a
62
+ restrictive license from a patent holder. Therefore, we insist that
63
+ any patent license obtained for a version of the library must be
64
+ consistent with the full freedom of use specified in this license.
65
+
66
+ Most GNU software, including some libraries, is covered by the
67
+ ordinary GNU General Public License. This license, the GNU Lesser
68
+ General Public License, applies to certain designated libraries, and
69
+ is quite different from the ordinary General Public License. We use
70
+ this license for certain libraries in order to permit linking those
71
+ libraries into non-free programs.
72
+
73
+ When a program is linked with a library, whether statically or using
74
+ a shared library, the combination of the two is legally speaking a
75
+ combined work, a derivative of the original library. The ordinary
76
+ General Public License therefore permits such linking only if the
77
+ entire combination fits its criteria of freedom. The Lesser General
78
+ Public License permits more lax criteria for linking other code with
79
+ the library.
80
+
81
+ We call this license the "Lesser" General Public License because it
82
+ does Less to protect the user's freedom than the ordinary General
83
+ Public License. It also provides other free software developers Less
84
+ of an advantage over competing non-free programs. These disadvantages
85
+ are the reason we use the ordinary General Public License for many
86
+ libraries. However, the Lesser license provides advantages in certain
87
+ special circumstances.
88
+
89
+ For example, on rare occasions, there may be a special need to
90
+ encourage the widest possible use of a certain library, so that it becomes
91
+ a de-facto standard. To achieve this, non-free programs must be
92
+ allowed to use the library. A more frequent case is that a free
93
+ library does the same job as widely used non-free libraries. In this
94
+ case, there is little to gain by limiting the free library to free
95
+ software only, so we use the Lesser General Public License.
96
+
97
+ In other cases, permission to use a particular library in non-free
98
+ programs enables a greater number of people to use a large body of
99
+ free software. For example, permission to use the GNU C Library in
100
+ non-free programs enables many more people to use the whole GNU
101
+ operating system, as well as its variant, the GNU/Linux operating
102
+ system.
103
+
104
+ Although the Lesser General Public License is Less protective of the
105
+ users' freedom, it does ensure that the user of a program that is
106
+ linked with the Library has the freedom and the wherewithal to run
107
+ that program using a modified version of the Library.
108
+
109
+ The precise terms and conditions for copying, distribution and
110
+ modification follow. Pay close attention to the difference between a
111
+ "work based on the library" and a "work that uses the library". The
112
+ former contains code derived from the library, whereas the latter must
113
+ be combined with the library in order to run.
114
+
115
+ GNU LESSER GENERAL PUBLIC LICENSE
116
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117
+
118
+ 0. This License Agreement applies to any software library or other
119
+ program which contains a notice placed by the copyright holder or
120
+ other authorized party saying it may be distributed under the terms of
121
+ this Lesser General Public License (also called "this License").
122
+ Each licensee is addressed as "you".
123
+
124
+ A "library" means a collection of software functions and/or data
125
+ prepared so as to be conveniently linked with application programs
126
+ (which use some of those functions and data) to form executables.
127
+
128
+ The "Library", below, refers to any such software library or work
129
+ which has been distributed under these terms. A "work based on the
130
+ Library" means either the Library or any derivative work under
131
+ copyright law: that is to say, a work containing the Library or a
132
+ portion of it, either verbatim or with modifications and/or translated
133
+ straightforwardly into another language. (Hereinafter, translation is
134
+ included without limitation in the term "modification".)
135
+
136
+ "Source code" for a work means the preferred form of the work for
137
+ making modifications to it. For a library, complete source code means
138
+ all the source code for all modules it contains, plus any associated
139
+ interface definition files, plus the scripts used to control compilation
140
+ and installation of the library.
141
+
142
+ Activities other than copying, distribution and modification are not
143
+ covered by this License; they are outside its scope. The act of
144
+ running a program using the Library is not restricted, and output from
145
+ such a program is covered only if its contents constitute a work based
146
+ on the Library (independent of the use of the Library in a tool for
147
+ writing it). Whether that is true depends on what the Library does
148
+ and what the program that uses the Library does.
149
+
150
+ 1. You may copy and distribute verbatim copies of the Library's
151
+ complete source code as you receive it, in any medium, provided that
152
+ you conspicuously and appropriately publish on each copy an
153
+ appropriate copyright notice and disclaimer of warranty; keep intact
154
+ all the notices that refer to this License and to the absence of any
155
+ warranty; and distribute a copy of this License along with the
156
+ Library.
157
+
158
+ You may charge a fee for the physical act of transferring a copy,
159
+ and you may at your option offer warranty protection in exchange for a
160
+ fee.
161
+
162
+ 2. You may modify your copy or copies of the Library or any portion
163
+ of it, thus forming a work based on the Library, and copy and
164
+ distribute such modifications or work under the terms of Section 1
165
+ above, provided that you also meet all of these conditions:
166
+
167
+ a) The modified work must itself be a software library.
168
+
169
+ b) You must cause the files modified to carry prominent notices
170
+ stating that you changed the files and the date of any change.
171
+
172
+ c) You must cause the whole of the work to be licensed at no
173
+ charge to all third parties under the terms of this License.
174
+
175
+ d) If a facility in the modified Library refers to a function or a
176
+ table of data to be supplied by an application program that uses
177
+ the facility, other than as an argument passed when the facility
178
+ is invoked, then you must make a good faith effort to ensure that,
179
+ in the event an application does not supply such function or
180
+ table, the facility still operates, and performs whatever part of
181
+ its purpose remains meaningful.
182
+
183
+ (For example, a function in a library to compute square roots has
184
+ a purpose that is entirely well-defined independent of the
185
+ application. Therefore, Subsection 2d requires that any
186
+ application-supplied function or table used by this function must
187
+ be optional: if the application does not supply it, the square
188
+ root function must still compute square roots.)
189
+
190
+ These requirements apply to the modified work as a whole. If
191
+ identifiable sections of that work are not derived from the Library,
192
+ and can be reasonably considered independent and separate works in
193
+ themselves, then this License, and its terms, do not apply to those
194
+ sections when you distribute them as separate works. But when you
195
+ distribute the same sections as part of a whole which is a work based
196
+ on the Library, the distribution of the whole must be on the terms of
197
+ this License, whose permissions for other licensees extend to the
198
+ entire whole, and thus to each and every part regardless of who wrote
199
+ it.
200
+
201
+ Thus, it is not the intent of this section to claim rights or contest
202
+ your rights to work written entirely by you; rather, the intent is to
203
+ exercise the right to control the distribution of derivative or
204
+ collective works based on the Library.
205
+
206
+ In addition, mere aggregation of another work not based on the Library
207
+ with the Library (or with a work based on the Library) on a volume of
208
+ a storage or distribution medium does not bring the other work under
209
+ the scope of this License.
210
+
211
+ 3. You may opt to apply the terms of the ordinary GNU General Public
212
+ License instead of this License to a given copy of the Library. To do
213
+ this, you must alter all the notices that refer to this License, so
214
+ that they refer to the ordinary GNU General Public License, version 2,
215
+ instead of to this License. (If a newer version than version 2 of the
216
+ ordinary GNU General Public License has appeared, then you can specify
217
+ that version instead if you wish.) Do not make any other change in
218
+ these notices.
219
+
220
+ Once this change is made in a given copy, it is irreversible for
221
+ that copy, so the ordinary GNU General Public License applies to all
222
+ subsequent copies and derivative works made from that copy.
223
+
224
+ This option is useful when you wish to copy part of the code of
225
+ the Library into a program that is not a library.
226
+
227
+ 4. You may copy and distribute the Library (or a portion or
228
+ derivative of it, under Section 2) in object code or executable form
229
+ under the terms of Sections 1 and 2 above provided that you accompany
230
+ it with the complete corresponding machine-readable source code, which
231
+ must be distributed under the terms of Sections 1 and 2 above on a
232
+ medium customarily used for software interchange.
233
+
234
+ If distribution of object code is made by offering access to copy
235
+ from a designated place, then offering equivalent access to copy the
236
+ source code from the same place satisfies the requirement to
237
+ distribute the source code, even though third parties are not
238
+ compelled to copy the source along with the object code.
239
+
240
+ 5. A program that contains no derivative of any portion of the
241
+ Library, but is designed to work with the Library by being compiled or
242
+ linked with it, is called a "work that uses the Library". Such a
243
+ work, in isolation, is not a derivative work of the Library, and
244
+ therefore falls outside the scope of this License.
245
+
246
+ However, linking a "work that uses the Library" with the Library
247
+ creates an executable that is a derivative of the Library (because it
248
+ contains portions of the Library), rather than a "work that uses the
249
+ library". The executable is therefore covered by this License.
250
+ Section 6 states terms for distribution of such executables.
251
+
252
+ When a "work that uses the Library" uses material from a header file
253
+ that is part of the Library, the object code for the work may be a
254
+ derivative work of the Library even though the source code is not.
255
+ Whether this is true is especially significant if the work can be
256
+ linked without the Library, or if the work is itself a library. The
257
+ threshold for this to be true is not precisely defined by law.
258
+
259
+ If such an object file uses only numerical parameters, data
260
+ structure layouts and accessors, and small macros and small inline
261
+ functions (ten lines or less in length), then the use of the object
262
+ file is unrestricted, regardless of whether it is legally a derivative
263
+ work. (Executables containing this object code plus portions of the
264
+ Library will still fall under Section 6.)
265
+
266
+ Otherwise, if the work is a derivative of the Library, you may
267
+ distribute the object code for the work under the terms of Section 6.
268
+ Any executables containing that work also fall under Section 6,
269
+ whether or not they are linked directly with the Library itself.
270
+
271
+ 6. As an exception to the Sections above, you may also combine or
272
+ link a "work that uses the Library" with the Library to produce a
273
+ work containing portions of the Library, and distribute that work
274
+ under terms of your choice, provided that the terms permit
275
+ modification of the work for the customer's own use and reverse
276
+ engineering for debugging such modifications.
277
+
278
+ You must give prominent notice with each copy of the work that the
279
+ Library is used in it and that the Library and its use are covered by
280
+ this License. You must supply a copy of this License. If the work
281
+ during execution displays copyright notices, you must include the
282
+ copyright notice for the Library among them, as well as a reference
283
+ directing the user to the copy of this License. Also, you must do one
284
+ of these things:
285
+
286
+ a) Accompany the work with the complete corresponding
287
+ machine-readable source code for the Library including whatever
288
+ changes were used in the work (which must be distributed under
289
+ Sections 1 and 2 above); and, if the work is an executable linked
290
+ with the Library, with the complete machine-readable "work that
291
+ uses the Library", as object code and/or source code, so that the
292
+ user can modify the Library and then relink to produce a modified
293
+ executable containing the modified Library. (It is understood
294
+ that the user who changes the contents of definitions files in the
295
+ Library will not necessarily be able to recompile the application
296
+ to use the modified definitions.)
297
+
298
+ b) Use a suitable shared library mechanism for linking with the
299
+ Library. A suitable mechanism is one that (1) uses at run time a
300
+ copy of the library already present on the user's computer system,
301
+ rather than copying library functions into the executable, and (2)
302
+ will operate properly with a modified version of the library, if
303
+ the user installs one, as long as the modified version is
304
+ interface-compatible with the version that the work was made with.
305
+
306
+ c) Accompany the work with a written offer, valid for at
307
+ least three years, to give the same user the materials
308
+ specified in Subsection 6a, above, for a charge no more
309
+ than the cost of performing this distribution.
310
+
311
+ d) If distribution of the work is made by offering access to copy
312
+ from a designated place, offer equivalent access to copy the above
313
+ specified materials from the same place.
314
+
315
+ e) Verify that the user has already received a copy of these
316
+ materials or that you have already sent this user a copy.
317
+
318
+ For an executable, the required form of the "work that uses the
319
+ Library" must include any data and utility programs needed for
320
+ reproducing the executable from it. However, as a special exception,
321
+ the materials to be distributed need not include anything that is
322
+ normally distributed (in either source or binary form) with the major
323
+ components (compiler, kernel, and so on) of the operating system on
324
+ which the executable runs, unless that component itself accompanies
325
+ the executable.
326
+
327
+ It may happen that this requirement contradicts the license
328
+ restrictions of other proprietary libraries that do not normally
329
+ accompany the operating system. Such a contradiction means you cannot
330
+ use both them and the Library together in an executable that you
331
+ distribute.
332
+
333
+ 7. You may place library facilities that are a work based on the
334
+ Library side-by-side in a single library together with other library
335
+ facilities not covered by this License, and distribute such a combined
336
+ library, provided that the separate distribution of the work based on
337
+ the Library and of the other library facilities is otherwise
338
+ permitted, and provided that you do these two things:
339
+
340
+ a) Accompany the combined library with a copy of the same work
341
+ based on the Library, uncombined with any other library
342
+ facilities. This must be distributed under the terms of the
343
+ Sections above.
344
+
345
+ b) Give prominent notice with the combined library of the fact
346
+ that part of it is a work based on the Library, and explaining
347
+ where to find the accompanying uncombined form of the same work.
348
+
349
+ 8. You may not copy, modify, sublicense, link with, or distribute
350
+ the Library except as expressly provided under this License. Any
351
+ attempt otherwise to copy, modify, sublicense, link with, or
352
+ distribute the Library is void, and will automatically terminate your
353
+ rights under this License. However, parties who have received copies,
354
+ or rights, from you under this License will not have their licenses
355
+ terminated so long as such parties remain in full compliance.
356
+
357
+ 9. You are not required to accept this License, since you have not
358
+ signed it. However, nothing else grants you permission to modify or
359
+ distribute the Library or its derivative works. These actions are
360
+ prohibited by law if you do not accept this License. Therefore, by
361
+ modifying or distributing the Library (or any work based on the
362
+ Library), you indicate your acceptance of this License to do so, and
363
+ all its terms and conditions for copying, distributing or modifying
364
+ the Library or works based on it.
365
+
366
+ 10. Each time you redistribute the Library (or any work based on the
367
+ Library), the recipient automatically receives a license from the
368
+ original licensor to copy, distribute, link with or modify the Library
369
+ subject to these terms and conditions. You may not impose any further
370
+ restrictions on the recipients' exercise of the rights granted herein.
371
+ You are not responsible for enforcing compliance by third parties with
372
+ this License.
373
+
374
+ 11. If, as a consequence of a court judgment or allegation of patent
375
+ infringement or for any other reason (not limited to patent issues),
376
+ conditions are imposed on you (whether by court order, agreement or
377
+ otherwise) that contradict the conditions of this License, they do not
378
+ excuse you from the conditions of this License. If you cannot
379
+ distribute so as to satisfy simultaneously your obligations under this
380
+ License and any other pertinent obligations, then as a consequence you
381
+ may not distribute the Library at all. For example, if a patent
382
+ license would not permit royalty-free redistribution of the Library by
383
+ all those who receive copies directly or indirectly through you, then
384
+ the only way you could satisfy both it and this License would be to
385
+ refrain entirely from distribution of the Library.
386
+
387
+ If any portion of this section is held invalid or unenforceable under any
388
+ particular circumstance, the balance of the section is intended to apply,
389
+ and the section as a whole is intended to apply in other circumstances.
390
+
391
+ It is not the purpose of this section to induce you to infringe any
392
+ patents or other property right claims or to contest validity of any
393
+ such claims; this section has the sole purpose of protecting the
394
+ integrity of the free software distribution system which is
395
+ implemented by public license practices. Many people have made
396
+ generous contributions to the wide range of software distributed
397
+ through that system in reliance on consistent application of that
398
+ system; it is up to the author/donor to decide if he or she is willing
399
+ to distribute software through any other system and a licensee cannot
400
+ impose that choice.
401
+
402
+ This section is intended to make thoroughly clear what is believed to
403
+ be a consequence of the rest of this License.
404
+
405
+ 12. If the distribution and/or use of the Library is restricted in
406
+ certain countries either by patents or by copyrighted interfaces, the
407
+ original copyright holder who places the Library under this License may add
408
+ an explicit geographical distribution limitation excluding those countries,
409
+ so that distribution is permitted only in or among countries not thus
410
+ excluded. In such case, this License incorporates the limitation as if
411
+ written in the body of this License.
412
+
413
+ 13. The Free Software Foundation may publish revised and/or new
414
+ versions of the Lesser General Public License from time to time.
415
+ Such new versions will be similar in spirit to the present version,
416
+ but may differ in detail to address new problems or concerns.
417
+
418
+ Each version is given a distinguishing version number. If the Library
419
+ specifies a version number of this License which applies to it and
420
+ "any later version", you have the option of following the terms and
421
+ conditions either of that version or of any later version published by
422
+ the Free Software Foundation. If the Library does not specify a
423
+ license version number, you may choose any version ever published by
424
+ the Free Software Foundation.
425
+
426
+ 14. If you wish to incorporate parts of the Library into other free
427
+ programs whose distribution conditions are incompatible with these,
428
+ write to the author to ask for permission. For software which is
429
+ copyrighted by the Free Software Foundation, write to the Free
430
+ Software Foundation; we sometimes make exceptions for this. Our
431
+ decision will be guided by the two goals of preserving the free status
432
+ of all derivatives of our free software and of promoting the sharing
433
+ and reuse of software generally.
434
+
435
+ NO WARRANTY
436
+
437
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438
+ WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439
+ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440
+ OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444
+ LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445
+ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446
+
447
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449
+ AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456
+ DAMAGES.
457
+
458
+ END OF TERMS AND CONDITIONS
459
+
460
+ How to Apply These Terms to Your New Libraries
461
+
462
+ If you develop a new library, and you want it to be of the greatest
463
+ possible use to the public, we recommend making it free software that
464
+ everyone can redistribute and change. You can do so by permitting
465
+ redistribution under these terms (or, alternatively, under the terms of the
466
+ ordinary General Public License).
467
+
468
+ To apply these terms, attach the following notices to the library. It is
469
+ safest to attach them to the start of each source file to most effectively
470
+ convey the exclusion of warranty; and each file should have at least the
471
+ "copyright" line and a pointer to where the full notice is found.
472
+
473
+ <one line to give the library's name and a brief idea of what it does.>
474
+ Copyright (C) <year> <name of author>
475
+
476
+ This library is free software; you can redistribute it and/or
477
+ modify it under the terms of the GNU Lesser General Public
478
+ License as published by the Free Software Foundation; either
479
+ version 2.1 of the License, or (at your option) any later version.
480
+
481
+ This library is distributed in the hope that it will be useful,
482
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
483
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484
+ Lesser General Public License for more details.
485
+
486
+ You should have received a copy of the GNU Lesser General Public
487
+ License along with this library; if not, write to the Free Software
488
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
489
+
490
+ Also add information on how to contact you by electronic and paper mail.
491
+
492
+ You should also get your employer (if you work as a programmer) or your
493
+ school, if any, to sign a "copyright disclaimer" for the library, if
494
+ necessary. Here is a sample; alter the names:
495
+
496
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
497
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
498
+
499
+ <signature of Ty Coon>, 1 April 1990
500
+ Ty Coon, President of Vice
501
+
502
+ That's all there is to it!
libs/SimpleCluvPie/idn/ReadMe.txt ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *******************************************************************************
2
+ * *
3
+ * IDNA Convert (idna_convert.class.php) *
4
+ * *
5
+ * http://idnaconv.phlymail.de mailto:phlymail@phlylabs.de *
6
+ *******************************************************************************
7
+ * (c) 2004-2007 phlyLabs, Berlin *
8
+ * This file is encoded in UTF-8 *
9
+ *******************************************************************************
10
+
11
+ Introduction
12
+ ------------
13
+
14
+ The class idna_convert allows to convert internationalized domain names
15
+ (see RFC 3490, 3491, 3492 and 3454 for detials) as they can be used with various
16
+ registries worldwide to be translated between their original (localized) form
17
+ and their encoded form as it will be used in the DNS (Domain Name System).
18
+
19
+ The class provides two public methods, encode() and decode(), which do exactly
20
+ what you would expect them to do. You are allowed to use complete domain names,
21
+ simple strings and complete email addresses as well. That means, that you might
22
+ use any of the following notations:
23
+
24
+ - www.nörgler.com
25
+ - xn--nrgler-wxa
26
+ - xn--brse-5qa.xn--knrz-1ra.info
27
+
28
+ Errors, incorrectly encoded or invalid strings will lead to either a FALSE
29
+ response (when in strict mode) or to only partially converted strings.
30
+ You can query the occured error by calling the method get_last_error().
31
+
32
+ Unicode strings are expected to be either UTF-8 strings, UCS-4 strings or UCS-4
33
+ arrays. The default format is UTF-8. For setting different encodings, you can
34
+ call the method setParams() - please see the inline documentation for details.
35
+ ACE strings (the Punycode form) are always 7bit ASCII strings.
36
+
37
+ ATTENTION: We no longer supply the PHP5 version of the class. It is not
38
+ necessary for achieving a successfull conversion, since the supplied PHP code is
39
+ compatible with both PHP4 and PHP5. We expect to see no compatibility issues
40
+ with the upcoming PHP6, too.
41
+
42
+
43
+ Files
44
+ -----
45
+
46
+ idna_convert.class.php - The actual class
47
+ idna_convert.create.npdata.php - Useful for (re)creating the NPData file
48
+ npdata.ser - Serialized data for NamePrep
49
+ example.php - An example web page for converting
50
+ ReadMe.txt - This file
51
+ LICENCE - The LGPL licence file
52
+
53
+ The class is contained in idna_convert.class.php.
54
+ MAKE SURE to copy the npdata.ser file into the same folder as the class file
55
+ itself!
56
+
57
+
58
+ Examples
59
+ --------
60
+
61
+ 1. Say we wish to encode the domain name nörgler.com:
62
+
63
+ // Include the class
64
+ include_once('idna_convert.class.php');
65
+ // Instantiate it *
66
+ $IDN = new idna_convert();
67
+ // The input string, if input is not UTF-8 or UCS-4, it must be converted before
68
+ $input = utf8_encode('nörgler.com');
69
+ // Encode it to its punycode presentation
70
+ $output = $IDN->encode($input);
71
+ // Output, what we got now
72
+ echo $output; // This will read: xn--nrgler-wxa.com
73
+
74
+
75
+ 2. We received an email from a punycoded domain and are willing to learn, how
76
+ the domain name reads originally
77
+
78
+ // Include the class
79
+ include_once('idna_convert.class.php');
80
+ // Instantiate it (depending on the version you are using) with
81
+ $IDN = new idna_convert();
82
+ // The input string
83
+ $input = 'andre@xn--brse-5qa.xn--knrz-1ra.info';
84
+ // Encode it to its punycode presentation
85
+ $output = $IDN->decode($input);
86
+ // Output, what we got now, if output should be in a format different to UTF-8
87
+ // or UCS-4, you will have to convert it before outputting it
88
+ echo utf8_decode($output); // This will read: andre@börse.knörz.info
89
+
90
+
91
+ 3. The input is read from a UCS-4 coded file and encoded line by line. By
92
+ appending the optional second parameter we tell enode() about the input
93
+ format to be used
94
+
95
+ // Include the class
96
+ include_once('idna_convert.class.php');
97
+ // Instantiate it
98
+ $IDN = new dinca_convert();
99
+ // Iterate through the input file line by line
100
+ foreach (file('ucs4-domains.txt') as $line) {
101
+ echo $IDN->encode(trim($line), 'ucs4_string');
102
+ echo "\n";
103
+ }
104
+
105
+
106
+ NPData
107
+ ------
108
+
109
+ Should you need to recreate the npdata.ser file, which holds all necessary translation
110
+ tables in a serialized format, you can run the file idna_convert.create.npdata.php, which
111
+ creates the file for you and stores it in the same folder, where it is placed.
112
+ Should you need to do changes to the tables you can do so, but beware of the consequences.
113
+
114
+
115
+ Contact us
116
+ ----------
117
+
118
+ In case of errors, bugs, questions, wishes, please don't hesitate to contact us
119
+ under the email address above.
120
+
121
+ The team of phlyLabs
122
+ http://phlylabs.de
123
+ mailto:phlymail@phlylabs.de
libs/SimpleCluvPie/idn/idna_convert.class.php ADDED
@@ -0,0 +1,969 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // {{{ license
3
+
4
+ /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
5
+ //
6
+ // +----------------------------------------------------------------------+
7
+ // | This library is free software; you can redistribute it and/or modify |
8
+ // | it under the terms of the GNU Lesser General Public License as |
9
+ // | published by the Free Software Foundation; either version 2.1 of the |
10
+ // | License, or (at your option) any later version. |
11
+ // | |
12
+ // | This library is distributed in the hope that it will be useful, but |
13
+ // | WITHOUT ANY WARRANTY; without even the implied warranty of |
14
+ // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15
+ // | Lesser General Public License for more details. |
16
+ // | |
17
+ // | You should have received a copy of the GNU Lesser General Public |
18
+ // | License along with this library; if not, write to the Free Software |
19
+ // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
20
+ // | USA. |
21
+ // +----------------------------------------------------------------------+
22
+ //
23
+
24
+ // }}}
25
+
26
+ /**
27
+ * Encode/decode Internationalized Domain Names.
28
+ *
29
+ * The class allows to convert internationalized domain names
30
+ * (see RFC 3490 for details) as they can be used with various registries worldwide
31
+ * to be translated between their original (localized) form and their encoded form
32
+ * as it will be used in the DNS (Domain Name System).
33
+ *
34
+ * The class provides two public methods, encode() and decode(), which do exactly
35
+ * what you would expect them to do. You are allowed to use complete domain names,
36
+ * simple strings and complete email addresses as well. That means, that you might
37
+ * use any of the following notations:
38
+ *
39
+ * - www.nörgler.com
40
+ * - xn--nrgler-wxa
41
+ * - xn--brse-5qa.xn--knrz-1ra.info
42
+ *
43
+ * Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4
44
+ * array. Unicode output is available in the same formats.
45
+ * You can select your preferred format via {@link set_paramter()}.
46
+ *
47
+ * ACE input and output is always expected to be ASCII.
48
+ *
49
+ * @author Matthias Sommerfeld <mso@phlylabs.de>
50
+ * @copyright 2004-2007 phlyLabs Berlin, http://phlylabs.de
51
+ * @version 0.5.1
52
+ *
53
+ */
54
+ class idna_convert
55
+ {
56
+ /**
57
+ * Holds all relevant mapping tables, loaded from a seperate file on construct
58
+ * See RFC3454 for details
59
+ *
60
+ * @var array
61
+ * @access private
62
+ */
63
+ var $NP = array();
64
+
65
+ // Internal settings, do not mess with them
66
+ var $_punycode_prefix = 'xn--';
67
+ var $_invalid_ucs = 0x80000000;
68
+ var $_max_ucs = 0x10FFFF;
69
+ var $_base = 36;
70
+ var $_tmin = 1;
71
+ var $_tmax = 26;
72
+ var $_skew = 38;
73
+ var $_damp = 700;
74
+ var $_initial_bias = 72;
75
+ var $_initial_n = 0x80;
76
+ var $_sbase = 0xAC00;
77
+ var $_lbase = 0x1100;
78
+ var $_vbase = 0x1161;
79
+ var $_tbase = 0x11A7;
80
+ var $_lcount = 19;
81
+ var $_vcount = 21;
82
+ var $_tcount = 28;
83
+ var $_ncount = 588; // _vcount * _tcount
84
+ var $_scount = 11172; // _lcount * _tcount * _vcount
85
+ var $_error = false;
86
+
87
+ // See {@link set_paramter()} for details of how to change the following
88
+ // settings from within your script / application
89
+ var $_api_encoding = 'utf8'; // Default input charset is UTF-8
90
+ var $_allow_overlong = false; // Overlong UTF-8 encodings are forbidden
91
+ var $_strict_mode = false; // Behave strict or not
92
+
93
+ // The constructor
94
+ function idna_convert($options = false)
95
+ {
96
+ $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount;
97
+ if (function_exists('file_get_contents')) {
98
+ $this->NP = unserialize(file_get_contents(dirname(__FILE__).'/npdata.ser'));
99
+ } else {
100
+ $this->NP = unserialize(join('', file(dirname(__FILE__).'/npdata.ser')));
101
+ }
102
+ // If parameters are given, pass these to the respective method
103
+ if (is_array($options)) {
104
+ return $this->set_parameter($options);
105
+ }
106
+ return true;
107
+ }
108
+
109
+ /**
110
+ * Sets a new option value. Available options and values:
111
+ * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8,
112
+ * 'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8]
113
+ * [overlong - Unicode does not allow unnecessarily long encodings of chars,
114
+ * to allow this, set this parameter to true, else to false;
115
+ * default is false.]
116
+ * [strict - true: strict mode, good for registration purposes - Causes errors
117
+ * on failures; false: loose mode, ideal for "wildlife" applications
118
+ * by silently ignoring errors and returning the original input instead
119
+ *
120
+ * @param mixed Parameter to set (string: single parameter; array of Parameter => Value pairs)
121
+ * @param string Value to use (if parameter 1 is a string)
122
+ * @return boolean true on success, false otherwise
123
+ * @access public
124
+ */
125
+ function set_parameter($option, $value = false)
126
+ {
127
+ if (!is_array($option)) {
128
+ $option = array($option => $value);
129
+ }
130
+ foreach ($option as $k => $v) {
131
+ switch ($k) {
132
+ case 'encoding':
133
+ switch ($v) {
134
+ case 'utf8':
135
+ case 'ucs4_string':
136
+ case 'ucs4_array':
137
+ $this->_api_encoding = $v;
138
+ break;
139
+ default:
140
+ $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
141
+ return false;
142
+ }
143
+ break;
144
+ case 'overlong':
145
+ $this->_allow_overlong = ($v) ? true : false;
146
+ break;
147
+ case 'strict':
148
+ $this->_strict_mode = ($v) ? true : false;
149
+ break;
150
+ default:
151
+ $this->_error('Set Parameter: Unknown option '.$k);
152
+ return false;
153
+ }
154
+ }
155
+ return true;
156
+ }
157
+
158
+ /**
159
+ * Decode a given ACE domain name
160
+ * @param string Domain name (ACE string)
161
+ * [@param string Desired output encoding, see {@link set_parameter}]
162
+ * @return string Decoded Domain name (UTF-8 or UCS-4)
163
+ * @access public
164
+ */
165
+ function decode($input, $one_time_encoding = false)
166
+ {
167
+ // Optionally set
168
+ if ($one_time_encoding) {
169
+ switch ($one_time_encoding) {
170
+ case 'utf8':
171
+ case 'ucs4_string':
172
+ case 'ucs4_array':
173
+ break;
174
+ default:
175
+ $this->_error('Unknown encoding '.$one_time_encoding);
176
+ return false;
177
+ }
178
+ }
179
+ // Make sure to drop any newline characters around
180
+ $input = trim($input);
181
+
182
+ // Negotiate input and try to determine, whether it is a plain string,
183
+ // an email address or something like a complete URL
184
+ if (strpos($input, '@')) { // Maybe it is an email address
185
+ // No no in strict mode
186
+ if ($this->_strict_mode) {
187
+ $this->_error('Only simple domain name parts can be handled in strict mode');
188
+ return false;
189
+ }
190
+ list ($email_pref, $input) = explode('@', $input, 2);
191
+ $arr = explode('.', $input);
192
+ foreach ($arr as $k => $v) {
193
+ if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
194
+ $conv = $this->_decode($v);
195
+ if ($conv) $arr[$k] = $conv;
196
+ }
197
+ }
198
+ $input = join('.', $arr);
199
+ $arr = explode('.', $email_pref);
200
+ foreach ($arr as $k => $v) {
201
+ if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
202
+ $conv = $this->_decode($v);
203
+ if ($conv) $arr[$k] = $conv;
204
+ }
205
+ }
206
+ $email_pref = join('.', $arr);
207
+ $return = $email_pref . '@' . $input;
208
+ } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
209
+ // No no in strict mode
210
+ if ($this->_strict_mode) {
211
+ $this->_error('Only simple domain name parts can be handled in strict mode');
212
+ return false;
213
+ }
214
+ $parsed = parse_url($input);
215
+ if (isset($parsed['host'])) {
216
+ $arr = explode('.', $parsed['host']);
217
+ foreach ($arr as $k => $v) {
218
+ $conv = $this->_decode($v);
219
+ if ($conv) $arr[$k] = $conv;
220
+ }
221
+ $parsed['host'] = join('.', $arr);
222
+ $return =
223
+ (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
224
+ .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
225
+ .$parsed['host']
226
+ .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
227
+ .(empty($parsed['path']) ? '' : $parsed['path'])
228
+ .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
229
+ .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
230
+ } else { // parse_url seems to have failed, try without it
231
+ $arr = explode('.', $input);
232
+ foreach ($arr as $k => $v) {
233
+ $conv = $this->_decode($v);
234
+ $arr[$k] = ($conv) ? $conv : $v;
235
+ }
236
+ $return = join('.', $arr);
237
+ }
238
+ } else { // Otherwise we consider it being a pure domain name string
239
+ $return = $this->_decode($input);
240
+ if (!$return) $return = $input;
241
+ }
242
+ // The output is UTF-8 by default, other output formats need conversion here
243
+ // If one time encoding is given, use this, else the objects property
244
+ switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
245
+ case 'utf8':
246
+ return $return;
247
+ break;
248
+ case 'ucs4_string':
249
+ return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
250
+ break;
251
+ case 'ucs4_array':
252
+ return $this->_utf8_to_ucs4($return);
253
+ break;
254
+ default:
255
+ $this->_error('Unsupported output format');
256
+ return false;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Encode a given UTF-8 domain name
262
+ * @param string Domain name (UTF-8 or UCS-4)
263
+ * [@param string Desired input encoding, see {@link set_parameter}]
264
+ * @return string Encoded Domain name (ACE string)
265
+ * @access public
266
+ */
267
+ function encode($decoded, $one_time_encoding = false)
268
+ {
269
+ // Forcing conversion of input to UCS4 array
270
+ // If one time encoding is given, use this, else the objects property
271
+ switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) {
272
+ case 'utf8':
273
+ $decoded = $this->_utf8_to_ucs4($decoded);
274
+ break;
275
+ case 'ucs4_string':
276
+ $decoded = $this->_ucs4_string_to_ucs4($decoded);
277
+ case 'ucs4_array':
278
+ break;
279
+ default:
280
+ $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding));
281
+ return false;
282
+ }
283
+
284
+ // No input, no output, what else did you expect?
285
+ if (empty($decoded)) return '';
286
+
287
+ // Anchors for iteration
288
+ $last_begin = 0;
289
+ // Output string
290
+ $output = '';
291
+ foreach ($decoded as $k => $v) {
292
+ // Make sure to use just the plain dot
293
+ switch($v) {
294
+ case 0x3002:
295
+ case 0xFF0E:
296
+ case 0xFF61:
297
+ $decoded[$k] = 0x2E;
298
+ // Right, no break here, the above are converted to dots anyway
299
+ // Stumbling across an anchoring character
300
+ case 0x2E:
301
+ case 0x2F:
302
+ case 0x3A:
303
+ case 0x3F:
304
+ case 0x40:
305
+ // Neither email addresses nor URLs allowed in strict mode
306
+ if ($this->_strict_mode) {
307
+ $this->_error('Neither email addresses nor URLs are allowed in strict mode.');
308
+ return false;
309
+ } else {
310
+ // Skip first char
311
+ if ($k) {
312
+ $encoded = '';
313
+ $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin)));
314
+ if ($encoded) {
315
+ $output .= $encoded;
316
+ } else {
317
+ $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin)));
318
+ }
319
+ $output .= chr($decoded[$k]);
320
+ }
321
+ $last_begin = $k + 1;
322
+ }
323
+ }
324
+ }
325
+ // Catch the rest of the string
326
+ if ($last_begin) {
327
+ $inp_len = sizeof($decoded);
328
+ $encoded = '';
329
+ $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
330
+ if ($encoded) {
331
+ $output .= $encoded;
332
+ } else {
333
+ $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
334
+ }
335
+ return $output;
336
+ } else {
337
+ if ($output = $this->_encode($decoded)) {
338
+ return $output;
339
+ } else {
340
+ return $this->_ucs4_to_utf8($decoded);
341
+ }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * Use this method to get the last error ocurred
347
+ * @param void
348
+ * @return string The last error, that occured
349
+ * @access public
350
+ */
351
+ function get_last_error()
352
+ {
353
+ return $this->_error;
354
+ }
355
+
356
+ /**
357
+ * The actual decoding algorithm
358
+ * @access private
359
+ */
360
+ function _decode($encoded)
361
+ {
362
+ // We do need to find the Punycode prefix
363
+ if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) {
364
+ $this->_error('This is not a punycode string');
365
+ return false;
366
+ }
367
+ $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded);
368
+ // If nothing left after removing the prefix, it is hopeless
369
+ if (!$encode_test) {
370
+ $this->_error('The given encoded string was empty');
371
+ return false;
372
+ }
373
+ // Find last occurence of the delimiter
374
+ $delim_pos = strrpos($encoded, '-');
375
+ if ($delim_pos > strlen($this->_punycode_prefix)) {
376
+ for ($k = strlen($this->_punycode_prefix); $k < $delim_pos; ++$k) {
377
+ $decoded[] = ord($encoded{$k});
378
+ }
379
+ } else {
380
+ $decoded = array();
381
+ }
382
+ $deco_len = count($decoded);
383
+ $enco_len = strlen($encoded);
384
+
385
+ // Wandering through the strings; init
386
+ $is_first = true;
387
+ $bias = $this->_initial_bias;
388
+ $idx = 0;
389
+ $char = $this->_initial_n;
390
+
391
+ for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
392
+ for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) {
393
+ $digit = $this->_decode_digit($encoded{$enco_idx++});
394
+ $idx += $digit * $w;
395
+ $t = ($k <= $bias) ? $this->_tmin :
396
+ (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias));
397
+ if ($digit < $t) break;
398
+ $w = (int) ($w * ($this->_base - $t));
399
+ }
400
+ $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first);
401
+ $is_first = false;
402
+ $char += (int) ($idx / ($deco_len + 1));
403
+ $idx %= ($deco_len + 1);
404
+ if ($deco_len > 0) {
405
+ // Make room for the decoded char
406
+ for ($i = $deco_len; $i > $idx; $i--) {
407
+ $decoded[$i] = $decoded[($i - 1)];
408
+ }
409
+ }
410
+ $decoded[$idx++] = $char;
411
+ }
412
+ return $this->_ucs4_to_utf8($decoded);
413
+ }
414
+
415
+ /**
416
+ * The actual encoding algorithm
417
+ * @access private
418
+ */
419
+ function _encode($decoded)
420
+ {
421
+ // We cannot encode a domain name containing the Punycode prefix
422
+ $extract = strlen($this->_punycode_prefix);
423
+ $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix);
424
+ $check_deco = array_slice($decoded, 0, $extract);
425
+
426
+ if ($check_pref == $check_deco) {
427
+ $this->_error('This is already a punycode string');
428
+ return false;
429
+ }
430
+ // We will not try to encode strings consisting of basic code points only
431
+ $encodable = false;
432
+ foreach ($decoded as $k => $v) {
433
+ if ($v > 0x7a) {
434
+ $encodable = true;
435
+ break;
436
+ }
437
+ }
438
+ if (!$encodable) {
439
+ $this->_error('The given string does not contain encodable chars');
440
+ return false;
441
+ }
442
+
443
+ // Do NAMEPREP
444
+ $decoded = $this->_nameprep($decoded);
445
+ if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed
446
+
447
+ $deco_len = count($decoded);
448
+ if (!$deco_len) return false; // Empty array
449
+
450
+ $codecount = 0; // How many chars have been consumed
451
+
452
+ $encoded = '';
453
+ // Copy all basic code points to output
454
+ for ($i = 0; $i < $deco_len; ++$i) {
455
+ $test = $decoded[$i];
456
+ // Will match [-0-9a-zA-Z]
457
+ if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B)
458
+ || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) {
459
+ $encoded .= chr($decoded[$i]);
460
+ $codecount++;
461
+ }
462
+ }
463
+ if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones
464
+
465
+ // Start with the prefix; copy it to output
466
+ $encoded = $this->_punycode_prefix.$encoded;
467
+
468
+ // If we have basic code points in output, add an hyphen to the end
469
+ if ($codecount) $encoded .= '-';
470
+
471
+ // Now find and encode all non-basic code points
472
+ $is_first = true;
473
+ $cur_code = $this->_initial_n;
474
+ $bias = $this->_initial_bias;
475
+ $delta = 0;
476
+ while ($codecount < $deco_len) {
477
+ // Find the smallest code point >= the current code point and
478
+ // remember the last ouccrence of it in the input
479
+ for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) {
480
+ if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
481
+ $next_code = $decoded[$i];
482
+ }
483
+ }
484
+
485
+ $delta += ($next_code - $cur_code) * ($codecount + 1);
486
+ $cur_code = $next_code;
487
+
488
+ // Scan input again and encode all characters whose code point is $cur_code
489
+ for ($i = 0; $i < $deco_len; $i++) {
490
+ if ($decoded[$i] < $cur_code) {
491
+ $delta++;
492
+ } elseif ($decoded[$i] == $cur_code) {
493
+ for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) {
494
+ $t = ($k <= $bias) ? $this->_tmin :
495
+ (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias);
496
+ if ($q < $t) break;
497
+ $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval()
498
+ $q = (int) (($q - $t) / ($this->_base - $t));
499
+ }
500
+ $encoded .= $this->_encode_digit($q);
501
+ $bias = $this->_adapt($delta, $codecount+1, $is_first);
502
+ $codecount++;
503
+ $delta = 0;
504
+ $is_first = false;
505
+ }
506
+ }
507
+ $delta++;
508
+ $cur_code++;
509
+ }
510
+ return $encoded;
511
+ }
512
+
513
+ /**
514
+ * Adapt the bias according to the current code point and position
515
+ * @access private
516
+ */
517
+ function _adapt($delta, $npoints, $is_first)
518
+ {
519
+ $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2));
520
+ $delta += intval($delta / $npoints);
521
+ for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) {
522
+ $delta = intval($delta / ($this->_base - $this->_tmin));
523
+ }
524
+ return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew));
525
+ }
526
+
527
+ /**
528
+ * Encoding a certain digit
529
+ * @access private
530
+ */
531
+ function _encode_digit($d)
532
+ {
533
+ return chr($d + 22 + 75 * ($d < 26));
534
+ }
535
+
536
+ /**
537
+ * Decode a certain digit
538
+ * @access private
539
+ */
540
+ function _decode_digit($cp)
541
+ {
542
+ $cp = ord($cp);
543
+ return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base));
544
+ }
545
+
546
+ /**
547
+ * Internal error handling method
548
+ * @access private
549
+ */
550
+ function _error($error = '')
551
+ {
552
+ $this->_error = $error;
553
+ }
554
+
555
+ /**
556
+ * Do Nameprep according to RFC3491 and RFC3454
557
+ * @param array Unicode Characters
558
+ * @return string Unicode Characters, Nameprep'd
559
+ * @access private
560
+ */
561
+ function _nameprep($input)
562
+ {
563
+ $output = array();
564
+ $error = false;
565
+ //
566
+ // Mapping
567
+ // Walking through the input array, performing the required steps on each of
568
+ // the input chars and putting the result into the output array
569
+ // While mapping required chars we apply the cannonical ordering
570
+ foreach ($input as $v) {
571
+ // Map to nothing == skip that code point
572
+ if (in_array($v, $this->NP['map_nothing'])) continue;
573
+
574
+ // Try to find prohibited input
575
+ if (in_array($v, $this->NP['prohibit']) || in_array($v, $this->NP['general_prohibited'])) {
576
+ $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
577
+ return false;
578
+ }
579
+ foreach ($this->NP['prohibit_ranges'] as $range) {
580
+ if ($range[0] <= $v && $v <= $range[1]) {
581
+ $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
582
+ return false;
583
+ }
584
+ }
585
+ //
586
+ // Hangul syllable decomposition
587
+ if (0xAC00 <= $v && $v <= 0xD7AF) {
588
+ foreach ($this->_hangul_decompose($v) as $out) {
589
+ $output[] = (int) $out;
590
+ }
591
+ // There's a decomposition mapping for that code point
592
+ } elseif (isset($this->NP['replacemaps'][$v])) {
593
+ foreach ($this->_apply_cannonical_ordering($this->NP['replacemaps'][$v]) as $out) {
594
+ $output[] = (int) $out;
595
+ }
596
+ } else {
597
+ $output[] = (int) $v;
598
+ }
599
+ }
600
+ // Before applying any Combining, try to rearrange any Hangul syllables
601
+ $output = $this->_hangul_compose($output);
602
+ //
603
+ // Combine code points
604
+ //
605
+ $last_class = 0;
606
+ $last_starter = 0;
607
+ $out_len = count($output);
608
+ for ($i = 0; $i < $out_len; ++$i) {
609
+ $class = $this->_get_combining_class($output[$i]);
610
+ if ((!$last_class || $last_class > $class) && $class) {
611
+ // Try to match
612
+ $seq_len = $i - $last_starter;
613
+ $out = $this->_combine(array_slice($output, $last_starter, $seq_len));
614
+ // On match: Replace the last starter with the composed character and remove
615
+ // the now redundant non-starter(s)
616
+ if ($out) {
617
+ $output[$last_starter] = $out;
618
+ if (count($out) != $seq_len) {
619
+ for ($j = $i+1; $j < $out_len; ++$j) {
620
+ $output[$j-1] = $output[$j];
621
+ }
622
+ unset($output[$out_len]);
623
+ }
624
+ // Rewind the for loop by one, since there can be more possible compositions
625
+ $i--;
626
+ $out_len--;
627
+ $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]);
628
+ continue;
629
+ }
630
+ }
631
+ // The current class is 0
632
+ if (!$class) $last_starter = $i;
633
+ $last_class = $class;
634
+ }
635
+ return $output;
636
+ }
637
+
638
+ /**
639
+ * Decomposes a Hangul syllable
640
+ * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
641
+ * @param integer 32bit UCS4 code point
642
+ * @return array Either Hangul Syllable decomposed or original 32bit value as one value array
643
+ * @access private
644
+ */
645
+ function _hangul_decompose($char)
646
+ {
647
+ $sindex = (int) $char - $this->_sbase;
648
+ if ($sindex < 0 || $sindex >= $this->_scount) {
649
+ return array($char);
650
+ }
651
+ $result = array();
652
+ $result[] = (int) $this->_lbase + $sindex / $this->_ncount;
653
+ $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount;
654
+ $T = intval($this->_tbase + $sindex % $this->_tcount);
655
+ if ($T != $this->_tbase) $result[] = $T;
656
+ return $result;
657
+ }
658
+ /**
659
+ * Ccomposes a Hangul syllable
660
+ * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
661
+ * @param array Decomposed UCS4 sequence
662
+ * @return array UCS4 sequence with syllables composed
663
+ * @access private
664
+ */
665
+ function _hangul_compose($input)
666
+ {
667
+ $inp_len = count($input);
668
+ if (!$inp_len) return array();
669
+ $result = array();
670
+ $last = (int) $input[0];
671
+ $result[] = $last; // copy first char from input to output
672
+
673
+ for ($i = 1; $i < $inp_len; ++$i) {
674
+ $char = (int) $input[$i];
675
+ $sindex = $last - $this->_sbase;
676
+ $lindex = $last - $this->_lbase;
677
+ $vindex = $char - $this->_vbase;
678
+ $tindex = $char - $this->_tbase;
679
+ // Find out, whether two current characters are LV and T
680
+ if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0)
681
+ && 0 <= $tindex && $tindex <= $this->_tcount) {
682
+ // create syllable of form LVT
683
+ $last += $tindex;
684
+ $result[(count($result) - 1)] = $last; // reset last
685
+ continue; // discard char
686
+ }
687
+ // Find out, whether two current characters form L and V
688
+ if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) {
689
+ // create syllable of form LV
690
+ $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount;
691
+ $result[(count($result) - 1)] = $last; // reset last
692
+ continue; // discard char
693
+ }
694
+ // if neither case was true, just add the character
695
+ $last = $char;
696
+ $result[] = $char;
697
+ }
698
+ return $result;
699
+ }
700
+
701
+ /**
702
+ * Returns the combining class of a certain wide char
703
+ * @param integer Wide char to check (32bit integer)
704
+ * @return integer Combining class if found, else 0
705
+ * @access private
706
+ */
707
+ function _get_combining_class($char)
708
+ {
709
+ return isset($this->NP['norm_combcls'][$char]) ? $this->NP['norm_combcls'][$char] : 0;
710
+ }
711
+
712
+ /**
713
+ * Apllies the cannonical ordering of a decomposed UCS4 sequence
714
+ * @param array Decomposed UCS4 sequence
715
+ * @return array Ordered USC4 sequence
716
+ * @access private
717
+ */
718
+ function _apply_cannonical_ordering($input)
719
+ {
720
+ $swap = true;
721
+ $size = count($input);
722
+ while ($swap) {
723
+ $swap = false;
724
+ $last = $this->_get_combining_class(intval($input[0]));
725
+ for ($i = 0; $i < $size-1; ++$i) {
726
+ $next = $this->_get_combining_class(intval($input[$i+1]));
727
+ if ($next != 0 && $last > $next) {
728
+ // Move item leftward until it fits
729
+ for ($j = $i + 1; $j > 0; --$j) {
730
+ if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break;
731
+ $t = intval($input[$j]);
732
+ $input[$j] = intval($input[$j-1]);
733
+ $input[$j-1] = $t;
734
+ $swap = true;
735
+ }
736
+ // Reentering the loop looking at the old character again
737
+ $next = $last;
738
+ }
739
+ $last = $next;
740
+ }
741
+ }
742
+ return $input;
743
+ }
744
+
745
+ /**
746
+ * Do composition of a sequence of starter and non-starter
747
+ * @param array UCS4 Decomposed sequence
748
+ * @return array Ordered USC4 sequence
749
+ * @access private
750
+ */
751
+ function _combine($input)
752
+ {
753
+ $inp_len = count($input);
754
+ foreach ($this->NP['replacemaps'] as $np_src => $np_target) {
755
+ if ($np_target[0] != $input[0]) continue;
756
+ if (count($np_target) != $inp_len) continue;
757
+ $hit = false;
758
+ foreach ($input as $k2 => $v2) {
759
+ if ($v2 == $np_target[$k2]) {
760
+ $hit = true;
761
+ } else {
762
+ $hit = false;
763
+ break;
764
+ }
765
+ }
766
+ if ($hit) return $np_src;
767
+ }
768
+ return false;
769
+ }
770
+
771
+ /**
772
+ * This converts an UTF-8 encoded string to its UCS-4 representation
773
+ * By talking about UCS-4 "strings" we mean arrays of 32bit integers representing
774
+ * each of the "chars". This is due to PHP not being able to handle strings with
775
+ * bit depth different from 8. This apllies to the reverse method _ucs4_to_utf8(), too.
776
+ * The following UTF-8 encodings are supported:
777
+ * bytes bits representation
778
+ * 1 7 0xxxxxxx
779
+ * 2 11 110xxxxx 10xxxxxx
780
+ * 3 16 1110xxxx 10xxxxxx 10xxxxxx
781
+ * 4 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
782
+ * 5 26 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
783
+ * 6 31 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
784
+ * Each x represents a bit that can be used to store character data.
785
+ * The five and six byte sequences are part of Annex D of ISO/IEC 10646-1:2000
786
+ * @access private
787
+ */
788
+ function _utf8_to_ucs4($input)
789
+ {
790
+ $output = array();
791
+ $out_len = 0;
792
+ $inp_len = strlen($input);
793
+ $mode = 'next';
794
+ $test = 'none';
795
+ for ($k = 0; $k < $inp_len; ++$k) {
796
+ $v = ord($input{$k}); // Extract byte from input string
797
+
798
+ if ($v < 128) { // We found an ASCII char - put into stirng as is
799
+ $output[$out_len] = $v;
800
+ ++$out_len;
801
+ if ('add' == $mode) {
802
+ $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
803
+ return false;
804
+ }
805
+ continue;
806
+ }
807
+ if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
808
+ $start_byte = $v;
809
+ $mode = 'add';
810
+ $test = 'range';
811
+ if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
812
+ $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
813
+ $v = ($v - 192) << 6;
814
+ } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
815
+ $next_byte = 1;
816
+ $v = ($v - 224) << 12;
817
+ } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
818
+ $next_byte = 2;
819
+ $v = ($v - 240) << 18;
820
+ } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
821
+ $next_byte = 3;
822
+ $v = ($v - 248) << 24;
823
+ } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
824
+ $next_byte = 4;
825
+ $v = ($v - 252) << 30;
826
+ } else {
827
+ $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k);
828
+ return false;
829
+ }
830
+ if ('add' == $mode) {
831
+ $output[$out_len] = (int) $v;
832
+ ++$out_len;
833
+ continue;
834
+ }
835
+ }
836
+ if ('add' == $mode) {
837
+ if (!$this->_allow_overlong && $test == 'range') {
838
+ $test = 'none';
839
+ if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
840
+ $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
841
+ return false;
842
+ }
843
+ }
844
+ if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
845
+ $v = ($v - 128) << ($next_byte * 6);
846
+ $output[($out_len - 1)] += $v;
847
+ --$next_byte;
848
+ } else {
849
+ $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
850
+ return false;
851
+ }
852
+ if ($next_byte < 0) {
853
+ $mode = 'next';
854
+ }
855
+ }
856
+ } // for
857
+ return $output;
858
+ }
859
+
860
+ /**
861
+ * Convert UCS-4 string into UTF-8 string
862
+ * See _utf8_to_ucs4() for details
863
+ * @access private
864
+ */
865
+ function _ucs4_to_utf8($input)
866
+ {
867
+ $output = '';
868
+ $k = 0;
869
+ foreach ($input as $v) {
870
+ ++$k;
871
+ // $v = ord($v);
872
+ if ($v < 128) { // 7bit are transferred literally
873
+ $output .= chr($v);
874
+ } elseif ($v < (1 << 11)) { // 2 bytes
875
+ $output .= chr(192 + ($v >> 6)) . chr(128 + ($v & 63));
876
+ } elseif ($v < (1 << 16)) { // 3 bytes
877
+ $output .= chr(224 + ($v >> 12)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
878
+ } elseif ($v < (1 << 21)) { // 4 bytes
879
+ $output .= chr(240 + ($v >> 18)) . chr(128 + (($v >> 12) & 63))
880
+ . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
881
+ } elseif ($v < (1 << 26)) { // 5 bytes
882
+ $output .= chr(248 + ($v >> 24)) . chr(128 + (($v >> 18) & 63))
883
+ . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63))
884
+ . chr(128 + ($v & 63));
885
+ } elseif ($v < (1 << 31)) { // 6 bytes
886
+ $output .= chr(252 + ($v >> 30)) . chr(128 + (($v >> 24) & 63))
887
+ . chr(128 + (($v >> 18) & 63)) . chr(128 + (($v >> 12) & 63))
888
+ . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
889
+ } else {
890
+ $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k);
891
+ return false;
892
+ }
893
+ }
894
+ return $output;
895
+ }
896
+
897
+ /**
898
+ * Convert UCS-4 array into UCS-4 string
899
+ *
900
+ * @access private
901
+ */
902
+ function _ucs4_to_ucs4_string($input)
903
+ {
904
+ $output = '';
905
+ // Take array values and split output to 4 bytes per value
906
+ // The bit mask is 255, which reads &11111111
907
+ foreach ($input as $v) {
908
+ $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255);
909
+ }
910
+ return $output;
911
+ }
912
+
913
+ /**
914
+ * Convert UCS-4 strin into UCS-4 garray
915
+ *
916
+ * @access private
917
+ */
918
+ function _ucs4_string_to_ucs4($input)
919
+ {
920
+ $output = array();
921
+ $inp_len = strlen($input);
922
+ // Input length must be dividable by 4
923
+ if ($inp_len % 4) {
924
+ $this->_error('Input UCS4 string is broken');
925
+ return false;
926
+ }
927
+ // Empty input - return empty output
928
+ if (!$inp_len) return $output;
929
+ for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
930
+ // Increment output position every 4 input bytes
931
+ if (!($i % 4)) {
932
+ $out_len++;
933
+ $output[$out_len] = 0;
934
+ }
935
+ $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
936
+ }
937
+ return $output;
938
+ }
939
+ }
940
+
941
+ /**
942
+ * Adapter class for aligning the API of idna_convert with that of Net_IDNA
943
+ * @author Matthias Sommerfeld <mso@phlylabs.de>
944
+ */
945
+ class Net_IDNA_php4 extends idna_convert
946
+ {
947
+ /**
948
+ * Sets a new option value. Available options and values:
949
+ * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8,
950
+ * 'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8]
951
+ * [overlong - Unicode does not allow unnecessarily long encodings of chars,
952
+ * to allow this, set this parameter to true, else to false;
953
+ * default is false.]
954
+ * [strict - true: strict mode, good for registration purposes - Causes errors
955
+ * on failures; false: loose mode, ideal for "wildlife" applications
956
+ * by silently ignoring errors and returning the original input instead
957
+ *
958
+ * @param mixed Parameter to set (string: single parameter; array of Parameter => Value pairs)
959
+ * @param string Value to use (if parameter 1 is a string)
960
+ * @return boolean true on success, false otherwise
961
+ * @access public
962
+ */
963
+ function setParams($option, $param = false)
964
+ {
965
+ return $this->IC->set_parameters($option, $param);
966
+ }
967
+ }
968
+
969
+ ?>
libs/SimpleCluvPie/idn/npdata.ser ADDED
@@ -0,0 +1 @@
 
1
+ a:6:{s:11:"map_nothing";a:27:{i:0;i:173;i:1;i:847;i:2;i:6150;i:3;i:6155;i:4;i:6156;i:5;i:6157;i:6;i:8203;i:7;i:8204;i:8;i:8205;i:9;i:8288;i:10;i:65024;i:11;i:65025;i:12;i:65026;i:13;i:65027;i:14;i:65028;i:15;i:65029;i:16;i:65030;i:17;i:65031;i:18;i:65032;i:19;i:65033;i:20;i:65034;i:21;i:65035;i:22;i:65036;i:23;i:65037;i:24;i:65038;i:25;i:65039;i:26;i:65279;}s:18:"general_prohibited";a:64:{i:0;i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;i:6;i:7;i:7;i:8;i:8;i:9;i:9;i:10;i:10;i:11;i:11;i:12;i:12;i:13;i:13;i:14;i:14;i:15;i:15;i:16;i:16;i:17;i:17;i:18;i:18;i:19;i:19;i:20;i:20;i:21;i:21;i:22;i:22;i:23;i:23;i:24;i:24;i:25;i:25;i:26;i:26;i:27;i:27;i:28;i:28;i:29;i:29;i:30;i:30;i:31;i:31;i:32;i:32;i:33;i:33;i:34;i:34;i:35;i:35;i:36;i:36;i:37;i:37;i:38;i:38;i:39;i:39;i:40;i:40;i:41;i:41;i:42;i:42;i:43;i:43;i:44;i:44;i:45;i:47;i:46;i:59;i:47;i:60;i:48;i:61;i:49;i:62;i:50;i:63;i:51;i:64;i:52;i:91;i:53;i:92;i:54;i:93;i:55;i:94;i:56;i:95;i:57;i:96;i:58;i:123;i:59;i:124;i:60;i:125;i:61;i:126;i:62;i:127;i:63;i:12290;}s:8:"prohibit";a:84:{i:0;i:160;i:1;i:5760;i:2;i:8192;i:3;i:8193;i:4;i:8194;i:5;i:8195;i:6;i:8196;i:7;i:8197;i:8;i:8198;i:9;i:8199;i:10;i:8200;i:11;i:8201;i:12;i:8202;i:13;i:8203;i:14;i:8239;i:15;i:8287;i:16;i:12288;i:17;i:1757;i:18;i:1807;i:19;i:6158;i:20;i:8204;i:21;i:8205;i:22;i:8232;i:23;i:8233;i:24;i:65279;i:25;i:65529;i:26;i:65530;i:27;i:65531;i:28;i:65532;i:29;i:65534;i:30;i:65535;i:31;i:131070;i:32;i:131071;i:33;i:196606;i:34;i:196607;i:35;i:262142;i:36;i:262143;i:37;i:327678;i:38;i:327679;i:39;i:393214;i:40;i:393215;i:41;i:458750;i:42;i:458751;i:43;i:524286;i:44;i:524287;i:45;i:589822;i:46;i:589823;i:47;i:655358;i:48;i:655359;i:49;i:720894;i:50;i:720895;i:51;i:786430;i:52;i:786431;i:53;i:851966;i:54;i:851967;i:55;i:917502;i:56;i:917503;i:57;i:983038;i:58;i:983039;i:59;i:1048574;i:60;i:1048575;i:61;i:1114110;i:62;i:1114111;i:63;i:65529;i:64;i:65530;i:65;i:65531;i:66;i:65532;i:67;i:65533;i:68;i:832;i:69;i:833;i:70;i:8206;i:71;i:8207;i:72;i:8234;i:73;i:8235;i:74;i:8236;i:75;i:8237;i:76;i:8238;i:77;i:8298;i:78;i:8299;i:79;i:8300;i:80;i:8301;i:81;i:8302;i:82;i:8303;i:83;i:917505;}s:15:"prohibit_ranges";a:10:{i:0;a:2:{i:0;i:128;i:1;i:159;}i:1;a:2:{i:0;i:8288;i:1;i:8303;}i:2;a:2:{i:0;i:119155;i:1;i:119162;}i:3;a:2:{i:0;i:57344;i:1;i:63743;}i:4;a:2:{i:0;i:983040;i:1;i:1048573;}i:5;a:2:{i:0;i:1048576;i:1;i:1114109;}i:6;a:2:{i:0;i:64976;i:1;i:65007;}i:7;a:2:{i:0;i:55296;i:1;i:57343;}i:8;a:2:{i:0;i:12272;i:1;i:12283;}i:9;a:2:{i:0;i:917536;i:1;i:917631;}}s:11:"replacemaps";a:1401:{i:65;a:1:{i:0;i:97;}i:66;a:1:{i:0;i:98;}i:67;a:1:{i:0;i:99;}i:68;a:1:{i:0;i:100;}i:69;a:1:{i:0;i:101;}i:70;a:1:{i:0;i:102;}i:71;a:1:{i:0;i:103;}i:72;a:1:{i:0;i:104;}i:73;a:1:{i:0;i:105;}i:74;a:1:{i:0;i:106;}i:75;a:1:{i:0;i:107;}i:76;a:1:{i:0;i:108;}i:77;a:1:{i:0;i:109;}i:78;a:1:{i:0;i:110;}i:79;a:1:{i:0;i:111;}i:80;a:1:{i:0;i:112;}i:81;a:1:{i:0;i:113;}i:82;a:1:{i:0;i:114;}i:83;a:1:{i:0;i:115;}i:84;a:1:{i:0;i:116;}i:85;a:1:{i:0;i:117;}i:86;a:1:{i:0;i:118;}i:87;a:1:{i:0;i:119;}i:88;a:1:{i:0;i:120;}i:89;a:1:{i:0;i:121;}i:90;a:1:{i:0;i:122;}i:181;a:1:{i:0;i:956;}i:192;a:1:{i:0;i:224;}i:193;a:1:{i:0;i:225;}i:194;a:1:{i:0;i:226;}i:195;a:1:{i:0;i:227;}i:196;a:1:{i:0;i:228;}i:197;a:1:{i:0;i:229;}i:198;a:1:{i:0;i:230;}i:199;a:1:{i:0;i:231;}i:200;a:1:{i:0;i:232;}i:201;a:1:{i:0;i:233;}i:202;a:1:{i:0;i:234;}i:203;a:1:{i:0;i:235;}i:204;a:1:{i:0;i:236;}i:205;a:1:{i:0;i:237;}i:206;a:1:{i:0;i:238;}i:207;a:1:{i:0;i:239;}i:208;a:1:{i:0;i:240;}i:209;a:1:{i:0;i:241;}i:210;a:1:{i:0;i:242;}i:211;a:1:{i:0;i:243;}i:212;a:1:{i:0;i:244;}i:213;a:1:{i:0;i:245;}i:214;a:1:{i:0;i:246;}i:216;a:1:{i:0;i:248;}i:217;a:1:{i:0;i:249;}i:218;a:1:{i:0;i:250;}i:219;a:1:{i:0;i:251;}i:220;a:1:{i:0;i:252;}i:221;a:1:{i:0;i:253;}i:222;a:1:{i:0;i:254;}i:223;a:2:{i:0;i:115;i:1;i:115;}i:256;a:1:{i:0;i:257;}i:258;a:1:{i:0;i:259;}i:260;a:1:{i:0;i:261;}i:262;a:1:{i:0;i:263;}i:264;a:1:{i:0;i:265;}i:266;a:1:{i:0;i:267;}i:268;a:1:{i:0;i:269;}i:270;a:1:{i:0;i:271;}i:272;a:1:{i:0;i:273;}i:274;a:1:{i:0;i:275;}i:276;a:1:{i:0;i:277;}i:278;a:1:{i:0;i:279;}i:280;a:1:{i:0;i:281;}i:282;a:1:{i:0;i:283;}i:284;a:1:{i:0;i:285;}i:286;a:1:{i:0;i:287;}i:288;a:1:{i:0;i:289;}i:290;a:1:{i:0;i:291;}i:292;a:1:{i:0;i:293;}i:294;a:1:{i:0;i:295;}i:296;a:1:{i:0;i:297;}i:298;a:1:{i:0;i:299;}i:300;a:1:{i:0;i:301;}i:302;a:1:{i:0;i:303;}i:304;a:2:{i:0;i:105;i:1;i:775;}i:306;a:1:{i:0;i:307;}i:308;a:1:{i:0;i:309;}i:310;a:1:{i:0;i:311;}i:313;a:1:{i:0;i:314;}i:315;a:1:{i:0;i:316;}i:317;a:1:{i:0;i:318;}i:319;a:1:{i:0;i:320;}i:321;a:1:{i:0;i:322;}i:323;a:1:{i:0;i:324;}i:325;a:1:{i:0;i:326;}i:327;a:1:{i:0;i:328;}i:329;a:2:{i:0;i:700;i:1;i:110;}i:330;a:1:{i:0;i:331;}i:332;a:1:{i:0;i:333;}i:334;a:1:{i:0;i:335;}i:336;a:1:{i:0;i:337;}i:338;a:1:{i:0;i:339;}i:340;a:1:{i:0;i:341;}i:342;a:1:{i:0;i:343;}i:344;a:1:{i:0;i:345;}i:346;a:1:{i:0;i:347;}i:348;a:1:{i:0;i:349;}i:350;a:1:{i:0;i:351;}i:352;a:1:{i:0;i:353;}i:354;a:1:{i:0;i:355;}i:356;a:1:{i:0;i:357;}i:358;a:1:{i:0;i:359;}i:360;a:1:{i:0;i:361;}i:362;a:1:{i:0;i:363;}i:364;a:1:{i:0;i:365;}i:366;a:1:{i:0;i:367;}i:368;a:1:{i:0;i:369;}i:370;a:1:{i:0;i:371;}i:372;a:1:{i:0;i:373;}i:374;a:1:{i:0;i:375;}i:376;a:1:{i:0;i:255;}i:377;a:1:{i:0;i:378;}i:379;a:1:{i:0;i:380;}i:381;a:1:{i:0;i:382;}i:383;a:1:{i:0;i:115;}i:385;a:1:{i:0;i:595;}i:386;a:1:{i:0;i:387;}i:388;a:1:{i:0;i:389;}i:390;a:1:{i:0;i:596;}i:391;a:1:{i:0;i:392;}i:393;a:1:{i:0;i:598;}i:394;a:1:{i:0;i:599;}i:395;a:1:{i:0;i:396;}i:398;a:1:{i:0;i:477;}i:399;a:1:{i:0;i:601;}i:400;a:1:{i:0;i:603;}i:401;a:1:{i:0;i:402;}i:403;a:1:{i:0;i:608;}i:404;a:1:{i:0;i:611;}i:406;a:1:{i:0;i:617;}i:407;a:1:{i:0;i:616;}i:408;a:1:{i:0;i:409;}i:412;a:1:{i:0;i:623;}i:413;a:1:{i:0;i:626;}i:415;a:1:{i:0;i:629;}i:416;a:1:{i:0;i:417;}i:418;a:1:{i:0;i:419;}i:420;a:1:{i:0;i:421;}i:422;a:1:{i:0;i:640;}i:423;a:1:{i:0;i:424;}i:425;a:1:{i:0;i:643;}i:428;a:1:{i:0;i:429;}i:430;a:1:{i:0;i:648;}i:431;a:1:{i:0;i:432;}i:433;a:1:{i:0;i:650;}i:434;a:1:{i:0;i:651;}i:435;a:1:{i:0;i:436;}i:437;a:1:{i:0;i:438;}i:439;a:1:{i:0;i:658;}i:440;a:1:{i:0;i:441;}i:444;a:1:{i:0;i:445;}i:452;a:1:{i:0;i:454;}i:453;a:1:{i:0;i:454;}i:455;a:1:{i:0;i:457;}i:456;a:1:{i:0;i:457;}i:458;a:1:{i:0;i:460;}i:459;a:1:{i:0;i:460;}i:461;a:1:{i:0;i:462;}i:463;a:1:{i:0;i:464;}i:465;a:1:{i:0;i:466;}i:467;a:1:{i:0;i:468;}i:469;a:1:{i:0;i:470;}i:471;a:1:{i:0;i:472;}i:473;a:1:{i:0;i:474;}i:475;a:1:{i:0;i:476;}i:478;a:1:{i:0;i:479;}i:480;a:1:{i:0;i:481;}i:482;a:1:{i:0;i:483;}i:484;a:1:{i:0;i:485;}i:486;a:1:{i:0;i:487;}i:488;a:1:{i:0;i:489;}i:490;a:1:{i:0;i:491;}i:492;a:1:{i:0;i:493;}i:494;a:1:{i:0;i:495;}i:496;a:2:{i:0;i:106;i:1;i:780;}i:497;a:1:{i:0;i:499;}i:498;a:1:{i:0;i:499;}i:500;a:1:{i:0;i:501;}i:502;a:1:{i:0;i:405;}i:503;a:1:{i:0;i:447;}i:504;a:1:{i:0;i:505;}i:506;a:1:{i:0;i:507;}i:508;a:1:{i:0;i:509;}i:510;a:1:{i:0;i:511;}i:512;a:1:{i:0;i:513;}i:514;a:1:{i:0;i:515;}i:516;a:1:{i:0;i:517;}i:518;a:1:{i:0;i:519;}i:520;a:1:{i:0;i:521;}i:522;a:1:{i:0;i:523;}i:524;a:1:{i:0;i:525;}i:526;a:1:{i:0;i:527;}i:528;a:1:{i:0;i:529;}i:530;a:1:{i:0;i:531;}i:532;a:1:{i:0;i:533;}i:534;a:1:{i:0;i:535;}i:536;a:1:{i:0;i:537;}i:538;a:1:{i:0;i:539;}i:540;a:1:{i:0;i:541;}i:542;a:1:{i:0;i:543;}i:544;a:1:{i:0;i:414;}i:546;a:1:{i:0;i:547;}i:548;a:1:{i:0;i:549;}i:550;a:1:{i:0;i:551;}i:552;a:1:{i:0;i:553;}i:554;a:1:{i:0;i:555;}i:556;a:1:{i:0;i:557;}i:558;a:1:{i:0;i:559;}i:560;a:1:{i:0;i:561;}i:562;a:1:{i:0;i:563;}i:837;a:1:{i:0;i:953;}i:890;a:2:{i:0;i:32;i:1;i:953;}i:902;a:1:{i:0;i:940;}i:904;a:1:{i:0;i:941;}i:905;a:1:{i:0;i:942;}i:906;a:1:{i:0;i:943;}i:908;a:1:{i:0;i:972;}i:910;a:1:{i:0;i:973;}i:911;a:1:{i:0;i:974;}i:912;a:3:{i:0;i:953;i:1;i:776;i:2;i:769;}i:913;a:1:{i:0;i:945;}i:914;a:1:{i:0;i:946;}i:915;a:1:{i:0;i:947;}i:916;a:1:{i:0;i:948;}i:917;a:1:{i:0;i:949;}i:918;a:1:{i:0;i:950;}i:919;a:1:{i:0;i:951;}i:920;a:1:{i:0;i:952;}i:921;a:1:{i:0;i:953;}i:922;a:1:{i:0;i:954;}i:923;a:1:{i:0;i:955;}i:924;a:1:{i:0;i:956;}i:925;a:1:{i:0;i:957;}i:926;a:1:{i:0;i:958;}i:927;a:1:{i:0;i:959;}i:928;a:1:{i:0;i:960;}i:929;a:1:{i:0;i:961;}i:931;a:1:{i:0;i:963;}i:932;a:1:{i:0;i:964;}i:933;a:1:{i:0;i:965;}i:934;a:1:{i:0;i:966;}i:935;a:1:{i:0;i:967;}i:936;a:1:{i:0;i:968;}i:937;a:1:{i:0;i:969;}i:938;a:1:{i:0;i:970;}i:939;a:1:{i:0;i:971;}i:944;a:3:{i:0;i:965;i:1;i:776;i:2;i:769;}i:962;a:1:{i:0;i:963;}i:976;a:1:{i:0;i:946;}i:977;a:1:{i:0;i:952;}i:978;a:1:{i:0;i:965;}i:979;a:1:{i:0;i:973;}i:980;a:1:{i:0;i:971;}i:981;a:1:{i:0;i:966;}i:982;a:1:{i:0;i:960;}i:984;a:1:{i:0;i:985;}i:986;a:1:{i:0;i:987;}i:988;a:1:{i:0;i:989;}i:990;a:1:{i:0;i:991;}i:992;a:1:{i:0;i:993;}i:994;a:1:{i:0;i:995;}i:996;a:1:{i:0;i:997;}i:998;a:1:{i:0;i:999;}i:1000;a:1:{i:0;i:1001;}i:1002;a:1:{i:0;i:1003;}i:1004;a:1:{i:0;i:1005;}i:1006;a:1:{i:0;i:1007;}i:1008;a:1:{i:0;i:954;}i:1009;a:1:{i:0;i:961;}i:1010;a:1:{i:0;i:963;}i:1012;a:1:{i:0;i:952;}i:1013;a:1:{i:0;i:949;}i:1024;a:1:{i:0;i:1104;}i:1025;a:1:{i:0;i:1105;}i:1026;a:1:{i:0;i:1106;}i:1027;a:1:{i:0;i:1107;}i:1028;a:1:{i:0;i:1108;}i:1029;a:1:{i:0;i:1109;}i:1030;a:1:{i:0;i:1110;}i:1031;a:1:{i:0;i:1111;}i:1032;a:1:{i:0;i:1112;}i:1033;a:1:{i:0;i:1113;}i:1034;a:1:{i:0;i:1114;}i:1035;a:1:{i:0;i:1115;}i:1036;a:1:{i:0;i:1116;}i:1037;a:1:{i:0;i:1117;}i:1038;a:1:{i:0;i:1118;}i:1039;a:1:{i:0;i:1119;}i:1040;a:1:{i:0;i:1072;}i:1041;a:1:{i:0;i:1073;}i:1042;a:1:{i:0;i:1074;}i:1043;a:1:{i:0;i:1075;}i:1044;a:1:{i:0;i:1076;}i:1045;a:1:{i:0;i:1077;}i:1046;a:1:{i:0;i:1078;}i:1047;a:1:{i:0;i:1079;}i:1048;a:1:{i:0;i:1080;}i:1049;a:1:{i:0;i:1081;}i:1050;a:1:{i:0;i:1082;}i:1051;a:1:{i:0;i:1083;}i:1052;a:1:{i:0;i:1084;}i:1053;a:1:{i:0;i:1085;}i:1054;a:1:{i:0;i:1086;}i:1055;a:1:{i:0;i:1087;}i:1056;a:1:{i:0;i:1088;}i:1057;a:1:{i:0;i:1089;}i:1058;a:1:{i:0;i:1090;}i:1059;a:1:{i:0;i:1091;}i:1060;a:1:{i:0;i:1092;}i:1061;a:1:{i:0;i:1093;}i:1062;a:1:{i:0;i:1094;}i:1063;a:1:{i:0;i:1095;}i:1064;a:1:{i:0;i:1096;}i:1065;a:1:{i:0;i:1097;}i:1066;a:1:{i:0;i:1098;}i:1067;a:1:{i:0;i:1099;}i:1068;a:1:{i:0;i:1100;}i:1069;a:1:{i:0;i:1101;}i:1070;a:1:{i:0;i:1102;}i:1071;a:1:{i:0;i:1103;}i:1120;a:1:{i:0;i:1121;}i:1122;a:1:{i:0;i:1123;}i:1124;a:1:{i:0;i:1125;}i:1126;a:1:{i:0;i:1127;}i:1128;a:1:{i:0;i:1129;}i:1130;a:1:{i:0;i:1131;}i:1132;a:1:{i:0;i:1133;}i:1134;a:1:{i:0;i:1135;}i:1136;a:1:{i:0;i:1137;}i:1138;a:1:{i:0;i:1139;}i:1140;a:1:{i:0;i:1141;}i:1142;a:1:{i:0;i:1143;}i:1144;a:1:{i:0;i:1145;}i:1146;a:1:{i:0;i:1147;}i:1148;a:1:{i:0;i:1149;}i:1150;a:1:{i:0;i:1151;}i:1152;a:1:{i:0;i:1153;}i:1162;a:1:{i:0;i:1163;}i:1164;a:1:{i:0;i:1165;}i:1166;a:1:{i:0;i:1167;}i:1168;a:1:{i:0;i:1169;}i:1170;a:1:{i:0;i:1171;}i:1172;a:1:{i:0;i:1173;}i:1174;a:1:{i:0;i:1175;}i:1176;a:1:{i:0;i:1177;}i:1178;a:1:{i:0;i:1179;}i:1180;a:1:{i:0;i:1181;}i:1182;a:1:{i:0;i:1183;}i:1184;a:1:{i:0;i:1185;}i:1186;a:1:{i:0;i:1187;}i:1188;a:1:{i:0;i:1189;}i:1190;a:1:{i:0;i:1191;}i:1192;a:1:{i:0;i:1193;}i:1194;a:1:{i:0;i:1195;}i:1196;a:1:{i:0;i:1197;}i:1198;a:1:{i:0;i:1199;}i:1200;a:1:{i:0;i:1201;}i:1202;a:1:{i:0;i:1203;}i:1204;a:1:{i:0;i:1205;}i:1206;a:1:{i:0;i:1207;}i:1208;a:1:{i:0;i:1209;}i:1210;a:1:{i:0;i:1211;}i:1212;a:1:{i:0;i:1213;}i:1214;a:1:{i:0;i:1215;}i:1217;a:1:{i:0;i:1218;}i:1219;a:1:{i:0;i:1220;}i:1221;a:1:{i:0;i:1222;}i:1223;a:1:{i:0;i:1224;}i:1225;a:1:{i:0;i:1226;}i:1227;a:1:{i:0;i:1228;}i:1229;a:1:{i:0;i:1230;}i:1232;a:1:{i:0;i:1233;}i:1234;a:1:{i:0;i:1235;}i:1236;a:1:{i:0;i:1237;}i:1238;a:1:{i:0;i:1239;}i:1240;a:1:{i:0;i:1241;}i:1242;a:1:{i:0;i:1243;}i:1244;a:1:{i:0;i:1245;}i:1246;a:1:{i:0;i:1247;}i:1248;a:1:{i:0;i:1249;}i:1250;a:1:{i:0;i:1251;}i:1252;a:1:{i:0;i:1253;}i:1254;a:1:{i:0;i:1255;}i:1256;a:1:{i:0;i:1257;}i:1258;a:1:{i:0;i:1259;}i:1260;a:1:{i:0;i:1261;}i:1262;a:1:{i:0;i:1263;}i:1264;a:1:{i:0;i:1265;}i:1266;a:1:{i:0;i:1267;}i:1268;a:1:{i:0;i:1269;}i:1272;a:1:{i:0;i:1273;}i:1280;a:1:{i:0;i:1281;}i:1282;a:1:{i:0;i:1283;}i:1284;a:1:{i:0;i:1285;}i:1286;a:1:{i:0;i:1287;}i:1288;a:1:{i:0;i:1289;}i:1290;a:1:{i:0;i:1291;}i:1292;a:1:{i:0;i:1293;}i:1294;a:1:{i:0;i:1295;}i:1329;a:1:{i:0;i:1377;}i:1330;a:1:{i:0;i:1378;}i:1331;a:1:{i:0;i:1379;}i:1332;a:1:{i:0;i:1380;}i:1333;a:1:{i:0;i:1381;}i:1334;a:1:{i:0;i:1382;}i:1335;a:1:{i:0;i:1383;}i:1336;a:1:{i:0;i:1384;}i:1337;a:1:{i:0;i:1385;}i:1338;a:1:{i:0;i:1386;}i:1339;a:1:{i:0;i:1387;}i:1340;a:1:{i:0;i:1388;}i:1341;a:1:{i:0;i:1389;}i:1342;a:1:{i:0;i:1390;}i:1343;a:1:{i:0;i:1391;}i:1344;a:1:{i:0;i:1392;}i:1345;a:1:{i:0;i:1393;}i:1346;a:1:{i:0;i:1394;}i:1347;a:1:{i:0;i:1395;}i:1348;a:1:{i:0;i:1396;}i:1349;a:1:{i:0;i:1397;}i:1350;a:1:{i:0;i:1398;}i:1351;a:1:{i:0;i:1399;}i:1352;a:1:{i:0;i:1400;}i:1353;a:1:{i:0;i:1401;}i:1354;a:1:{i:0;i:1402;}i:1355;a:1:{i:0;i:1403;}i:1356;a:1:{i:0;i:1404;}i:1357;a:1:{i:0;i:1405;}i:1358;a:1:{i:0;i:1406;}i:1359;a:1:{i:0;i:1407;}i:1360;a:1:{i:0;i:1408;}i:1361;a:1:{i:0;i:1409;}i:1362;a:1:{i:0;i:1410;}i:1363;a:1:{i:0;i:1411;}i:1364;a:1:{i:0;i:1412;}i:1365;a:1:{i:0;i:1413;}i:1366;a:1:{i:0;i:1414;}i:1415;a:2:{i:0;i:1381;i:1;i:1410;}i:7680;a:1:{i:0;i:7681;}i:7682;a:1:{i:0;i:7683;}i:7684;a:1:{i:0;i:7685;}i:7686;a:1:{i:0;i:7687;}i:7688;a:1:{i:0;i:7689;}i:7690;a:1:{i:0;i:7691;}i:7692;a:1:{i:0;i:7693;}i:7694;a:1:{i:0;i:7695;}i:7696;a:1:{i:0;i:7697;}i:7698;a:1:{i:0;i:7699;}i:7700;a:1:{i:0;i:7701;}i:7702;a:1:{i:0;i:7703;}i:7704;a:1:{i:0;i:7705;}i:7706;a:1:{i:0;i:7707;}i:7708;a:1:{i:0;i:7709;}i:7710;a:1:{i:0;i:7711;}i:7712;a:1:{i:0;i:7713;}i:7714;a:1:{i:0;i:7715;}i:7716;a:1:{i:0;i:7717;}i:7718;a:1:{i:0;i:7719;}i:7720;a:1:{i:0;i:7721;}i:7722;a:1:{i:0;i:7723;}i:7724;a:1:{i:0;i:7725;}i:7726;a:1:{i:0;i:7727;}i:7728;a:1:{i:0;i:7729;}i:7730;a:1:{i:0;i:7731;}i:7732;a:1:{i:0;i:7733;}i:7734;a:1:{i:0;i:7735;}i:7736;a:1:{i:0;i:7737;}i:7738;a:1:{i:0;i:7739;}i:7740;a:1:{i:0;i:7741;}i:7742;a:1:{i:0;i:7743;}i:7744;a:1:{i:0;i:7745;}i:7746;a:1:{i:0;i:7747;}i:7748;a:1:{i:0;i:7749;}i:7750;a:1:{i:0;i:7751;}i:7752;a:1:{i:0;i:7753;}i:7754;a:1:{i:0;i:7755;}i:7756;a:1:{i:0;i:7757;}i:7758;a:1:{i:0;i:7759;}i:7760;a:1:{i:0;i:7761;}i:7762;a:1:{i:0;i:7763;}i:7764;a:1:{i:0;i:7765;}i:7766;a:1:{i:0;i:7767;}i:7768;a:1:{i:0;i:7769;}i:7770;a:1:{i:0;i:7771;}i:7772;a:1:{i:0;i:7773;}i:7774;a:1:{i:0;i:7775;}i:7776;a:1:{i:0;i:7777;}i:7778;a:1:{i:0;i:7779;}i:7780;a:1:{i:0;i:7781;}i:7782;a:1:{i:0;i:7783;}i:7784;a:1:{i:0;i:7785;}i:7786;a:1:{i:0;i:7787;}i:7788;a:1:{i:0;i:7789;}i:7790;a:1:{i:0;i:7791;}i:7792;a:1:{i:0;i:7793;}i:7794;a:1:{i:0;i:7795;}i:7796;a:1:{i:0;i:7797;}i:7798;a:1:{i:0;i:7799;}i:7800;a:1:{i:0;i:7801;}i:7802;a:1:{i:0;i:7803;}i:7804;a:1:{i:0;i:7805;}i:7806;a:1:{i:0;i:7807;}i:7808;a:1:{i:0;i:7809;}i:7810;a:1:{i:0;i:7811;}i:7812;a:1:{i:0;i:7813;}i:7814;a:1:{i:0;i:7815;}i:7816;a:1:{i:0;i:7817;}i:7818;a:1:{i:0;i:7819;}i:7820;a:1:{i:0;i:7821;}i:7822;a:1:{i:0;i:7823;}i:7824;a:1:{i:0;i:7825;}i:7826;a:1:{i:0;i:7827;}i:7828;a:1:{i:0;i:7829;}i:7830;a:2:{i:0;i:104;i:1;i:817;}i:7831;a:2:{i:0;i:116;i:1;i:776;}i:7832;a:2:{i:0;i:119;i:1;i:778;}i:7833;a:2:{i:0;i:121;i:1;i:778;}i:7834;a:2:{i:0;i:97;i:1;i:702;}i:7835;a:1:{i:0;i:7777;}i:7840;a:1:{i:0;i:7841;}i:7842;a:1:{i:0;i:7843;}i:7844;a:1:{i:0;i:7845;}i:7846;a:1:{i:0;i:7847;}i:7848;a:1:{i:0;i:7849;}i:7850;a:1:{i:0;i:7851;}i:7852;a:1:{i:0;i:7853;}i:7854;a:1:{i:0;i:7855;}i:7856;a:1:{i:0;i:7857;}i:7858;a:1:{i:0;i:7859;}i:7860;a:1:{i:0;i:7861;}i:7862;a:1:{i:0;i:7863;}i:7864;a:1:{i:0;i:7865;}i:7866;a:1:{i:0;i:7867;}i:7868;a:1:{i:0;i:7869;}i:7870;a:1:{i:0;i:7871;}i:7872;a:1:{i:0;i:7873;}i:7874;a:1:{i:0;i:7875;}i:7876;a:1:{i:0;i:7877;}i:7878;a:1:{i:0;i:7879;}i:7880;a:1:{i:0;i:7881;}i:7882;a:1:{i:0;i:7883;}i:7884;a:1:{i:0;i:7885;}i:7886;a:1:{i:0;i:7887;}i:7888;a:1:{i:0;i:7889;}i:7890;a:1:{i:0;i:7891;}i:7892;a:1:{i:0;i:7893;}i:7894;a:1:{i:0;i:7895;}i:7896;a:1:{i:0;i:7897;}i:7898;a:1:{i:0;i:7899;}i:7900;a:1:{i:0;i:7901;}i:7902;a:1:{i:0;i:7903;}i:7904;a:1:{i:0;i:7905;}i:7906;a:1:{i:0;i:7907;}i:7908;a:1:{i:0;i:7909;}i:7910;a:1:{i:0;i:7911;}i:7912;a:1:{i:0;i:7913;}i:7914;a:1:{i:0;i:7915;}i:7916;a:1:{i:0;i:7917;}i:7918;a:1:{i:0;i:7919;}i:7920;a:1:{i:0;i:7921;}i:7922;a:1:{i:0;i:7923;}i:7924;a:1:{i:0;i:7925;}i:7926;a:1:{i:0;i:7927;}i:7928;a:1:{i:0;i:7929;}i:7944;a:1:{i:0;i:7936;}i:7945;a:1:{i:0;i:7937;}i:7946;a:1:{i:0;i:7938;}i:7947;a:1:{i:0;i:7939;}i:7948;a:1:{i:0;i:7940;}i:7949;a:1:{i:0;i:7941;}i:7950;a:1:{i:0;i:7942;}i:7951;a:1:{i:0;i:7943;}i:7960;a:1:{i:0;i:7952;}i:7961;a:1:{i:0;i:7953;}i:7962;a:1:{i:0;i:7954;}i:7963;a:1:{i:0;i:7955;}i:7964;a:1:{i:0;i:7956;}i:7965;a:1:{i:0;i:7957;}i:7976;a:1:{i:0;i:7968;}i:7977;a:1:{i:0;i:7969;}i:7978;a:1:{i:0;i:7970;}i:7979;a:1:{i:0;i:7971;}i:7980;a:1:{i:0;i:7972;}i:7981;a:1:{i:0;i:7973;}i:7982;a:1:{i:0;i:7974;}i:7983;a:1:{i:0;i:7975;}i:7992;a:1:{i:0;i:7984;}i:7993;a:1:{i:0;i:7985;}i:7994;a:1:{i:0;i:7986;}i:7995;a:1:{i:0;i:7987;}i:7996;a:1:{i:0;i:7988;}i:7997;a:1:{i:0;i:7989;}i:7998;a:1:{i:0;i:7990;}i:7999;a:1:{i:0;i:7991;}i:8008;a:1:{i:0;i:8000;}i:8009;a:1:{i:0;i:8001;}i:8010;a:1:{i:0;i:8002;}i:8011;a:1:{i:0;i:8003;}i:8012;a:1:{i:0;i:8004;}i:8013;a:1:{i:0;i:8005;}i:8016;a:2:{i:0;i:965;i:1;i:787;}i:8018;a:3:{i:0;i:965;i:1;i:787;i:2;i:768;}i:8020;a:3:{i:0;i:965;i:1;i:787;i:2;i:769;}i:8022;a:3:{i:0;i:965;i:1;i:787;i:2;i:834;}i:8025;a:1:{i:0;i:8017;}i:8027;a:1:{i:0;i:8019;}i:8029;a:1:{i:0;i:8021;}i:8031;a:1:{i:0;i:8023;}i:8040;a:1:{i:0;i:8032;}i:8041;a:1:{i:0;i:8033;}i:8042;a:1:{i:0;i:8034;}i:8043;a:1:{i:0;i:8035;}i:8044;a:1:{i:0;i:8036;}i:8045;a:1:{i:0;i:8037;}i:8046;a:1:{i:0;i:8038;}i:8047;a:1:{i:0;i:8039;}i:8064;a:2:{i:0;i:7936;i:1;i:953;}i:8065;a:2:{i:0;i:7937;i:1;i:953;}i:8066;a:2:{i:0;i:7938;i:1;i:953;}i:8067;a:2:{i:0;i:7939;i:1;i:953;}i:8068;a:2:{i:0;i:7940;i:1;i:953;}i:8069;a:2:{i:0;i:7941;i:1;i:953;}i:8070;a:2:{i:0;i:7942;i:1;i:953;}i:8071;a:2:{i:0;i:7943;i:1;i:953;}i:8072;a:2:{i:0;i:7936;i:1;i:953;}i:8073;a:2:{i:0;i:7937;i:1;i:953;}i:8074;a:2:{i:0;i:7938;i:1;i:953;}i:8075;a:2:{i:0;i:7939;i:1;i:953;}i:8076;a:2:{i:0;i:7940;i:1;i:953;}i:8077;a:2:{i:0;i:7941;i:1;i:953;}i:8078;a:2:{i:0;i:7942;i:1;i:953;}i:8079;a:2:{i:0;i:7943;i:1;i:953;}i:8080;a:2:{i:0;i:7968;i:1;i:953;}i:8081;a:2:{i:0;i:7969;i:1;i:953;}i:8082;a:2:{i:0;i:7970;i:1;i:953;}i:8083;a:2:{i:0;i:7971;i:1;i:953;}i:8084;a:2:{i:0;i:7972;i:1;i:953;}i:8085;a:2:{i:0;i:7973;i:1;i:953;}i:8086;a:2:{i:0;i:7974;i:1;i:953;}i:8087;a:2:{i:0;i:7975;i:1;i:953;}i:8088;a:2:{i:0;i:7968;i:1;i:953;}i:8089;a:2:{i:0;i:7969;i:1;i:953;}i:8090;a:2:{i:0;i:7970;i:1;i:953;}i:8091;a:2:{i:0;i:7971;i:1;i:953;}i:8092;a:2:{i:0;i:7972;i:1;i:953;}i:8093;a:2:{i:0;i:7973;i:1;i:953;}i:8094;a:2:{i:0;i:7974;i:1;i:953;}i:8095;a:2:{i:0;i:7975;i:1;i:953;}i:8096;a:2:{i:0;i:8032;i:1;i:953;}i:8097;a:2:{i:0;i:8033;i:1;i:953;}i:8098;a:2:{i:0;i:8034;i:1;i:953;}i:8099;a:2:{i:0;i:8035;i:1;i:953;}i:8100;a:2:{i:0;i:8036;i:1;i:953;}i:8101;a:2:{i:0;i:8037;i:1;i:953;}i:8102;a:2:{i:0;i:8038;i:1;i:953;}i:8103;a:2:{i:0;i:8039;i:1;i:953;}i:8104;a:2:{i:0;i:8032;i:1;i:953;}i:8105;a:2:{i:0;i:8033;i:1;i:953;}i:8106;a:2:{i:0;i:8034;i:1;i:953;}i:8107;a:2:{i:0;i:8035;i:1;i:953;}i:8108;a:2:{i:0;i:8036;i:1;i:953;}i:8109;a:2:{i:0;i:8037;i:1;i:953;}i:8110;a:2:{i:0;i:8038;i:1;i:953;}i:8111;a:2:{i:0;i:8039;i:1;i:953;}i:8114;a:2:{i:0;i:8048;i:1;i:953;}i:8115;a:2:{i:0;i:945;i:1;i:953;}i:8116;a:2:{i:0;i:940;i:1;i:953;}i:8118;a:2:{i:0;i:945;i:1;i:834;}i:8119;a:3:{i:0;i:945;i:1;i:834;i:2;i:953;}i:8120;a:1:{i:0;i:8112;}i:8121;a:1:{i:0;i:8113;}i:8122;a:1:{i:0;i:8048;}i:8123;a:1:{i:0;i:8049;}i:8124;a:2:{i:0;i:945;i:1;i:953;}i:8126;a:1:{i:0;i:953;}i:8130;a:2:{i:0;i:8052;i:1;i:953;}i:8131;a:2:{i:0;i:951;i:1;i:953;}i:8132;a:2:{i:0;i:942;i:1;i:953;}i:8134;a:2:{i:0;i:951;i:1;i:834;}i:8135;a:3:{i:0;i:951;i:1;i:834;i:2;i:953;}i:8136;a:1:{i:0;i:8050;}i:8137;a:1:{i:0;i:8051;}i:8138;a:1:{i:0;i:8052;}i:8139;a:1:{i:0;i:8053;}i:8140;a:2:{i:0;i:951;i:1;i:953;}i:8146;a:3:{i:0;i:953;i:1;i:776;i:2;i:768;}i:8147;a:3:{i:0;i:953;i:1;i:776;i:2;i:769;}i:8150;a:2:{i:0;i:953;i:1;i:834;}i:8151;a:3:{i:0;i:953;i:1;i:776;i:2;i:834;}i:8152;a:1:{i:0;i:8144;}i:8153;a:1:{i:0;i:8145;}i:8154;a:1:{i:0;i:8054;}i:8155;a:1:{i:0;i:8055;}i:8162;a:3:{i:0;i:965;i:1;i:776;i:2;i:768;}i:8163;a:3:{i:0;i:965;i:1;i:776;i:2;i:769;}i:8164;a:2:{i:0;i:961;i:1;i:787;}i:8166;a:2:{i:0;i:965;i:1;i:834;}i:8167;a:3:{i:0;i:965;i:1;i:776;i:2;i:834;}i:8168;a:1:{i:0;i:8160;}i:8169;a:1:{i:0;i:8161;}i:8170;a:1:{i:0;i:8058;}i:8171;a:1:{i:0;i:8059;}i:8172;a:1:{i:0;i:8165;}i:8178;a:2:{i:0;i:8060;i:1;i:953;}i:8179;a:2:{i:0;i:969;i:1;i:953;}i:8180;a:2:{i:0;i:974;i:1;i:953;}i:8182;a:2:{i:0;i:969;i:1;i:834;}i:8183;a:3:{i:0;i:969;i:1;i:834;i:2;i:953;}i:8184;a:1:{i:0;i:8056;}i:8185;a:1:{i:0;i:8057;}i:8186;a:1:{i:0;i:8060;}i:8187;a:1:{i:0;i:8061;}i:8188;a:2:{i:0;i:969;i:1;i:953;}i:8360;a:2:{i:0;i:114;i:1;i:115;}i:8450;a:1:{i:0;i:99;}i:8451;a:2:{i:0;i:176;i:1;i:99;}i:8455;a:1:{i:0;i:603;}i:8457;a:2:{i:0;i:176;i:1;i:102;}i:8459;a:1:{i:0;i:104;}i:8460;a:1:{i:0;i:104;}i:8461;a:1:{i:0;i:104;}i:8464;a:1:{i:0;i:105;}i:8465;a:1:{i:0;i:105;}i:8466;a:1:{i:0;i:108;}i:8469;a:1:{i:0;i:110;}i:8470;a:2:{i:0;i:110;i:1;i:111;}i:8473;a:1:{i:0;i:112;}i:8474;a:1:{i:0;i:113;}i:8475;a:1:{i:0;i:114;}i:8476;a:1:{i:0;i:114;}i:8477;a:1:{i:0;i:114;}i:8480;a:2:{i:0;i:115;i:1;i:109;}i:8481;a:3:{i:0;i:116;i:1;i:101;i:2;i:108;}i:8482;a:2:{i:0;i:116;i:1;i:109;}i:8484;a:1:{i:0;i:122;}i:8486;a:1:{i:0;i:969;}i:8488;a:1:{i:0;i:122;}i:8490;a:1:{i:0;i:107;}i:8491;a:1:{i:0;i:229;}i:8492;a:1:{i:0;i:98;}i:8493;a:1:{i:0;i:99;}i:8496;a:1:{i:0;i:101;}i:8497;a:1:{i:0;i:102;}i:8499;a:1:{i:0;i:109;}i:8510;a:1:{i:0;i:947;}i:8511;a:1:{i:0;i:960;}i:8517;a:1:{i:0;i:100;}i:8544;a:1:{i:0;i:8560;}i:8545;a:1:{i:0;i:8561;}i:8546;a:1:{i:0;i:8562;}i:8547;a:1:{i:0;i:8563;}i:8548;a:1:{i:0;i:8564;}i:8549;a:1:{i:0;i:8565;}i:8550;a:1:{i:0;i:8566;}i:8551;a:1:{i:0;i:8567;}i:8552;a:1:{i:0;i:8568;}i:8553;a:1:{i:0;i:8569;}i:8554;a:1:{i:0;i:8570;}i:8555;a:1:{i:0;i:8571;}i:8556;a:1:{i:0;i:8572;}i:8557;a:1:{i:0;i:8573;}i:8558;a:1:{i:0;i:8574;}i:8559;a:1:{i:0;i:8575;}i:9398;a:1:{i:0;i:9424;}i:9399;a:1:{i:0;i:9425;}i:9400;a:1:{i:0;i:9426;}i:9401;a:1:{i:0;i:9427;}i:9402;a:1:{i:0;i:9428;}i:9403;a:1:{i:0;i:9429;}i:9404;a:1:{i:0;i:9430;}i:9405;a:1:{i:0;i:9431;}i:9406;a:1:{i:0;i:9432;}i:9407;a:1:{i:0;i:9433;}i:9408;a:1:{i:0;i:9434;}i:9409;a:1:{i:0;i:9435;}i:9410;a:1:{i:0;i:9436;}i:9411;a:1:{i:0;i:9437;}i:9412;a:1:{i:0;i:9438;}i:9413;a:1:{i:0;i:9439;}i:9414;a:1:{i:0;i:9440;}i:9415;a:1:{i:0;i:9441;}i:9416;a:1:{i:0;i:9442;}i:9417;a:1:{i:0;i:9443;}i:9418;a:1:{i:0;i:9444;}i:9419;a:1:{i:0;i:9445;}i:9420;a:1:{i:0;i:9446;}i:9421;a:1:{i:0;i:9447;}i:9422;a:1:{i:0;i:9448;}i:9423;a:1:{i:0;i:9449;}i:13169;a:3:{i:0;i:104;i:1;i:112;i:2;i:97;}i:13171;a:2:{i:0;i:97;i:1;i:117;}i:13173;a:2:{i:0;i:111;i:1;i:118;}i:13184;a:2:{i:0;i:112;i:1;i:97;}i:13185;a:2:{i:0;i:110;i:1;i:97;}i:13186;a:2:{i:0;i:956;i:1;i:97;}i:13187;a:2:{i:0;i:109;i:1;i:97;}i:13188;a:2:{i:0;i:107;i:1;i:97;}i:13189;a:2:{i:0;i:107;i:1;i:98;}i:13190;a:2:{i:0;i:109;i:1;i:98;}i:13191;a:2:{i:0;i:103;i:1;i:98;}i:13194;a:2:{i:0;i:112;i:1;i:102;}i:13195;a:2:{i:0;i:110;i:1;i:102;}i:13196;a:2:{i:0;i:956;i:1;i:102;}i:13200;a:2:{i:0;i:104;i:1;i:122;}i:13201;a:3:{i:0;i:107;i:1;i:104;i:2;i:122;}i:13202;a:3:{i:0;i:109;i:1;i:104;i:2;i:122;}i:13203;a:3:{i:0;i:103;i:1;i:104;i:2;i:122;}i:13204;a:3:{i:0;i:116;i:1;i:104;i:2;i:122;}i:13225;a:2:{i:0;i:112;i:1;i:97;}i:13226;a:3:{i:0;i:107;i:1;i:112;i:2;i:97;}i:13227;a:3:{i:0;i:109;i:1;i:112;i:2;i:97;}i:13228;a:3:{i:0;i:103;i:1;i:112;i:2;i:97;}i:13236;a:2:{i:0;i:112;i:1;i:118;}i:13237;a:2:{i:0;i:110;i:1;i:118;}i:13238;a:2:{i:0;i:956;i:1;i:118;}i:13239;a:2:{i:0;i:109;i:1;i:118;}i:13240;a:2:{i:0;i:107;i:1;i:118;}i:13241;a:2:{i:0;i:109;i:1;i:118;}i:13242;a:2:{i:0;i:112;i:1;i:119;}i:13243;a:2:{i:0;i:110;i:1;i:119;}i:13244;a:2:{i:0;i:956;i:1;i:119;}i:13245;a:2:{i:0;i:109;i:1;i:119;}i:13246;a:2:{i:0;i:107;i:1;i:119;}i:13247;a:2:{i:0;i:109;i:1;i:119;}i:13248;a:2:{i:0;i:107;i:1;i:969;}i:13249;a:2:{i:0;i:109;i:1;i:969;}i:13251;a:2:{i:0;i:98;i:1;i:113;}i:13254;a:4:{i:0;i:99;i:1;i:8725;i:2;i:107;i:3;i:103;}i:13255;a:3:{i:0;i:99;i:1;i:111;i:2;i:46;}i:13256;a:2:{i:0;i:100;i:1;i:98;}i:13257;a:2:{i:0;i:103;i:1;i:121;}i:13259;a:2:{i:0;i:104;i:1;i:112;}i:13261;a:2:{i:0;i:107;i:1;i:107;}i:13262;a:2:{i:0;i:107;i:1;i:109;}i:13271;a:2:{i:0;i:112;i:1;i:104;}i:13273;a:3:{i:0;i:112;i:1;i:112;i:2;i:109;}i:13274;a:2:{i:0;i:112;i:1;i:114;}i:13276;a:2:{i:0;i:115;i:1;i:118;}i:13277;a:2:{i:0;i:119;i:1;i:98;}i:64256;a:2:{i:0;i:102;i:1;i:102;}i:64257;a:2:{i:0;i:102;i:1;i:105;}i:64258;a:2:{i:0;i:102;i:1;i:108;}i:64259;a:3:{i:0;i:102;i:1;i:102;i:2;i:105;}i:64260;a:3:{i:0;i:102;i:1;i:102;i:2;i:108;}i:64261;a:2:{i:0;i:115;i:1;i:116;}i:64262;a:2:{i:0;i:115;i:1;i:116;}i:64275;a:2:{i:0;i:1396;i:1;i:1398;}i:64276;a:2:{i:0;i:1396;i:1;i:1381;}i:64277;a:2:{i:0;i:1396;i:1;i:1387;}i:64278;a:2:{i:0;i:1406;i:1;i:1398;}i:64279;a:2:{i:0;i:1396;i:1;i:1389;}i:65313;a:1:{i:0;i:65345;}i:65314;a:1:{i:0;i:65346;}i:65315;a:1:{i:0;i:65347;}i:65316;a:1:{i:0;i:65348;}i:65317;a:1:{i:0;i:65349;}i:65318;a:1:{i:0;i:65350;}i:65319;a:1:{i:0;i:65351;}i:65320;a:1:{i:0;i:65352;}i:65321;a:1:{i:0;i:65353;}i:65322;a:1:{i:0;i:65354;}i:65323;a:1:{i:0;i:65355;}i:65324;a:1:{i:0;i:65356;}i:65325;a:1:{i:0;i:65357;}i:65326;a:1:{i:0;i:65358;}i:65327;a:1:{i:0;i:65359;}i:65328;a:1:{i:0;i:65360;}i:65329;a:1:{i:0;i:65361;}i:65330;a:1:{i:0;i:65362;}i:65331;a:1:{i:0;i:65363;}i:65332;a:1:{i:0;i:65364;}i:65333;a:1:{i:0;i:65365;}i:65334;a:1:{i:0;i:65366;}i:65335;a:1:{i:0;i:65367;}i:65336;a:1:{i:0;i:65368;}i:65337;a:1:{i:0;i:65369;}i:65338;a:1:{i:0;i:65370;}i:66560;a:1:{i:0;i:66600;}i:66561;a:1:{i:0;i:66601;}i:66562;a:1:{i:0;i:66602;}i:66563;a:1:{i:0;i:66603;}i:66564;a:1:{i:0;i:66604;}i:66565;a:1:{i:0;i:66605;}i:66566;a:1:{i:0;i:66606;}i:66567;a:1:{i:0;i:66607;}i:66568;a:1:{i:0;i:66608;}i:66569;a:1:{i:0;i:66609;}i:66570;a:1:{i:0;i:66610;}i:66571;a:1:{i:0;i:66611;}i:66572;a:1:{i:0;i:66612;}i:66573;a:1:{i:0;i:66613;}i:66574;a:1:{i:0;i:66614;}i:66575;a:1:{i:0;i:66615;}i:66576;a:1:{i:0;i:66616;}i:66577;a:1:{i:0;i:66617;}i:66578;a:1:{i:0;i:66618;}i:66579;a:1:{i:0;i:66619;}i:66580;a:1:{i:0;i:66620;}i:66581;a:1:{i:0;i:66621;}i:66582;a:1:{i:0;i:66622;}i:66583;a:1:{i:0;i:66623;}i:66584;a:1:{i:0;i:66624;}i:66585;a:1:{i:0;i:66625;}i:66586;a:1:{i:0;i:66626;}i:66587;a:1:{i:0;i:66627;}i:66588;a:1:{i:0;i:66628;}i:66589;a:1:{i:0;i:66629;}i:66590;a:1:{i:0;i:66630;}i:66591;a:1:{i:0;i:66631;}i:66592;a:1:{i:0;i:66632;}i:66593;a:1:{i:0;i:66633;}i:66594;a:1:{i:0;i:66634;}i:66595;a:1:{i:0;i:66635;}i:66596;a:1:{i:0;i:66636;}i:66597;a:1:{i:0;i:66637;}i:119808;a:1:{i:0;i:97;}i:119809;a:1:{i:0;i:98;}i:119810;a:1:{i:0;i:99;}i:119811;a:1:{i:0;i:100;}i:119812;a:1:{i:0;i:101;}i:119813;a:1:{i:0;i:102;}i:119814;a:1:{i:0;i:103;}i:119815;a:1:{i:0;i:104;}i:119816;a:1:{i:0;i:105;}i:119817;a:1:{i:0;i:106;}i:119818;a:1:{i:0;i:107;}i:119819;a:1:{i:0;i:108;}i:119820;a:1:{i:0;i:109;}i:119821;a:1:{i:0;i:110;}i:119822;a:1:{i:0;i:111;}i:119823;a:1:{i:0;i:112;}i:119824;a:1:{i:0;i:113;}i:119825;a:1:{i:0;i:114;}i:119826;a:1:{i:0;i:115;}i:119827;a:1:{i:0;i:116;}i:119828;a:1:{i:0;i:117;}i:119829;a:1:{i:0;i:118;}i:119830;a:1:{i:0;i:119;}i:119831;a:1:{i:0;i:120;}i:119832;a:1:{i:0;i:121;}i:119833;a:1:{i:0;i:122;}i:119860;a:1:{i:0;i:97;}i:119861;a:1:{i:0;i:98;}i:119862;a:1:{i:0;i:99;}i:119863;a:1:{i:0;i:100;}i:119864;a:1:{i:0;i:101;}i:119865;a:1:{i:0;i:102;}i:119866;a:1:{i:0;i:103;}i:119867;a:1:{i:0;i:104;}i:119868;a:1:{i:0;i:105;}i:119869;a:1:{i:0;i:106;}i:119870;a:1:{i:0;i:107;}i:119871;a:1:{i:0;i:108;}i:119872;a:1:{i:0;i:109;}i:119873;a:1:{i:0;i:110;}i:119874;a:1:{i:0;i:111;}i:119875;a:1:{i:0;i:112;}i:119876;a:1:{i:0;i:113;}i:119877;a:1:{i:0;i:114;}i:119878;a:1:{i:0;i:115;}i:119879;a:1:{i:0;i:116;}i:119880;a:1:{i:0;i:117;}i:119881;a:1:{i:0;i:118;}i:119882;a:1:{i:0;i:119;}i:119883;a:1:{i:0;i:120;}i:119884;a:1:{i:0;i:121;}i:119885;a:1:{i:0;i:122;}i:119912;a:1:{i:0;i:97;}i:119913;a:1:{i:0;i:98;}i:119914;a:1:{i:0;i:99;}i:119915;a:1:{i:0;i:100;}i:119916;a:1:{i:0;i:101;}i:119917;a:1:{i:0;i:102;}i:119918;a:1:{i:0;i:103;}i:119919;a:1:{i:0;i:104;}i:119920;a:1:{i:0;i:105;}i:119921;a:1:{i:0;i:106;}i:119922;a:1:{i:0;i:107;}i:119923;a:1:{i:0;i:108;}i:119924;a:1:{i:0;i:109;}i:119925;a:1:{i:0;i:110;}i:119926;a:1:{i:0;i:111;}i:119927;a:1:{i:0;i:112;}i:119928;a:1:{i:0;i:113;}i:119929;a:1:{i:0;i:114;}i:119930;a:1:{i:0;i:115;}i:119931;a:1:{i:0;i:116;}i:119932;a:1:{i:0;i:117;}i:119933;a:1:{i:0;i:118;}i:119934;a:1:{i:0;i:119;}i:119935;a:1:{i:0;i:120;}i:119936;a:1:{i:0;i:121;}i:119937;a:1:{i:0;i:122;}i:119964;a:1:{i:0;i:97;}i:119966;a:1:{i:0;i:99;}i:119967;a:1:{i:0;i:100;}i:119970;a:1:{i:0;i:103;}i:119973;a:1:{i:0;i:106;}i:119974;a:1:{i:0;i:107;}i:119977;a:1:{i:0;i:110;}i:119978;a:1:{i:0;i:111;}i:119979;a:1:{i:0;i:112;}i:119980;a:1:{i:0;i:113;}i:119982;a:1:{i:0;i:115;}i:119983;a:1:{i:0;i:116;}i:119984;a:1:{i:0;i:117;}i:119985;a:1:{i:0;i:118;}i:119986;a:1:{i:0;i:119;}i:119987;a:1:{i:0;i:120;}i:119988;a:1:{i:0;i:121;}i:119989;a:1:{i:0;i:122;}i:120016;a:1:{i:0;i:97;}i:120017;a:1:{i:0;i:98;}i:120018;a:1:{i:0;i:99;}i:120019;a:1:{i:0;i:100;}i:120020;a:1:{i:0;i:101;}i:120021;a:1:{i:0;i:102;}i:120022;a:1:{i:0;i:103;}i:120023;a:1:{i:0;i:104;}i:120024;a:1:{i:0;i:105;}i:120025;a:1:{i:0;i:106;}i:120026;a:1:{i:0;i:107;}i:120027;a:1:{i:0;i:108;}i:120028;a:1:{i:0;i:109;}i:120029;a:1:{i:0;i:110;}i:120030;a:1:{i:0;i:111;}i:120031;a:1:{i:0;i:112;}i:120032;a:1:{i:0;i:113;}i:120033;a:1:{i:0;i:114;}i:120034;a:1:{i:0;i:115;}i:120035;a:1:{i:0;i:116;}i:120036;a:1:{i:0;i:117;}i:120037;a:1:{i:0;i:118;}i:120038;a:1:{i:0;i:119;}i:120039;a:1:{i:0;i:120;}i:120040;a:1:{i:0;i:121;}i:120041;a:1:{i:0;i:122;}i:120068;a:1:{i:0;i:97;}i:120069;a:1:{i:0;i:98;}i:120071;a:1:{i:0;i:100;}i:120072;a:1:{i:0;i:101;}i:120073;a:1:{i:0;i:102;}i:120074;a:1:{i:0;i:103;}i:120077;a:1:{i:0;i:106;}i:120078;a:1:{i:0;i:107;}i:120079;a:1:{i:0;i:108;}i:120080;a:1:{i:0;i:109;}i:120081;a:1:{i:0;i:110;}i:120082;a:1:{i:0;i:111;}i:120083;a:1:{i:0;i:112;}i:120084;a:1:{i:0;i:113;}i:120086;a:1:{i:0;i:115;}i:120087;a:1:{i:0;i:116;}i:120088;a:1:{i:0;i:117;}i:120089;a:1:{i:0;i:118;}i:120090;a:1:{i:0;i:119;}i:120091;a:1:{i:0;i:120;}i:120092;a:1:{i:0;i:121;}i:120120;a:1:{i:0;i:97;}i:120121;a:1:{i:0;i:98;}i:120123;a:1:{i:0;i:100;}i:120124;a:1:{i:0;i:101;}i:120125;a:1:{i:0;i:102;}i:120126;a:1:{i:0;i:103;}i:120128;a:1:{i:0;i:105;}i:120129;a:1:{i:0;i:106;}i:120130;a:1:{i:0;i:107;}i:120131;a:1:{i:0;i:108;}i:120132;a:1:{i:0;i:109;}i:120134;a:1:{i:0;i:111;}i:120138;a:1:{i:0;i:115;}i:120139;a:1:{i:0;i:116;}i:120140;a:1:{i:0;i:117;}i:120141;a:1:{i:0;i:118;}i:120142;a:1:{i:0;i:119;}i:120143;a:1:{i:0;i:120;}i:120144;a:1:{i:0;i:121;}i:120172;a:1:{i:0;i:97;}i:120173;a:1:{i:0;i:98;}i:120174;a:1:{i:0;i:99;}i:120175;a:1:{i:0;i:100;}i:120176;a:1:{i:0;i:101;}i:120177;a:1:{i:0;i:102;}i:120178;a:1:{i:0;i:103;}i:120179;a:1:{i:0;i:104;}i:120180;a:1:{i:0;i:105;}i:120181;a:1:{i:0;i:106;}i:120182;a:1:{i:0;i:107;}i:120183;a:1:{i:0;i:108;}i:120184;a:1:{i:0;i:109;}i:120185;a:1:{i:0;i:110;}i:120186;a:1:{i:0;i:111;}i:120187;a:1:{i:0;i:112;}i:120188;a:1:{i:0;i:113;}i:120189;a:1:{i:0;i:114;}i:120190;a:1:{i:0;i:115;}i:120191;a:1:{i:0;i:116;}i:120192;a:1:{i:0;i:117;}i:120193;a:1:{i:0;i:118;}i:120194;a:1:{i:0;i:119;}i:120195;a:1:{i:0;i:120;}i:120196;a:1:{i:0;i:121;}i:120197;a:1:{i:0;i:122;}i:120224;a:1:{i:0;i:97;}i:120225;a:1:{i:0;i:98;}i:120226;a:1:{i:0;i:99;}i:120227;a:1:{i:0;i:100;}i:120228;a:1:{i:0;i:101;}i:120229;a:1:{i:0;i:102;}i:120230;a:1:{i:0;i:103;}i:120231;a:1:{i:0;i:104;}i:120232;a:1:{i:0;i:105;}i:120233;a:1:{i:0;i:106;}i:120234;a:1:{i:0;i:107;}i:120235;a:1:{i:0;i:108;}i:120236;a:1:{i:0;i:109;}i:120237;a:1:{i:0;i:110;}i:120238;a:1:{i:0;i:111;}i:120239;a:1:{i:0;i:112;}i:120240;a:1:{i:0;i:113;}i:120241;a:1:{i:0;i:114;}i:120242;a:1:{i:0;i:115;}i:120243;a:1:{i:0;i:116;}i:120244;a:1:{i:0;i:117;}i:120245;a:1:{i:0;i:118;}i:120246;a:1:{i:0;i:119;}i:120247;a:1:{i:0;i:120;}i:120248;a:1:{i:0;i:121;}i:120249;a:1:{i:0;i:122;}i:120276;a:1:{i:0;i:97;}i:120277;a:1:{i:0;i:98;}i:120278;a:1:{i:0;i:99;}i:120279;a:1:{i:0;i:100;}i:120280;a:1:{i:0;i:101;}i:120281;a:1:{i:0;i:102;}i:120282;a:1:{i:0;i:103;}i:120283;a:1:{i:0;i:104;}i:120284;a:1:{i:0;i:105;}i:120285;a:1:{i:0;i:106;}i:120286;a:1:{i:0;i:107;}i:120287;a:1:{i:0;i:108;}i:120288;a:1:{i:0;i:109;}i:120289;a:1:{i:0;i:110;}i:120290;a:1:{i:0;i:111;}i:120291;a:1:{i:0;i:112;}i:120292;a:1:{i:0;i:113;}i:120293;a:1:{i:0;i:114;}i:120294;a:1:{i:0;i:115;}i:120295;a:1:{i:0;i:116;}i:120296;a:1:{i:0;i:117;}i:120297;a:1:{i:0;i:118;}i:120298;a:1:{i:0;i:119;}i:120299;a:1:{i:0;i:120;}i:120300;a:1:{i:0;i:121;}i:120301;a:1:{i:0;i:122;}i:120328;a:1:{i:0;i:97;}i:120329;a:1:{i:0;i:98;}i:120330;a:1:{i:0;i:99;}i:120331;a:1:{i:0;i:100;}i:120332;a:1:{i:0;i:101;}i:120333;a:1:{i:0;i:102;}i:120334;a:1:{i:0;i:103;}i:120335;a:1:{i:0;i:104;}i:120336;a:1:{i:0;i:105;}i:120337;a:1:{i:0;i:106;}i:120338;a:1:{i:0;i:107;}i:120339;a:1:{i:0;i:108;}i:120340;a:1:{i:0;i:109;}i:120341;a:1:{i:0;i:110;}i:120342;a:1:{i:0;i:111;}i:120343;a:1:{i:0;i:112;}i:120344;a:1:{i:0;i:113;}i:120345;a:1:{i:0;i:114;}i:120346;a:1:{i:0;i:115;}i:120347;a:1:{i:0;i:116;}i:120348;a:1:{i:0;i:117;}i:120349;a:1:{i:0;i:118;}i:120350;a:1:{i:0;i:119;}i:120351;a:1:{i:0;i:120;}i:120352;a:1:{i:0;i:121;}i:120353;a:1:{i:0;i:122;}i:120380;a:1:{i:0;i:97;}i:120381;a:1:{i:0;i:98;}i:120382;a:1:{i:0;i:99;}i:120383;a:1:{i:0;i:100;}i:120384;a:1:{i:0;i:101;}i:120385;a:1:{i:0;i:102;}i:120386;a:1:{i:0;i:103;}i:120387;a:1:{i:0;i:104;}i:120388;a:1:{i:0;i:105;}i:120389;a:1:{i:0;i:106;}i:120390;a:1:{i:0;i:107;}i:120391;a:1:{i:0;i:108;}i:120392;a:1:{i:0;i:109;}i:120393;a:1:{i:0;i:110;}i:120394;a:1:{i:0;i:111;}i:120395;a:1:{i:0;i:112;}i:120396;a:1:{i:0;i:113;}i:120397;a:1:{i:0;i:114;}i:120398;a:1:{i:0;i:115;}i:120399;a:1:{i:0;i:116;}i:120400;a:1:{i:0;i:117;}i:120401;a:1:{i:0;i:118;}i:120402;a:1:{i:0;i:119;}i:120403;a:1:{i:0;i:120;}i:120404;a:1:{i:0;i:121;}i:120405;a:1:{i:0;i:122;}i:120432;a:1:{i:0;i:97;}i:120433;a:1:{i:0;i:98;}i:120434;a:1:{i:0;i:99;}i:120435;a:1:{i:0;i:100;}i:120436;a:1:{i:0;i:101;}i:120437;a:1:{i:0;i:102;}i:120438;a:1:{i:0;i:103;}i:120439;a:1:{i:0;i:104;}i:120440;a:1:{i:0;i:105;}i:120441;a:1:{i:0;i:106;}i:120442;a:1:{i:0;i:107;}i:120443;a:1:{i:0;i:108;}i:120444;a:1:{i:0;i:109;}i:120445;a:1:{i:0;i:110;}i:120446;a:1:{i:0;i:111;}i:120447;a:1:{i:0;i:112;}i:120448;a:1:{i:0;i:113;}i:120449;a:1:{i:0;i:114;}i:120450;a:1:{i:0;i:115;}i:120451;a:1:{i:0;i:116;}i:120452;a:1:{i:0;i:117;}i:120453;a:1:{i:0;i:118;}i:120454;a:1:{i:0;i:119;}i:120455;a:1:{i:0;i:120;}i:120456;a:1:{i:0;i:121;}i:120457;a:1:{i:0;i:122;}i:120488;a:1:{i:0;i:945;}i:120489;a:1:{i:0;i:946;}i:120490;a:1:{i:0;i:947;}i:120491;a:1:{i:0;i:948;}i:120492;a:1:{i:0;i:949;}i:120493;a:1:{i:0;i:950;}i:120494;a:1:{i:0;i:951;}i:120495;a:1:{i:0;i:952;}i:120496;a:1:{i:0;i:953;}i:120497;a:1:{i:0;i:954;}i:120498;a:1:{i:0;i:955;}i:120499;a:1:{i:0;i:956;}i:120500;a:1:{i:0;i:957;}i:120501;a:1:{i:0;i:958;}i:120502;a:1:{i:0;i:959;}i:120503;a:1:{i:0;i:960;}i:120504;a:1:{i:0;i:961;}i:120505;a:1:{i:0;i:952;}i:120506;a:1:{i:0;i:963;}i:120507;a:1:{i:0;i:964;}i:120508;a:1:{i:0;i:965;}i:120509;a:1:{i:0;i:966;}i:120510;a:1:{i:0;i:967;}i:120511;a:1:{i:0;i:968;}i:120512;a:1:{i:0;i:969;}i:120531;a:1:{i:0;i:963;}i:120546;a:1:{i:0;i:945;}i:120547;a:1:{i:0;i:946;}i:120548;a:1:{i:0;i:947;}i:120549;a:1:{i:0;i:948;}i:120550;a:1:{i:0;i:949;}i:120551;a:1:{i:0;i:950;}i:120552;a:1:{i:0;i:951;}i:120553;a:1:{i:0;i:952;}i:120554;a:1:{i:0;i:953;}i:120555;a:1:{i:0;i:954;}i:120556;a:1:{i:0;i:955;}i:120557;a:1:{i:0;i:956;}i:120558;a:1:{i:0;i:957;}i:120559;a:1:{i:0;i:958;}i:120560;a:1:{i:0;i:959;}i:120561;a:1:{i:0;i:960;}i:120562;a:1:{i:0;i:961;}i:120563;a:1:{i:0;i:952;}i:120564;a:1:{i:0;i:963;}i:120565;a:1:{i:0;i:964;}i:120566;a:1:{i:0;i:965;}i:120567;a:1:{i:0;i:966;}i:120568;a:1:{i:0;i:967;}i:120569;a:1:{i:0;i:968;}i:120570;a:1:{i:0;i:969;}i:120589;a:1:{i:0;i:963;}i:120604;a:1:{i:0;i:945;}i:120605;a:1:{i:0;i:946;}i:120606;a:1:{i:0;i:947;}i:120607;a:1:{i:0;i:948;}i:120608;a:1:{i:0;i:949;}i:120609;a:1:{i:0;i:950;}i:120610;a:1:{i:0;i:951;}i:120611;a:1:{i:0;i:952;}i:120612;a:1:{i:0;i:953;}i:120613;a:1:{i:0;i:954;}i:120614;a:1:{i:0;i:955;}i:120615;a:1:{i:0;i:956;}i:120616;a:1:{i:0;i:957;}i:120617;a:1:{i:0;i:958;}i:120618;a:1:{i:0;i:959;}i:120619;a:1:{i:0;i:960;}i:120620;a:1:{i:0;i:961;}i:120621;a:1:{i:0;i:952;}i:120622;a:1:{i:0;i:963;}i:120623;a:1:{i:0;i:964;}i:120624;a:1:{i:0;i:965;}i:120625;a:1:{i:0;i:966;}i:120626;a:1:{i:0;i:967;}i:120627;a:1:{i:0;i:968;}i:120628;a:1:{i:0;i:969;}i:120647;a:1:{i:0;i:963;}i:120662;a:1:{i:0;i:945;}i:120663;a:1:{i:0;i:946;}i:120664;a:1:{i:0;i:947;}i:120665;a:1:{i:0;i:948;}i:120666;a:1:{i:0;i:949;}i:120667;a:1:{i:0;i:950;}i:120668;a:1:{i:0;i:951;}i:120669;a:1:{i:0;i:952;}i:120670;a:1:{i:0;i:953;}i:120671;a:1:{i:0;i:954;}i:120672;a:1:{i:0;i:955;}i:120673;a:1:{i:0;i:956;}i:120674;a:1:{i:0;i:957;}i:120675;a:1:{i:0;i:958;}i:120676;a:1:{i:0;i:959;}i:120677;a:1:{i:0;i:960;}i:120678;a:1:{i:0;i:961;}i:120679;a:1:{i:0;i:952;}i:120680;a:1:{i:0;i:963;}i:120681;a:1:{i:0;i:964;}i:120682;a:1:{i:0;i:965;}i:120683;a:1:{i:0;i:966;}i:120684;a:1:{i:0;i:967;}i:120685;a:1:{i:0;i:968;}i:120686;a:1:{i:0;i:969;}i:120705;a:1:{i:0;i:963;}i:120720;a:1:{i:0;i:945;}i:120721;a:1:{i:0;i:946;}i:120722;a:1:{i:0;i:947;}i:120723;a:1:{i:0;i:948;}i:120724;a:1:{i:0;i:949;}i:120725;a:1:{i:0;i:950;}i:120726;a:1:{i:0;i:951;}i:120727;a:1:{i:0;i:952;}i:120728;a:1:{i:0;i:953;}i:120729;a:1:{i:0;i:954;}i:120730;a:1:{i:0;i:955;}i:120731;a:1:{i:0;i:956;}i:120732;a:1:{i:0;i:957;}i:120733;a:1:{i:0;i:958;}i:120734;a:1:{i:0;i:959;}i:120735;a:1:{i:0;i:960;}i:120736;a:1:{i:0;i:961;}i:120737;a:1:{i:0;i:952;}i:120738;a:1:{i:0;i:963;}i:120739;a:1:{i:0;i:964;}i:120740;a:1:{i:0;i:965;}i:120741;a:1:{i:0;i:966;}i:120742;a:1:{i:0;i:967;}i:120743;a:1:{i:0;i:968;}i:120744;a:1:{i:0;i:969;}i:120763;a:1:{i:0;i:963;}i:1017;a:1:{i:0;i:963;}i:7468;a:1:{i:0;i:97;}i:7469;a:1:{i:0;i:230;}i:7470;a:1:{i:0;i:98;}i:7472;a:1:{i:0;i:100;}i:7473;a:1:{i:0;i:101;}i:7474;a:1:{i:0;i:477;}i:7475;a:1:{i:0;i:103;}i:7476;a:1:{i:0;i:104;}i:7477;a:1:{i:0;i:105;}i:7478;a:1:{i:0;i:106;}i:7479;a:1:{i:0;i:107;}i:7480;a:1:{i:0;i:108;}i:7481;a:1:{i:0;i:109;}i:7482;a:1:{i:0;i:110;}i:7484;a:1:{i:0;i:111;}i:7485;a:1:{i:0;i:547;}i:7486;a:1:{i:0;i:112;}i:7487;a:1:{i:0;i:114;}i:7488;a:1:{i:0;i:116;}i:7489;a:1:{i:0;i:117;}i:7490;a:1:{i:0;i:119;}i:8507;a:3:{i:0;i:102;i:1;i:97;i:2;i:120;}i:12880;a:3:{i:0;i:112;i:1;i:116;i:2;i:101;}i:13004;a:2:{i:0;i:104;i:1;i:103;}i:13006;a:2:{i:0;i:101;i:1;i:118;}i:13007;a:3:{i:0;i:108;i:1;i:116;i:2;i:100;}i:13178;a:2:{i:0;i:105;i:1;i:117;}i:13278;a:3:{i:0;i:118;i:1;i:8725;i:2;i:109;}i:13279;a:3:{i:0;i:97;i:1;i:8725;i:2;i:109;}}s:12:"norm_combcls";a:341:{i:820;i:1;i:821;i:1;i:822;i:1;i:823;i:1;i:824;i:1;i:2364;i:7;i:2492;i:7;i:2620;i:7;i:2748;i:7;i:2876;i:7;i:3260;i:7;i:4151;i:7;i:12441;i:8;i:12442;i:8;i:2381;i:9;i:2509;i:9;i:2637;i:9;i:2765;i:9;i:2893;i:9;i:3021;i:9;i:3149;i:9;i:3277;i:9;i:3405;i:9;i:3530;i:9;i:3642;i:9;i:3972;i:9;i:4153;i:9;i:5908;i:9;i:5940;i:9;i:6098;i:9;i:1456;i:10;i:1457;i:11;i:1458;i:12;i:1459;i:13;i:1460;i:14;i:1461;i:15;i:1462;i:16;i:1463;i:17;i:1464;i:18;i:1465;i:19;i:1467;i:20;i:1468;i:21;i:1469;i:22;i:1471;i:23;i:1473;i:24;i:1474;i:25;i:64286;i:26;i:1611;i:27;i:1612;i:28;i:1613;i:29;i:1614;i:30;i:1615;i:31;i:1616;i:32;i:1617;i:33;i:1618;i:34;i:1648;i:35;i:1809;i:36;i:3157;i:84;i:3158;i:91;i:3640;i:103;i:3641;i:103;i:3656;i:107;i:3657;i:107;i:3658;i:107;i:3659;i:107;i:3768;i:118;i:3769;i:118;i:3784;i:122;i:3785;i:122;i:3786;i:122;i:3787;i:122;i:3953;i:129;i:3954;i:130;i:3962;i:130;i:3963;i:130;i:3964;i:130;i:3965;i:130;i:3968;i:130;i:3956;i:132;i:801;i:202;i:802;i:202;i:807;i:202;i:808;i:202;i:795;i:216;i:3897;i:216;i:119141;i:216;i:119142;i:216;i:119150;i:216;i:119151;i:216;i:119152;i:216;i:119153;i:216;i:119154;i:216;i:12330;i:218;i:790;i:220;i:791;i:220;i:792;i:220;i:793;i:220;i:796;i:220;i:797;i:220;i:798;i:220;i:799;i:220;i:800;i:220;i:803;i:220;i:804;i:220;i:805;i:220;i:806;i:220;i:809;i:220;i:810;i:220;i:811;i:220;i:812;i:220;i:813;i:220;i:814;i:220;i:815;i:220;i:816;i:220;i:817;i:220;i:818;i:220;i:819;i:220;i:825;i:220;i:826;i:220;i:827;i:220;i:828;i:220;i:839;i:220;i:840;i:220;i:841;i:220;i:845;i:220;i:846;i:220;i:851;i:220;i:852;i:220;i:853;i:220;i:854;i:220;i:1425;i:220;i:1430;i:220;i:1435;i:220;i:1443;i:220;i:1444;i:220;i:1445;i:220;i:1446;i:220;i:1447;i:220;i:1450;i:220;i:1621;i:220;i:1622;i:220;i:1763;i:220;i:1770;i:220;i:1773;i:220;i:1841;i:220;i:1844;i:220;i:1847;i:220;i:1848;i:220;i:1849;i:220;i:1851;i:220;i:1852;i:220;i:1854;i:220;i:1858;i:220;i:1860;i:220;i:1862;i:220;i:1864;i:220;i:2386;i:220;i:3864;i:220;i:3865;i:220;i:3893;i:220;i:3895;i:220;i:4038;i:220;i:6459;i:220;i:8424;i:220;i:119163;i:220;i:119164;i:220;i:119165;i:220;i:119166;i:220;i:119167;i:220;i:119168;i:220;i:119169;i:220;i:119170;i:220;i:119178;i:220;i:119179;i:220;i:1434;i:222;i:1453;i:222;i:6441;i:222;i:12333;i:222;i:12334;i:224;i:12335;i:224;i:119149;i:226;i:1454;i:228;i:6313;i:228;i:12331;i:228;i:768;i:230;i:769;i:230;i:770;i:230;i:771;i:230;i:772;i:230;i:773;i:230;i:774;i:230;i:775;i:230;i:776;i:230;i:777;i:230;i:778;i:230;i:779;i:230;i:780;i:230;i:781;i:230;i:782;i:230;i:783;i:230;i:784;i:230;i:785;i:230;i:786;i:230;i:787;i:230;i:788;i:230;i:829;i:230;i:830;i:230;i:831;i:230;i:832;i:230;i:833;i:230;i:834;i:230;i:835;i:230;i:836;i:230;i:838;i:230;i:842;i:230;i:843;i:230;i:844;i:230;i:848;i:230;i:849;i:230;i:850;i:230;i:855;i:230;i:867;i:230;i:868;i:230;i:869;i:230;i:870;i:230;i:871;i:230;i:872;i:230;i:873;i:230;i:874;i:230;i:875;i:230;i:876;i:230;i:877;i:230;i:878;i:230;i:879;i:230;i:1155;i:230;i:1156;i:230;i:1157;i:230;i:1158;i:230;i:1426;i:230;i:1427;i:230;i:1428;i:230;i:1429;i:230;i:1431;i:230;i:1432;i:230;i:1433;i:230;i:1436;i:230;i:1437;i:230;i:1438;i:230;i:1439;i:230;i:1440;i:230;i:1441;i:230;i:1448;i:230;i:1449;i:230;i:1451;i:230;i:1452;i:230;i:1455;i:230;i:1476;i:230;i:1552;i:230;i:1553;i:230;i:1554;i:230;i:1555;i:230;i:1556;i:230;i:1557;i:230;i:1619;i:230;i:1620;i:230;i:1623;i:230;i:1624;i:230;i:1750;i:230;i:1751;i:230;i:1752;i:230;i:1753;i:230;i:1754;i:230;i:1755;i:230;i:1756;i:230;i:1759;i:230;i:1760;i:230;i:1761;i:230;i:1762;i:230;i:1764;i:230;i:1767;i:230;i:1768;i:230;i:1771;i:230;i:1772;i:230;i:1840;i:230;i:1842;i:230;i:1843;i:230;i:1845;i:230;i:1846;i:230;i:1850;i:230;i:1853;i:230;i:1855;i:230;i:1856;i:230;i:1857;i:230;i:1859;i:230;i:1861;i:230;i:1863;i:230;i:1865;i:230;i:1866;i:230;i:2385;i:230;i:2387;i:230;i:2388;i:230;i:3970;i:230;i:3971;i:230;i:3974;i:230;i:3975;i:230;i:5901;i:230;i:6458;i:230;i:8400;i:230;i:8401;i:230;i:8404;i:230;i:8405;i:230;i:8406;i:230;i:8407;i:230;i:8411;i:230;i:8412;i:230;i:8417;i:230;i:8423;i:230;i:8425;i:230;i:65056;i:230;i:65057;i:230;i:65058;i:230;i:65059;i:230;i:119173;i:230;i:119174;i:230;i:119175;i:230;i:119177;i:230;i:119176;i:230;i:119210;i:230;i:119211;i:230;i:119212;i:230;i:119213;i:230;i:789;i:232;i:794;i:232;i:12332;i:232;i:863;i:233;i:866;i:233;i:861;i:234;i:862;i:234;i:864;i:234;i:865;i:234;i:837;i:240;}}
libs/SimpleCluvPie/library/SimpleCluvPie.php ADDED
@@ -0,0 +1,3274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @version 1.4.1
37
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
38
+ * @author Ryan Parman
39
+ * @author Geoffrey Sneddon
40
+ * @author Ryan McCue
41
+ * @link http://simplecluvpie.org/ SimpleCluvPie
42
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
43
+ */
44
+
45
+ /**
46
+ * SimpleCluvPie Name
47
+ */
48
+ define('SIMPLECLUVPIE_NAME', 'SimpleCluvPie');
49
+
50
+ /**
51
+ * SimpleCluvPie Version
52
+ */
53
+ define('SIMPLECLUVPIE_VERSION', '1.4.1');
54
+
55
+ /**
56
+ * SimpleCluvPie Build
57
+ * @todo Hardcode for release (there's no need to have to call SimpleCluvPie_Misc::get_build() only every load of simplecluvpie.inc)
58
+ */
59
+ define('SIMPLECLUVPIE_BUILD', gmdate('YmdHis', SimpleCluvPie_Misc::get_build()));
60
+
61
+ /**
62
+ * SimpleCluvPie Website URL
63
+ */
64
+ define('SIMPLECLUVPIE_URL', 'http://simplecluvpie.org');
65
+
66
+ /**
67
+ * SimpleCluvPie Useragent
68
+ * @see SimpleCluvPie::set_useragent()
69
+ */
70
+ define('SIMPLECLUVPIE_USERAGENT', SIMPLECLUVPIE_NAME . '/' . SIMPLECLUVPIE_VERSION . ' (Feed Parser; ' . SIMPLECLUVPIE_URL . '; Allow like Gecko) Build/' . SIMPLECLUVPIE_BUILD);
71
+
72
+ /**
73
+ * SimpleCluvPie Linkback
74
+ */
75
+ define('SIMPLECLUVPIE_LINKBACK', '<a href="' . SIMPLECLUVPIE_URL . '" title="' . SIMPLECLUVPIE_NAME . ' ' . SIMPLECLUVPIE_VERSION . '">' . SIMPLECLUVPIE_NAME . '</a>');
76
+
77
+ /**
78
+ * No Autodiscovery
79
+ * @see SimpleCluvPie::set_autodiscovery_level()
80
+ */
81
+ define('SIMPLECLUVPIE_LOCATOR_NONE', 0);
82
+
83
+ /**
84
+ * Feed Link Element Autodiscovery
85
+ * @see SimpleCluvPie::set_autodiscovery_level()
86
+ */
87
+ define('SIMPLECLUVPIE_LOCATOR_AUTODISCOVERY', 1);
88
+
89
+ /**
90
+ * Local Feed Extension Autodiscovery
91
+ * @see SimpleCluvPie::set_autodiscovery_level()
92
+ */
93
+ define('SIMPLECLUVPIE_LOCATOR_LOCAL_EXTENSION', 2);
94
+
95
+ /**
96
+ * Local Feed Body Autodiscovery
97
+ * @see SimpleCluvPie::set_autodiscovery_level()
98
+ */
99
+ define('SIMPLECLUVPIE_LOCATOR_LOCAL_BODY', 4);
100
+
101
+ /**
102
+ * Remote Feed Extension Autodiscovery
103
+ * @see SimpleCluvPie::set_autodiscovery_level()
104
+ */
105
+ define('SIMPLECLUVPIE_LOCATOR_REMOTE_EXTENSION', 8);
106
+
107
+ /**
108
+ * Remote Feed Body Autodiscovery
109
+ * @see SimpleCluvPie::set_autodiscovery_level()
110
+ */
111
+ define('SIMPLECLUVPIE_LOCATOR_REMOTE_BODY', 16);
112
+
113
+ /**
114
+ * All Feed Autodiscovery
115
+ * @see SimpleCluvPie::set_autodiscovery_level()
116
+ */
117
+ define('SIMPLECLUVPIE_LOCATOR_ALL', 31);
118
+
119
+ /**
120
+ * No known feed type
121
+ */
122
+ define('SIMPLECLUVPIE_TYPE_NONE', 0);
123
+
124
+ /**
125
+ * RSS 0.90
126
+ */
127
+ define('SIMPLECLUVPIE_TYPE_RSS_090', 1);
128
+
129
+ /**
130
+ * RSS 0.91 (Netscape)
131
+ */
132
+ define('SIMPLECLUVPIE_TYPE_RSS_091_NETSCAPE', 2);
133
+
134
+ /**
135
+ * RSS 0.91 (Userland)
136
+ */
137
+ define('SIMPLECLUVPIE_TYPE_RSS_091_USERLAND', 4);
138
+
139
+ /**
140
+ * RSS 0.91 (both Netscape and Userland)
141
+ */
142
+ define('SIMPLECLUVPIE_TYPE_RSS_091', 6);
143
+
144
+ /**
145
+ * RSS 0.92
146
+ */
147
+ define('SIMPLECLUVPIE_TYPE_RSS_092', 8);
148
+
149
+ /**
150
+ * RSS 0.93
151
+ */
152
+ define('SIMPLECLUVPIE_TYPE_RSS_093', 16);
153
+
154
+ /**
155
+ * RSS 0.94
156
+ */
157
+ define('SIMPLECLUVPIE_TYPE_RSS_094', 32);
158
+
159
+ /**
160
+ * RSS 1.0
161
+ */
162
+ define('SIMPLECLUVPIE_TYPE_RSS_10', 64);
163
+
164
+ /**
165
+ * RSS 2.0
166
+ */
167
+ define('SIMPLECLUVPIE_TYPE_RSS_20', 128);
168
+
169
+ /**
170
+ * RDF-based RSS
171
+ */
172
+ define('SIMPLECLUVPIE_TYPE_RSS_RDF', 65);
173
+
174
+ /**
175
+ * Non-RDF-based RSS (truly intended as syndication format)
176
+ */
177
+ define('SIMPLECLUVPIE_TYPE_RSS_SYNDICATION', 190);
178
+
179
+ /**
180
+ * All RSS
181
+ */
182
+ define('SIMPLECLUVPIE_TYPE_RSS_ALL', 255);
183
+
184
+ /**
185
+ * Atom 0.3
186
+ */
187
+ define('SIMPLECLUVPIE_TYPE_ATOM_03', 256);
188
+
189
+ /**
190
+ * Atom 1.0
191
+ */
192
+ define('SIMPLECLUVPIE_TYPE_ATOM_10', 512);
193
+
194
+ /**
195
+ * All Atom
196
+ */
197
+ define('SIMPLECLUVPIE_TYPE_ATOM_ALL', 768);
198
+
199
+ /**
200
+ * All feed types
201
+ */
202
+ define('SIMPLECLUVPIE_TYPE_ALL', 1023);
203
+
204
+ /**
205
+ * No construct
206
+ */
207
+ define('SIMPLECLUVPIE_CONSTRUCT_NONE', 0);
208
+
209
+ /**
210
+ * Text construct
211
+ */
212
+ define('SIMPLECLUVPIE_CONSTRUCT_TEXT', 1);
213
+
214
+ /**
215
+ * HTML construct
216
+ */
217
+ define('SIMPLECLUVPIE_CONSTRUCT_HTML', 2);
218
+
219
+ /**
220
+ * XHTML construct
221
+ */
222
+ define('SIMPLECLUVPIE_CONSTRUCT_XHTML', 4);
223
+
224
+ /**
225
+ * base64-encoded construct
226
+ */
227
+ define('SIMPLECLUVPIE_CONSTRUCT_BASE64', 8);
228
+
229
+ /**
230
+ * IRI construct
231
+ */
232
+ define('SIMPLECLUVPIE_CONSTRUCT_IRI', 16);
233
+
234
+ /**
235
+ * A construct that might be HTML
236
+ */
237
+ define('SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML', 32);
238
+
239
+ /**
240
+ * All constructs
241
+ */
242
+ define('SIMPLECLUVPIE_CONSTRUCT_ALL', 63);
243
+
244
+ /**
245
+ * Don't change case
246
+ */
247
+ define('SIMPLECLUVPIE_SAME_CASE', 1);
248
+
249
+ /**
250
+ * Change to lowercase
251
+ */
252
+ define('SIMPLECLUVPIE_LOWERCASE', 2);
253
+
254
+ /**
255
+ * Change to uppercase
256
+ */
257
+ define('SIMPLECLUVPIE_UPPERCASE', 4);
258
+
259
+ /**
260
+ * PCRE for HTML attributes
261
+ */
262
+ define('SIMPLECLUVPIE_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]*');
263
+
264
+ /**
265
+ * PCRE for XML attributes
266
+ */
267
+ define('SIMPLECLUVPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
268
+
269
+ /**
270
+ * XML Namespace
271
+ */
272
+ define('SIMPLECLUVPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
273
+
274
+ /**
275
+ * Atom 1.0 Namespace
276
+ */
277
+ define('SIMPLECLUVPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
278
+
279
+ /**
280
+ * Atom 0.3 Namespace
281
+ */
282
+ define('SIMPLECLUVPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
283
+
284
+ /**
285
+ * RDF Namespace
286
+ */
287
+ define('SIMPLECLUVPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
288
+
289
+ /**
290
+ * RSS 0.90 Namespace
291
+ */
292
+ define('SIMPLECLUVPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
293
+
294
+ /**
295
+ * RSS 1.0 Namespace
296
+ */
297
+ define('SIMPLECLUVPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
298
+
299
+ /**
300
+ * RSS 1.0 Content Module Namespace
301
+ */
302
+ define('SIMPLECLUVPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
303
+
304
+ /**
305
+ * RSS 2.0 Namespace
306
+ * (Stupid, I know, but I'm certain it will confuse people less with support.)
307
+ */
308
+ define('SIMPLECLUVPIE_NAMESPACE_RSS_20', '');
309
+
310
+ /**
311
+ * DC 1.0 Namespace
312
+ */
313
+ define('SIMPLECLUVPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
314
+
315
+ /**
316
+ * DC 1.1 Namespace
317
+ */
318
+ define('SIMPLECLUVPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
319
+
320
+ /**
321
+ * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
322
+ */
323
+ define('SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
324
+
325
+ /**
326
+ * GeoRSS Namespace
327
+ */
328
+ define('SIMPLECLUVPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
329
+
330
+ /**
331
+ * Media RSS Namespace
332
+ */
333
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
334
+
335
+ /**
336
+ * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
337
+ */
338
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
339
+
340
+ /**
341
+ * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
342
+ */
343
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
344
+
345
+ /**
346
+ * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
347
+ */
348
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
349
+
350
+ /**
351
+ * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
352
+ */
353
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
354
+
355
+ /**
356
+ * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
357
+ */
358
+ define('SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
359
+
360
+ /**
361
+ * iTunes RSS Namespace
362
+ */
363
+ define('SIMPLECLUVPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
364
+
365
+ /**
366
+ * XHTML Namespace
367
+ */
368
+ define('SIMPLECLUVPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
369
+
370
+ /**
371
+ * IANA Link Relations Registry
372
+ */
373
+ define('SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
374
+
375
+ /**
376
+ * No file source
377
+ */
378
+ define('SIMPLECLUVPIE_FILE_SOURCE_NONE', 0);
379
+
380
+ /**
381
+ * Remote file source
382
+ */
383
+ define('SIMPLECLUVPIE_FILE_SOURCE_REMOTE', 1);
384
+
385
+ /**
386
+ * Local file source
387
+ */
388
+ define('SIMPLECLUVPIE_FILE_SOURCE_LOCAL', 2);
389
+
390
+ /**
391
+ * fsockopen() file source
392
+ */
393
+ define('SIMPLECLUVPIE_FILE_SOURCE_FSOCKOPEN', 4);
394
+
395
+ /**
396
+ * cURL file source
397
+ */
398
+ define('SIMPLECLUVPIE_FILE_SOURCE_CURL', 8);
399
+
400
+ /**
401
+ * file_get_contents() file source
402
+ */
403
+ define('SIMPLECLUVPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
404
+
405
+
406
+
407
+ /**
408
+ * SimpleCluvPie
409
+ *
410
+ * @package SimpleCluvPie
411
+ * @subpackage API
412
+ */
413
+ class SimpleCluvPie
414
+ {
415
+ /**
416
+ * @var array Raw data
417
+ * @access private
418
+ */
419
+ public $data = array();
420
+
421
+ /**
422
+ * @var mixed Error string
423
+ * @access private
424
+ */
425
+ public $error;
426
+
427
+ /**
428
+ * @var object Instance of SimpleCluvPie_Sanitize (or other class)
429
+ * @see SimpleCluvPie::set_sanitize_class()
430
+ * @access private
431
+ */
432
+ public $sanitize;
433
+
434
+ /**
435
+ * @var string SimpleCluvPie Useragent
436
+ * @see SimpleCluvPie::set_useragent()
437
+ * @access private
438
+ */
439
+ public $useragent = SIMPLECLUVPIE_USERAGENT;
440
+
441
+ /**
442
+ * @var string Feed URL
443
+ * @see SimpleCluvPie::set_feed_url()
444
+ * @access private
445
+ */
446
+ public $feed_url;
447
+
448
+ /**
449
+ * @var string Original feed URL, or new feed URL iff HTTP 301 Moved Permanently
450
+ * @see SimpleCluvPie::subscribe_url()
451
+ * @access private
452
+ */
453
+ public $permanent_url = null;
454
+
455
+ /**
456
+ * @var object Instance of SimpleCluvPie_File to use as a feed
457
+ * @see SimpleCluvPie::set_file()
458
+ * @access private
459
+ */
460
+ public $file;
461
+
462
+ /**
463
+ * @var string Raw feed data
464
+ * @see SimpleCluvPie::set_raw_data()
465
+ * @access private
466
+ */
467
+ public $raw_data;
468
+
469
+ /**
470
+ * @var int Timeout for fetching remote files
471
+ * @see SimpleCluvPie::set_timeout()
472
+ * @access private
473
+ */
474
+ public $timeout = 10;
475
+
476
+ /**
477
+ * @var array Custom curl options
478
+ * @see SimpleCluvPie::set_curl_options()
479
+ * @access private
480
+ */
481
+ public $curl_options = array();
482
+
483
+ /**
484
+ * @var bool Forces fsockopen() to be used for remote files instead
485
+ * of cURL, even if a new enough version is installed
486
+ * @see SimpleCluvPie::force_fsockopen()
487
+ * @access private
488
+ */
489
+ public $force_fsockopen = false;
490
+
491
+ /**
492
+ * @var bool Force the given data/URL to be treated as a feed no matter what
493
+ * it appears like
494
+ * @see SimpleCluvPie::force_feed()
495
+ * @access private
496
+ */
497
+ public $force_feed = false;
498
+
499
+ /**
500
+ * @var bool Enable/Disable Caching
501
+ * @see SimpleCluvPie::enable_cache()
502
+ * @access private
503
+ */
504
+ public $cache = true;
505
+
506
+ /**
507
+ * @var bool Force SimpleCluvPie to fallback to expired cache, if enabled,
508
+ * when feed is unavailable.
509
+ * @see SimpleCluvPie::force_cache_fallback()
510
+ * @access private
511
+ */
512
+ public $force_cache_fallback = false;
513
+
514
+ /**
515
+ * @var int Cache duration (in seconds)
516
+ * @see SimpleCluvPie::set_cache_duration()
517
+ * @access private
518
+ */
519
+ public $cache_duration = 3600;
520
+
521
+ /**
522
+ * @var int Auto-discovery cache duration (in seconds)
523
+ * @see SimpleCluvPie::set_autodiscovery_cache_duration()
524
+ * @access private
525
+ */
526
+ public $autodiscovery_cache_duration = 604800; // 7 Days.
527
+
528
+ /**
529
+ * @var string Cache location (relative to executing script)
530
+ * @see SimpleCluvPie::set_cache_location()
531
+ * @access private
532
+ */
533
+ public $cache_location = './cache';
534
+
535
+ /**
536
+ * @var string Function that creates the cache filename
537
+ * @see SimpleCluvPie::set_cache_name_function()
538
+ * @access private
539
+ */
540
+ public $cache_name_function = 'md5';
541
+
542
+ /**
543
+ * @var bool Reorder feed by date descending
544
+ * @see SimpleCluvPie::enable_order_by_date()
545
+ * @access private
546
+ */
547
+ public $order_by_date = true;
548
+
549
+ /**
550
+ * @var mixed Force input encoding to be set to the follow value
551
+ * (false, or anything type-cast to false, disables this feature)
552
+ * @see SimpleCluvPie::set_input_encoding()
553
+ * @access private
554
+ */
555
+ public $input_encoding = false;
556
+
557
+ /**
558
+ * @var int Feed Autodiscovery Level
559
+ * @see SimpleCluvPie::set_autodiscovery_level()
560
+ * @access private
561
+ */
562
+ public $autodiscovery = SIMPLECLUVPIE_LOCATOR_ALL;
563
+
564
+ /**
565
+ * Class registry object
566
+ *
567
+ * @var SimpleCluvPie_Registry
568
+ */
569
+ public $registry;
570
+
571
+ /**
572
+ * @var int Maximum number of feeds to check with autodiscovery
573
+ * @see SimpleCluvPie::set_max_checked_feeds()
574
+ * @access private
575
+ */
576
+ public $max_checked_feeds = 10;
577
+
578
+ /**
579
+ * @var array All the feeds found during the autodiscovery process
580
+ * @see SimpleCluvPie::get_all_discovered_feeds()
581
+ * @access private
582
+ */
583
+ public $all_discovered_feeds = array();
584
+
585
+ /**
586
+ * @var string Web-accessible path to the handler_image.php file.
587
+ * @see SimpleCluvPie::set_image_handler()
588
+ * @access private
589
+ */
590
+ public $image_handler = '';
591
+
592
+ /**
593
+ * @var array Stores the URLs when multiple feeds are being initialized.
594
+ * @see SimpleCluvPie::set_feed_url()
595
+ * @access private
596
+ */
597
+ public $multifeed_url = array();
598
+
599
+ /**
600
+ * @var array Stores SimpleCluvPie objects when multiple feeds initialized.
601
+ * @access private
602
+ */
603
+ public $multifeed_objects = array();
604
+
605
+ /**
606
+ * @var array Stores the get_object_vars() array for use with multifeeds.
607
+ * @see SimpleCluvPie::set_feed_url()
608
+ * @access private
609
+ */
610
+ public $config_settings = null;
611
+
612
+ /**
613
+ * @var integer Stores the number of items to return per-feed with multifeeds.
614
+ * @see SimpleCluvPie::set_item_limit()
615
+ * @access private
616
+ */
617
+ public $item_limit = 0;
618
+
619
+ /**
620
+ * @var bool Stores if last-modified and/or etag headers were sent with the
621
+ * request when checking a feed.
622
+ */
623
+ public $check_modified = false;
624
+
625
+ /**
626
+ * @var array Stores the default attributes to be stripped by strip_attributes().
627
+ * @see SimpleCluvPie::strip_attributes()
628
+ * @access private
629
+ */
630
+ public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
631
+
632
+ /**
633
+ * @var array Stores the default attributes to add to different tags by add_attributes().
634
+ * @see SimpleCluvPie::add_attributes()
635
+ * @access private
636
+ */
637
+ public $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'));
638
+
639
+ /**
640
+ * @var array Stores the default tags to be stripped by strip_htmltags().
641
+ * @see SimpleCluvPie::strip_htmltags()
642
+ * @access private
643
+ */
644
+ public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
645
+
646
+ /**
647
+ * The SimpleCluvPie class contains feed level data and options
648
+ *
649
+ * To use SimpleCluvPie, create the SimpleCluvPie object with no parameters. You can
650
+ * then set configuration options using the provided methods. After setting
651
+ * them, you must initialise the feed using $feed->init(). At that point the
652
+ * object's methods and properties will be available to you.
653
+ *
654
+ * Previously, it was possible to pass in the feed URL along with cache
655
+ * options directly into the constructor. This has been removed as of 1.3 as
656
+ * it caused a lot of confusion.
657
+ *
658
+ * @since 1.0 Preview Release
659
+ */
660
+ public function __construct()
661
+ {
662
+ if (version_compare(PHP_VERSION, '5.2', '<'))
663
+ {
664
+ trigger_error('PHP 4.x, 5.0 and 5.1 are no longer supported. Please upgrade to PHP 5.2 or newer.');
665
+ die();
666
+ }
667
+
668
+ // Other objects, instances created here so we can set options on them
669
+ $this->sanitize = new SimpleCluvPie_Sanitize();
670
+ $this->registry = new SimpleCluvPie_Registry();
671
+
672
+ if (func_num_args() > 0)
673
+ {
674
+ $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
675
+ trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_duration() directly.', $level);
676
+
677
+ $args = func_get_args();
678
+ switch (count($args)) {
679
+ case 3:
680
+ $this->set_cache_duration($args[2]);
681
+ case 2:
682
+ $this->set_cache_location($args[1]);
683
+ case 1:
684
+ $this->set_feed_url($args[0]);
685
+ $this->init();
686
+ }
687
+ }
688
+ }
689
+
690
+ /**
691
+ * Used for converting object to a string
692
+ */
693
+ public function __toString()
694
+ {
695
+ return md5(serialize($this->data));
696
+ }
697
+
698
+ /**
699
+ * Remove items that link back to this before destroying this object
700
+ */
701
+ public function __destruct()
702
+ {
703
+ if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
704
+ {
705
+ if (!empty($this->data['items']))
706
+ {
707
+ foreach ($this->data['items'] as $item)
708
+ {
709
+ $item->__destruct();
710
+ }
711
+ unset($item, $this->data['items']);
712
+ }
713
+ if (!empty($this->data['ordered_items']))
714
+ {
715
+ foreach ($this->data['ordered_items'] as $item)
716
+ {
717
+ $item->__destruct();
718
+ }
719
+ unset($item, $this->data['ordered_items']);
720
+ }
721
+ }
722
+ }
723
+
724
+ /**
725
+ * Force the given data/URL to be treated as a feed
726
+ *
727
+ * This tells SimpleCluvPie to ignore the content-type provided by the server.
728
+ * Be careful when using this option, as it will also disable autodiscovery.
729
+ *
730
+ * @since 1.1
731
+ * @param bool $enable Force the given data/URL to be treated as a feed
732
+ */
733
+ public function force_feed($enable = false)
734
+ {
735
+ $this->force_feed = (bool) $enable;
736
+ }
737
+
738
+ /**
739
+ * Set the URL of the feed you want to parse
740
+ *
741
+ * This allows you to enter the URL of the feed you want to parse, or the
742
+ * website you want to try to use auto-discovery on. This takes priority
743
+ * over any set raw data.
744
+ *
745
+ * You can set multiple feeds to mash together by passing an array instead
746
+ * of a string for the $url. Remember that with each additional feed comes
747
+ * additional processing and resources.
748
+ *
749
+ * @since 1.0 Preview Release
750
+ * @see set_raw_data()
751
+ * @param string|array $url This is the URL (or array of URLs) that you want to parse.
752
+ */
753
+ public function set_feed_url($url)
754
+ {
755
+ $this->multifeed_url = array();
756
+ if (is_array($url))
757
+ {
758
+ foreach ($url as $value)
759
+ {
760
+ $this->multifeed_url[] = $this->registry->call('Misc', 'fix_protocol', array($value, 1));
761
+ }
762
+ }
763
+ else
764
+ {
765
+ $this->feed_url = $this->registry->call('Misc', 'fix_protocol', array($url, 1));
766
+ $this->permanent_url = $this->feed_url;
767
+ }
768
+ }
769
+
770
+ /**
771
+ * Set an instance of {@see SimpleCluvPie_File} to use as a feed
772
+ *
773
+ * @param SimpleCluvPie_File &$file
774
+ * @return bool True on success, false on failure
775
+ */
776
+ public function set_file(&$file)
777
+ {
778
+ if ($file instanceof SimpleCluvPie_File)
779
+ {
780
+ $this->feed_url = $file->url;
781
+ $this->permanent_url = $this->feed_url;
782
+ $this->file =& $file;
783
+ return true;
784
+ }
785
+ return false;
786
+ }
787
+
788
+ /**
789
+ * Set the raw XML data to parse
790
+ *
791
+ * Allows you to use a string of RSS/Atom data instead of a remote feed.
792
+ *
793
+ * If you have a feed available as a string in PHP, you can tell SimpleCluvPie
794
+ * to parse that data string instead of a remote feed. Any set feed URL
795
+ * takes precedence.
796
+ *
797
+ * @since 1.0 Beta 3
798
+ * @param string $data RSS or Atom data as a string.
799
+ * @see set_feed_url()
800
+ */
801
+ public function set_raw_data($data)
802
+ {
803
+ $this->raw_data = $data;
804
+ }
805
+
806
+ /**
807
+ * Set the the default timeout for fetching remote feeds
808
+ *
809
+ * This allows you to change the maximum time the feed's server to respond
810
+ * and send the feed back.
811
+ *
812
+ * @since 1.0 Beta 3
813
+ * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
814
+ */
815
+ public function set_timeout($timeout = 10)
816
+ {
817
+ $this->timeout = (int) $timeout;
818
+ }
819
+
820
+ /**
821
+ * Set custom curl options
822
+ *
823
+ * This allows you to change default curl options
824
+ *
825
+ * @since 1.0 Beta 3
826
+ * @param array $curl_options Curl options to add to default settings
827
+ */
828
+ public function set_curl_options(array $curl_options = array())
829
+ {
830
+ $this->curl_options = $curl_options;
831
+ }
832
+
833
+ /**
834
+ * Force SimpleCluvPie to use fsockopen() instead of cURL
835
+ *
836
+ * @since 1.0 Beta 3
837
+ * @param bool $enable Force fsockopen() to be used
838
+ */
839
+ public function force_fsockopen($enable = false)
840
+ {
841
+ $this->force_fsockopen = (bool) $enable;
842
+ }
843
+
844
+ /**
845
+ * Enable/disable caching in SimpleCluvPie.
846
+ *
847
+ * This option allows you to disable caching all-together in SimpleCluvPie.
848
+ * However, disabling the cache can lead to longer load times.
849
+ *
850
+ * @since 1.0 Preview Release
851
+ * @param bool $enable Enable caching
852
+ */
853
+ public function enable_cache($enable = true)
854
+ {
855
+ $this->cache = (bool) $enable;
856
+ }
857
+
858
+ /**
859
+ * SimpleCluvPie to continue to fall back to expired cache, if enabled, when
860
+ * feed is unavailable.
861
+ *
862
+ * This tells SimpleCluvPie to ignore any file errors and fall back to cache
863
+ * instead. This only works if caching is enabled and cached content
864
+ * still exists.
865
+
866
+ * @param bool $enable Force use of cache on fail.
867
+ */
868
+ public function force_cache_fallback($enable = false)
869
+ {
870
+ $this->force_cache_fallback= (bool) $enable;
871
+ }
872
+
873
+ /**
874
+ * Set the length of time (in seconds) that the contents of a feed will be
875
+ * cached
876
+ *
877
+ * @param int $seconds The feed content cache duration
878
+ */
879
+ public function set_cache_duration($seconds = 3600)
880
+ {
881
+ $this->cache_duration = (int) $seconds;
882
+ }
883
+
884
+ /**
885
+ * Set the length of time (in seconds) that the autodiscovered feed URL will
886
+ * be cached
887
+ *
888
+ * @param int $seconds The autodiscovered feed URL cache duration.
889
+ */
890
+ public function set_autodiscovery_cache_duration($seconds = 604800)
891
+ {
892
+ $this->autodiscovery_cache_duration = (int) $seconds;
893
+ }
894
+
895
+ /**
896
+ * Set the file system location where the cached files should be stored
897
+ *
898
+ * @param string $location The file system location.
899
+ */
900
+ public function set_cache_location($location = './cache')
901
+ {
902
+ $this->cache_location = (string) $location;
903
+ }
904
+
905
+ /**
906
+ * Set whether feed items should be sorted into reverse chronological order
907
+ *
908
+ * @param bool $enable Sort as reverse chronological order.
909
+ */
910
+ public function enable_order_by_date($enable = true)
911
+ {
912
+ $this->order_by_date = (bool) $enable;
913
+ }
914
+
915
+ /**
916
+ * Set the character encoding used to parse the feed
917
+ *
918
+ * This overrides the encoding reported by the feed, however it will fall
919
+ * back to the normal encoding detection if the override fails
920
+ *
921
+ * @param string $encoding Character encoding
922
+ */
923
+ public function set_input_encoding($encoding = false)
924
+ {
925
+ if ($encoding)
926
+ {
927
+ $this->input_encoding = (string) $encoding;
928
+ }
929
+ else
930
+ {
931
+ $this->input_encoding = false;
932
+ }
933
+ }
934
+
935
+ /**
936
+ * Set how much feed autodiscovery to do
937
+ *
938
+ * @see SIMPLECLUVPIE_LOCATOR_NONE
939
+ * @see SIMPLECLUVPIE_LOCATOR_AUTODISCOVERY
940
+ * @see SIMPLECLUVPIE_LOCATOR_LOCAL_EXTENSION
941
+ * @see SIMPLECLUVPIE_LOCATOR_LOCAL_BODY
942
+ * @see SIMPLECLUVPIE_LOCATOR_REMOTE_EXTENSION
943
+ * @see SIMPLECLUVPIE_LOCATOR_REMOTE_BODY
944
+ * @see SIMPLECLUVPIE_LOCATOR_ALL
945
+ * @param int $level Feed Autodiscovery Level (level can be a combination of the above constants, see bitwise OR operator)
946
+ */
947
+ public function set_autodiscovery_level($level = SIMPLECLUVPIE_LOCATOR_ALL)
948
+ {
949
+ $this->autodiscovery = (int) $level;
950
+ }
951
+
952
+ /**
953
+ * Get the class registry
954
+ *
955
+ * Use this to override SimpleCluvPie's default classes
956
+ * @see SimpleCluvPie_Registry
957
+ * @return SimpleCluvPie_Registry
958
+ */
959
+ public function &get_registry()
960
+ {
961
+ return $this->registry;
962
+ }
963
+
964
+ /**#@+
965
+ * Useful when you are overloading or extending SimpleCluvPie's default classes.
966
+ *
967
+ * @deprecated Use {@see get_registry()} instead
968
+ * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
969
+ * @param string $class Name of custom class
970
+ * @return boolean True on success, false otherwise
971
+ */
972
+ /**
973
+ * Set which class SimpleCluvPie uses for caching
974
+ */
975
+ public function set_cache_class($class = 'SimpleCluvPie_Cache')
976
+ {
977
+ return $this->registry->register('Cache', $class, true);
978
+ }
979
+
980
+ /**
981
+ * Set which class SimpleCluvPie uses for auto-discovery
982
+ */
983
+ public function set_locator_class($class = 'SimpleCluvPie_Locator')
984
+ {
985
+ return $this->registry->register('Locator', $class, true);
986
+ }
987
+
988
+ /**
989
+ * Set which class SimpleCluvPie uses for XML parsing
990
+ */
991
+ public function set_parser_class($class = 'SimpleCluvPie_Parser')
992
+ {
993
+ return $this->registry->register('Parser', $class, true);
994
+ }
995
+
996
+ /**
997
+ * Set which class SimpleCluvPie uses for remote file fetching
998
+ */
999
+ public function set_file_class($class = 'SimpleCluvPie_File')
1000
+ {
1001
+ return $this->registry->register('File', $class, true);
1002
+ }
1003
+
1004
+ /**
1005
+ * Set which class SimpleCluvPie uses for data sanitization
1006
+ */
1007
+ public function set_sanitize_class($class = 'SimpleCluvPie_Sanitize')
1008
+ {
1009
+ return $this->registry->register('Sanitize', $class, true);
1010
+ }
1011
+
1012
+ /**
1013
+ * Set which class SimpleCluvPie uses for handling feed items
1014
+ */
1015
+ public function set_item_class($class = 'SimpleCluvPie_Item')
1016
+ {
1017
+ return $this->registry->register('Item', $class, true);
1018
+ }
1019
+
1020
+ /**
1021
+ * Set which class SimpleCluvPie uses for handling author data
1022
+ */
1023
+ public function set_author_class($class = 'SimpleCluvPie_Author')
1024
+ {
1025
+ return $this->registry->register('Author', $class, true);
1026
+ }
1027
+
1028
+ /**
1029
+ * Set which class SimpleCluvPie uses for handling category data
1030
+ */
1031
+ public function set_category_class($class = 'SimpleCluvPie_Category')
1032
+ {
1033
+ return $this->registry->register('Category', $class, true);
1034
+ }
1035
+
1036
+ /**
1037
+ * Set which class SimpleCluvPie uses for feed enclosures
1038
+ */
1039
+ public function set_enclosure_class($class = 'SimpleCluvPie_Enclosure')
1040
+ {
1041
+ return $this->registry->register('Enclosure', $class, true);
1042
+ }
1043
+
1044
+ /**
1045
+ * Set which class SimpleCluvPie uses for `<media:text>` captions
1046
+ */
1047
+ public function set_caption_class($class = 'SimpleCluvPie_Caption')
1048
+ {
1049
+ return $this->registry->register('Caption', $class, true);
1050
+ }
1051
+
1052
+ /**
1053
+ * Set which class SimpleCluvPie uses for `<media:copyright>`
1054
+ */
1055
+ public function set_copyright_class($class = 'SimpleCluvPie_Copyright')
1056
+ {
1057
+ return $this->registry->register('Copyright', $class, true);
1058
+ }
1059
+
1060
+ /**
1061
+ * Set which class SimpleCluvPie uses for `<media:credit>`
1062
+ */
1063
+ public function set_credit_class($class = 'SimpleCluvPie_Credit')
1064
+ {
1065
+ return $this->registry->register('Credit', $class, true);
1066
+ }
1067
+
1068
+ /**
1069
+ * Set which class SimpleCluvPie uses for `<media:rating>`
1070
+ */
1071
+ public function set_rating_class($class = 'SimpleCluvPie_Rating')
1072
+ {
1073
+ return $this->registry->register('Rating', $class, true);
1074
+ }
1075
+
1076
+ /**
1077
+ * Set which class SimpleCluvPie uses for `<media:restriction>`
1078
+ */
1079
+ public function set_restriction_class($class = 'SimpleCluvPie_Restriction')
1080
+ {
1081
+ return $this->registry->register('Restriction', $class, true);
1082
+ }
1083
+
1084
+ /**
1085
+ * Set which class SimpleCluvPie uses for content-type sniffing
1086
+ */
1087
+ public function set_content_type_sniffer_class($class = 'SimpleCluvPie_Content_Type_Sniffer')
1088
+ {
1089
+ return $this->registry->register('Content_Type_Sniffer', $class, true);
1090
+ }
1091
+
1092
+ /**
1093
+ * Set which class SimpleCluvPie uses item sources
1094
+ */
1095
+ public function set_source_class($class = 'SimpleCluvPie_Source')
1096
+ {
1097
+ return $this->registry->register('Source', $class, true);
1098
+ }
1099
+ /**#@-*/
1100
+
1101
+ /**
1102
+ * Set the user agent string
1103
+ *
1104
+ * @param string $ua New user agent string.
1105
+ */
1106
+ public function set_useragent($ua = SIMPLECLUVPIE_USERAGENT)
1107
+ {
1108
+ $this->useragent = (string) $ua;
1109
+ }
1110
+
1111
+ /**
1112
+ * Set callback function to create cache filename with
1113
+ *
1114
+ * @param mixed $function Callback function
1115
+ */
1116
+ public function set_cache_name_function($function = 'md5')
1117
+ {
1118
+ if (is_callable($function))
1119
+ {
1120
+ $this->cache_name_function = $function;
1121
+ }
1122
+ }
1123
+
1124
+ /**
1125
+ * Set options to make SP as fast as possible
1126
+ *
1127
+ * Forgoes a substantial amount of data sanitization in favor of speed. This
1128
+ * turns SimpleCluvPie into a dumb parser of feeds.
1129
+ *
1130
+ * @param bool $set Whether to set them or not
1131
+ */
1132
+ public function set_stupidly_fast($set = false)
1133
+ {
1134
+ if ($set)
1135
+ {
1136
+ $this->enable_order_by_date(false);
1137
+ $this->remove_div(false);
1138
+ $this->strip_comments(false);
1139
+ $this->strip_htmltags(false);
1140
+ $this->strip_attributes(false);
1141
+ $this->add_attributes(false);
1142
+ $this->set_image_handler(false);
1143
+ }
1144
+ }
1145
+
1146
+ /**
1147
+ * Set maximum number of feeds to check with autodiscovery
1148
+ *
1149
+ * @param int $max Maximum number of feeds to check
1150
+ */
1151
+ public function set_max_checked_feeds($max = 10)
1152
+ {
1153
+ $this->max_checked_feeds = (int) $max;
1154
+ }
1155
+
1156
+ public function remove_div($enable = true)
1157
+ {
1158
+ $this->sanitize->remove_div($enable);
1159
+ }
1160
+
1161
+ public function strip_htmltags($tags = '', $encode = null)
1162
+ {
1163
+ if ($tags === '')
1164
+ {
1165
+ $tags = $this->strip_htmltags;
1166
+ }
1167
+ $this->sanitize->strip_htmltags($tags);
1168
+ if ($encode !== null)
1169
+ {
1170
+ $this->sanitize->encode_instead_of_strip($tags);
1171
+ }
1172
+ }
1173
+
1174
+ public function encode_instead_of_strip($enable = true)
1175
+ {
1176
+ $this->sanitize->encode_instead_of_strip($enable);
1177
+ }
1178
+
1179
+ public function strip_attributes($attribs = '')
1180
+ {
1181
+ if ($attribs === '')
1182
+ {
1183
+ $attribs = $this->strip_attributes;
1184
+ }
1185
+ $this->sanitize->strip_attributes($attribs);
1186
+ }
1187
+
1188
+ public function add_attributes($attribs = '')
1189
+ {
1190
+ if ($attribs === '')
1191
+ {
1192
+ $attribs = $this->add_attributes;
1193
+ }
1194
+ $this->sanitize->add_attributes($attribs);
1195
+ }
1196
+
1197
+ /**
1198
+ * Set the output encoding
1199
+ *
1200
+ * Allows you to override SimpleCluvPie's output to match that of your webpage.
1201
+ * This is useful for times when your webpages are not being served as
1202
+ * UTF-8. This setting will be obeyed by {@see handle_content_type()}, and
1203
+ * is similar to {@see set_input_encoding()}.
1204
+ *
1205
+ * It should be noted, however, that not all character encodings can support
1206
+ * all characters. If your page is being served as ISO-8859-1 and you try
1207
+ * to display a Japanese feed, you'll likely see garbled characters.
1208
+ * Because of this, it is highly recommended to ensure that your webpages
1209
+ * are served as UTF-8.
1210
+ *
1211
+ * The number of supported character encodings depends on whether your web
1212
+ * host supports {@link http://php.net/mbstring mbstring},
1213
+ * {@link http://php.net/iconv iconv}, or both. See
1214
+ * {@link http://simplecluvpie.org/wiki/faq/Supported_Character_Encodings} for
1215
+ * more information.
1216
+ *
1217
+ * @param string $encoding
1218
+ */
1219
+ public function set_output_encoding($encoding = 'UTF-8')
1220
+ {
1221
+ $this->sanitize->set_output_encoding($encoding);
1222
+ }
1223
+
1224
+ public function strip_comments($strip = false)
1225
+ {
1226
+ $this->sanitize->strip_comments($strip);
1227
+ }
1228
+
1229
+ /**
1230
+ * Set element/attribute key/value pairs of HTML attributes
1231
+ * containing URLs that need to be resolved relative to the feed
1232
+ *
1233
+ * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
1234
+ * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
1235
+ * |q|@cite
1236
+ *
1237
+ * @since 1.0
1238
+ * @param array|null $element_attribute Element/attribute key/value pairs, null for default
1239
+ */
1240
+ public function set_url_replacements($element_attribute = null)
1241
+ {
1242
+ $this->sanitize->set_url_replacements($element_attribute);
1243
+ }
1244
+
1245
+ /**
1246
+ * Set the handler to enable the display of cached images.
1247
+ *
1248
+ * @param str $page Web-accessible path to the handler_image.php file.
1249
+ * @param str $qs The query string that the value should be passed to.
1250
+ */
1251
+ public function set_image_handler($page = false, $qs = 'i')
1252
+ {
1253
+ if ($page !== false)
1254
+ {
1255
+ $this->sanitize->set_image_handler($page . '?' . $qs . '=');
1256
+ }
1257
+ else
1258
+ {
1259
+ $this->image_handler = '';
1260
+ }
1261
+ }
1262
+
1263
+ /**
1264
+ * Set the limit for items returned per-feed with multifeeds
1265
+ *
1266
+ * @param integer $limit The maximum number of items to return.
1267
+ */
1268
+ public function set_item_limit($limit = 0)
1269
+ {
1270
+ $this->item_limit = (int) $limit;
1271
+ }
1272
+
1273
+ /**
1274
+ * Enable throwing exceptions
1275
+ *
1276
+ * @param boolean $enable Should we throw exceptions, or use the old-style error property?
1277
+ */
1278
+ public function enable_exceptions($enable = true)
1279
+ {
1280
+ $this->enable_exceptions = $enable;
1281
+ }
1282
+
1283
+ /**
1284
+ * Initialize the feed object
1285
+ *
1286
+ * This is what makes everything happen. Period. This is where all of the
1287
+ * configuration options get processed, feeds are fetched, cached, and
1288
+ * parsed, and all of that other good stuff.
1289
+ *
1290
+ * @return boolean True if successful, false otherwise
1291
+ */
1292
+ public function init()
1293
+ {
1294
+ // Check absolute bare minimum requirements.
1295
+ if (!extension_loaded('xml') || !extension_loaded('pcre'))
1296
+ {
1297
+ return false;
1298
+ }
1299
+ // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
1300
+ elseif (!extension_loaded('xmlreader'))
1301
+ {
1302
+ static $xml_is_sane = null;
1303
+ if ($xml_is_sane === null)
1304
+ {
1305
+ $parser_check = xml_parser_create();
1306
+ xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
1307
+ xml_parser_free($parser_check);
1308
+ $xml_is_sane = isset($values[0]['value']);
1309
+ }
1310
+ if (!$xml_is_sane)
1311
+ {
1312
+ return false;
1313
+ }
1314
+ }
1315
+
1316
+ if (method_exists($this->sanitize, 'set_registry'))
1317
+ {
1318
+ $this->sanitize->set_registry($this->registry);
1319
+ }
1320
+
1321
+ // Pass whatever was set with config options over to the sanitizer.
1322
+ // Pass the classes in for legacy support; new classes should use the registry instead
1323
+ $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->registry->get_class('Cache'));
1324
+ $this->sanitize->pass_file_data($this->registry->get_class('File'), $this->timeout, $this->useragent, $this->force_fsockopen, $this->curl_options);
1325
+
1326
+ if (!empty($this->multifeed_url))
1327
+ {
1328
+ $i = 0;
1329
+ $success = 0;
1330
+ $this->multifeed_objects = array();
1331
+ $this->error = array();
1332
+ foreach ($this->multifeed_url as $url)
1333
+ {
1334
+ $this->multifeed_objects[$i] = clone $this;
1335
+ $this->multifeed_objects[$i]->set_feed_url($url);
1336
+ $single_success = $this->multifeed_objects[$i]->init();
1337
+ $success |= $single_success;
1338
+ if (!$single_success)
1339
+ {
1340
+ $this->error[$i] = $this->multifeed_objects[$i]->error();
1341
+ }
1342
+ $i++;
1343
+ }
1344
+ return (bool) $success;
1345
+ }
1346
+ elseif ($this->feed_url === null && $this->raw_data === null)
1347
+ {
1348
+ return false;
1349
+ }
1350
+
1351
+ $this->error = null;
1352
+ $this->data = array();
1353
+ $this->check_modified = false;
1354
+ $this->multifeed_objects = array();
1355
+ $cache = false;
1356
+
1357
+ if ($this->feed_url !== null)
1358
+ {
1359
+ $parsed_feed_url = $this->registry->call('Misc', 'parse_url', array($this->feed_url));
1360
+
1361
+ // Decide whether to enable caching
1362
+ if ($this->cache && $parsed_feed_url['scheme'] !== '')
1363
+ {
1364
+ $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc'));
1365
+ }
1366
+
1367
+ // Fetch the data via SimpleCluvPie_File into $this->raw_data
1368
+ if (($fetched = $this->fetch_data($cache)) === true)
1369
+ {
1370
+ return true;
1371
+ }
1372
+ elseif ($fetched === false) {
1373
+ return false;
1374
+ }
1375
+
1376
+ list($headers, $sniffed) = $fetched;
1377
+ }
1378
+
1379
+ // Set up array of possible encodings
1380
+ $encodings = array();
1381
+
1382
+ // First check to see if input has been overridden.
1383
+ if ($this->input_encoding !== false)
1384
+ {
1385
+ $encodings[] = strtoupper($this->input_encoding);
1386
+ }
1387
+
1388
+ $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
1389
+ $text_types = array('text/xml', 'text/xml-external-parsed-entity');
1390
+
1391
+ // RFC 3023 (only applies to sniffed content)
1392
+ if (isset($sniffed))
1393
+ {
1394
+ if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
1395
+ {
1396
+ if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1397
+ {
1398
+ $encodings[] = strtoupper($charset[1]);
1399
+ }
1400
+ $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1401
+ $encodings[] = 'UTF-8';
1402
+ }
1403
+ elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
1404
+ {
1405
+ if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
1406
+ {
1407
+ $encodings[] = strtoupper($charset[1]);
1408
+ }
1409
+ $encodings[] = 'US-ASCII';
1410
+ }
1411
+ // Text MIME-type default
1412
+ elseif (substr($sniffed, 0, 5) === 'text/')
1413
+ {
1414
+ $encodings[] = 'UTF-8';
1415
+ }
1416
+ }
1417
+
1418
+ // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
1419
+ $encodings = array_merge($encodings, $this->registry->call('Misc', 'xml_encoding', array($this->raw_data, &$this->registry)));
1420
+ $encodings[] = 'UTF-8';
1421
+ $encodings[] = 'ISO-8859-1';
1422
+
1423
+ // There's no point in trying an encoding twice
1424
+ $encodings = array_unique($encodings);
1425
+
1426
+ // Loop through each possible encoding, till we return something, or run out of possibilities
1427
+ foreach ($encodings as $encoding)
1428
+ {
1429
+ // Change the encoding to UTF-8 (as we always use UTF-8 internally)
1430
+ if ($utf8_data = $this->registry->call('Misc', 'change_encoding', array($this->raw_data, $encoding, 'UTF-8')))
1431
+ {
1432
+ // Create new parser
1433
+ $parser = $this->registry->create('Parser');
1434
+
1435
+ // If it's parsed fine
1436
+ if ($parser->parse($utf8_data, 'UTF-8', $this->permanent_url))
1437
+ {
1438
+ $this->data = $parser->get_data();
1439
+ if (!($this->get_type() & ~SIMPLECLUVPIE_TYPE_NONE))
1440
+ {
1441
+ $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
1442
+ $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1443
+ return false;
1444
+ }
1445
+
1446
+ if (isset($headers))
1447
+ {
1448
+ $this->data['headers'] = $headers;
1449
+ }
1450
+ $this->data['build'] = SIMPLECLUVPIE_BUILD;
1451
+
1452
+ // Cache the file if caching is enabled
1453
+ if ($cache && !$cache->save($this))
1454
+ {
1455
+ trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1456
+ }
1457
+ return true;
1458
+ }
1459
+ }
1460
+ }
1461
+
1462
+ if (isset($parser))
1463
+ {
1464
+ // We have an error, just set SimpleCluvPie_Misc::error to it and quit
1465
+ $this->error = $this->feed_url;
1466
+ $this->error .= sprintf(' is invalid XML, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
1467
+ }
1468
+ else
1469
+ {
1470
+ $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
1471
+ }
1472
+
1473
+ $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1474
+
1475
+ return false;
1476
+ }
1477
+
1478
+ /**
1479
+ * Fetch the data via SimpleCluvPie_File
1480
+ *
1481
+ * If the data is already cached, attempt to fetch it from there instead
1482
+ * @param SimpleCluvPie_Cache|false $cache Cache handler, or false to not load from the cache
1483
+ * @return array|true Returns true if the data was loaded from the cache, or an array of HTTP headers and sniffed type
1484
+ */
1485
+ protected function fetch_data(&$cache)
1486
+ {
1487
+ // If it's enabled, use the cache
1488
+ if ($cache)
1489
+ {
1490
+ // Load the Cache
1491
+ $this->data = $cache->load();
1492
+ if (!empty($this->data))
1493
+ {
1494
+ // If the cache is for an outdated build of SimpleCluvPie
1495
+ if (!isset($this->data['build']) || $this->data['build'] !== SIMPLECLUVPIE_BUILD)
1496
+ {
1497
+ $cache->unlink();
1498
+ $this->data = array();
1499
+ }
1500
+ // If we've hit a collision just rerun it with caching disabled
1501
+ elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
1502
+ {
1503
+ $cache = false;
1504
+ $this->data = array();
1505
+ }
1506
+ // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
1507
+ elseif (isset($this->data['feed_url']))
1508
+ {
1509
+ // If the autodiscovery cache is still valid use it.
1510
+ if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
1511
+ {
1512
+ // Do not need to do feed autodiscovery yet.
1513
+ if ($this->data['feed_url'] !== $this->data['url'])
1514
+ {
1515
+ $this->set_feed_url($this->data['feed_url']);
1516
+ return $this->init();
1517
+ }
1518
+
1519
+ $cache->unlink();
1520
+ $this->data = array();
1521
+ }
1522
+ }
1523
+ // Check if the cache has been updated
1524
+ elseif ($cache->mtime() + $this->cache_duration < time())
1525
+ {
1526
+ // Want to know if we tried to send last-modified and/or etag headers
1527
+ // when requesting this file. (Note that it's up to the file to
1528
+ // support this, but we don't always send the headers either.)
1529
+ $this->check_modified = true;
1530
+ if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
1531
+ {
1532
+ $headers = array(
1533
+ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1534
+ );
1535
+ if (isset($this->data['headers']['last-modified']))
1536
+ {
1537
+ $headers['if-modified-since'] = $this->data['headers']['last-modified'];
1538
+ }
1539
+ if (isset($this->data['headers']['etag']))
1540
+ {
1541
+ $headers['if-none-match'] = $this->data['headers']['etag'];
1542
+ }
1543
+
1544
+ $file = $this->registry->create('File', array($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
1545
+
1546
+ if ($file->success)
1547
+ {
1548
+ if ($file->status_code === 304)
1549
+ {
1550
+ // Set raw_data to false here too, to signify that the cache
1551
+ // is still valid.
1552
+ $this->raw_data = false;
1553
+ $cache->touch();
1554
+ return true;
1555
+ }
1556
+ }
1557
+ else
1558
+ {
1559
+ $this->check_modified = false;
1560
+ if($this->force_cache_fallback)
1561
+ {
1562
+ $cache->touch();
1563
+ return true;
1564
+ }
1565
+
1566
+ unset($file);
1567
+ }
1568
+ }
1569
+ }
1570
+ // If the cache is still valid, just return true
1571
+ else
1572
+ {
1573
+ $this->raw_data = false;
1574
+ return true;
1575
+ }
1576
+ }
1577
+ // If the cache is empty, delete it
1578
+ else
1579
+ {
1580
+ $cache->unlink();
1581
+ $this->data = array();
1582
+ }
1583
+ }
1584
+ // 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.
1585
+ if (!isset($file))
1586
+ {
1587
+ if ($this->file instanceof SimpleCluvPie_File && $this->file->url === $this->feed_url)
1588
+ {
1589
+ $file =& $this->file;
1590
+ }
1591
+ else
1592
+ {
1593
+ $headers = array(
1594
+ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
1595
+ );
1596
+ $file = $this->registry->create('File', array($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen, $this->curl_options));
1597
+ }
1598
+ }
1599
+ // If the file connection has an error, set SimpleCluvPie::error to that and quit
1600
+ if (!$file->success && !($file->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
1601
+ {
1602
+ $this->error = $file->error;
1603
+ return !empty($this->data);
1604
+ }
1605
+
1606
+ if (!$this->force_feed)
1607
+ {
1608
+ // Check if the supplied URL is a feed, if it isn't, look for it.
1609
+ $locate = $this->registry->create('Locator', array(&$file, $this->timeout, $this->useragent, $this->max_checked_feeds));
1610
+
1611
+ if (!$locate->is_feed($file))
1612
+ {
1613
+ $copyStatusCode = $file->status_code;
1614
+ $copyContentType = $file->headers['content-type'];
1615
+ try
1616
+ {
1617
+ $microformats = false;
1618
+ if (function_exists('Mf2\parse')) {
1619
+ // Check for both h-feed and h-entry, as both a feed with no entries
1620
+ // and a list of entries without an h-feed wrapper are both valid.
1621
+ $position = 0;
1622
+ while ($position = strpos($file->body, 'h-feed', $position))
1623
+ {
1624
+ $start = $position < 200 ? 0 : $position - 200;
1625
+ $check = substr($file->body, $start, 400);
1626
+ if ($microformats = preg_match('/class="[^"]*h-feed/', $check))
1627
+ {
1628
+ break;
1629
+ }
1630
+ $position += 7;
1631
+ }
1632
+ $position = 0;
1633
+ while ($position = strpos($file->body, 'h-entry', $position))
1634
+ {
1635
+ $start = $position < 200 ? 0 : $position - 200;
1636
+ $check = substr($file->body, $start, 400);
1637
+ if ($microformats = preg_match('/class="[^"]*h-entry/', $check))
1638
+ {
1639
+ break;
1640
+ }
1641
+ $position += 7;
1642
+ }
1643
+ }
1644
+ // Now also do feed discovery, but if an h-entry was found don't
1645
+ // overwrite the current value of file.
1646
+ $discovered = $locate->find($this->autodiscovery,
1647
+ $this->all_discovered_feeds);
1648
+ if ($microformats)
1649
+ {
1650
+ if ($hub = $locate->get_rel_link('hub'))
1651
+ {
1652
+ $self = $locate->get_rel_link('self');
1653
+ $this->store_links($file, $hub, $self);
1654
+ }
1655
+ // Push the current file onto all_discovered feeds so the user can
1656
+ // be shown this as one of the options.
1657
+ if (isset($this->all_discovered_feeds)) {
1658
+ $this->all_discovered_feeds[] = $file;
1659
+ }
1660
+ }
1661
+ else
1662
+ {
1663
+ if ($discovered)
1664
+ {
1665
+ $file = $discovered;
1666
+ }
1667
+ else
1668
+ {
1669
+ // We need to unset this so that if SimpleCluvPie::set_file() has
1670
+ // been called that object is untouched
1671
+ unset($file);
1672
+ $this->error = "A feed could not be found at `$this->feed_url`; the status code is `$copyStatusCode` and content-type is `$copyContentType`";
1673
+ $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, __FILE__, __LINE__));
1674
+ return false;
1675
+ }
1676
+ }
1677
+ }
1678
+ catch (SimpleCluvPie_Exception $e)
1679
+ {
1680
+ // We need to unset this so that if SimpleCluvPie::set_file() has been called that object is untouched
1681
+ unset($file);
1682
+ // This is usually because DOMDocument doesn't exist
1683
+ $this->error = $e->getMessage();
1684
+ $this->registry->call('Misc', 'error', array($this->error, E_USER_NOTICE, $e->getFile(), $e->getLine()));
1685
+ return false;
1686
+ }
1687
+ if ($cache)
1688
+ {
1689
+ $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLECLUVPIE_BUILD);
1690
+ if (!$cache->save($this))
1691
+ {
1692
+ trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
1693
+ }
1694
+ $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc'));
1695
+ }
1696
+ $this->feed_url = $file->url;
1697
+ }
1698
+ $locate = null;
1699
+ }
1700
+
1701
+ $this->raw_data = $file->body;
1702
+ $this->permanent_url = $file->permanent_url;
1703
+ $headers = $file->headers;
1704
+ $sniffer = $this->registry->create('Content_Type_Sniffer', array(&$file));
1705
+ $sniffed = $sniffer->get_type();
1706
+
1707
+ return array($headers, $sniffed);
1708
+ }
1709
+
1710
+ /**
1711
+ * Get the error message for the occured error
1712
+ *
1713
+ * @return string|array Error message, or array of messages for multifeeds
1714
+ */
1715
+ public function error()
1716
+ {
1717
+ return $this->error;
1718
+ }
1719
+
1720
+ /**
1721
+ * Get the raw XML
1722
+ *
1723
+ * This is the same as the old `$feed->enable_xml_dump(true)`, but returns
1724
+ * the data instead of printing it.
1725
+ *
1726
+ * @return string|boolean Raw XML data, false if the cache is used
1727
+ */
1728
+ public function get_raw_data()
1729
+ {
1730
+ return $this->raw_data;
1731
+ }
1732
+
1733
+ /**
1734
+ * Get the character encoding used for output
1735
+ *
1736
+ * @since Preview Release
1737
+ * @return string
1738
+ */
1739
+ public function get_encoding()
1740
+ {
1741
+ return $this->sanitize->output_encoding;
1742
+ }
1743
+
1744
+ /**
1745
+ * Send the content-type header with correct encoding
1746
+ *
1747
+ * This method ensures that the SimpleCluvPie-enabled page is being served with
1748
+ * the correct {@link http://www.iana.org/assignments/media-types/ mime-type}
1749
+ * and character encoding HTTP headers (character encoding determined by the
1750
+ * {@see set_output_encoding} config option).
1751
+ *
1752
+ * This won't work properly if any content or whitespace has already been
1753
+ * sent to the browser, because it relies on PHP's
1754
+ * {@link http://php.net/header header()} function, and these are the
1755
+ * circumstances under which the function works.
1756
+ *
1757
+ * Because it's setting these settings for the entire page (as is the nature
1758
+ * of HTTP headers), this should only be used once per page (again, at the
1759
+ * top).
1760
+ *
1761
+ * @param string $mime MIME type to serve the page as
1762
+ */
1763
+ public function handle_content_type($mime = 'text/html')
1764
+ {
1765
+ if (!headers_sent())
1766
+ {
1767
+ $header = "Content-type: $mime;";
1768
+ if ($this->get_encoding())
1769
+ {
1770
+ $header .= ' charset=' . $this->get_encoding();
1771
+ }
1772
+ else
1773
+ {
1774
+ $header .= ' charset=UTF-8';
1775
+ }
1776
+ header($header);
1777
+ }
1778
+ }
1779
+
1780
+ /**
1781
+ * Get the type of the feed
1782
+ *
1783
+ * This returns a SIMPLECLUVPIE_TYPE_* constant, which can be tested against
1784
+ * using {@link http://php.net/language.operators.bitwise bitwise operators}
1785
+ *
1786
+ * @since 0.8 (usage changed to using constants in 1.0)
1787
+ * @see SIMPLECLUVPIE_TYPE_NONE Unknown.
1788
+ * @see SIMPLECLUVPIE_TYPE_RSS_090 RSS 0.90.
1789
+ * @see SIMPLECLUVPIE_TYPE_RSS_091_NETSCAPE RSS 0.91 (Netscape).
1790
+ * @see SIMPLECLUVPIE_TYPE_RSS_091_USERLAND RSS 0.91 (Userland).
1791
+ * @see SIMPLECLUVPIE_TYPE_RSS_091 RSS 0.91.
1792
+ * @see SIMPLECLUVPIE_TYPE_RSS_092 RSS 0.92.
1793
+ * @see SIMPLECLUVPIE_TYPE_RSS_093 RSS 0.93.
1794
+ * @see SIMPLECLUVPIE_TYPE_RSS_094 RSS 0.94.
1795
+ * @see SIMPLECLUVPIE_TYPE_RSS_10 RSS 1.0.
1796
+ * @see SIMPLECLUVPIE_TYPE_RSS_20 RSS 2.0.x.
1797
+ * @see SIMPLECLUVPIE_TYPE_RSS_RDF RDF-based RSS.
1798
+ * @see SIMPLECLUVPIE_TYPE_RSS_SYNDICATION Non-RDF-based RSS (truly intended as syndication format).
1799
+ * @see SIMPLECLUVPIE_TYPE_RSS_ALL Any version of RSS.
1800
+ * @see SIMPLECLUVPIE_TYPE_ATOM_03 Atom 0.3.
1801
+ * @see SIMPLECLUVPIE_TYPE_ATOM_10 Atom 1.0.
1802
+ * @see SIMPLECLUVPIE_TYPE_ATOM_ALL Any version of Atom.
1803
+ * @see SIMPLECLUVPIE_TYPE_ALL Any known/supported feed type.
1804
+ * @return int SIMPLECLUVPIE_TYPE_* constant
1805
+ */
1806
+ public function get_type()
1807
+ {
1808
+ if (!isset($this->data['type']))
1809
+ {
1810
+ $this->data['type'] = SIMPLECLUVPIE_TYPE_ALL;
1811
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed']))
1812
+ {
1813
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_ATOM_10;
1814
+ }
1815
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed']))
1816
+ {
1817
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_ATOM_03;
1818
+ }
1819
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF']))
1820
+ {
1821
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['channel'])
1822
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['image'])
1823
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['item'])
1824
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['textinput']))
1825
+ {
1826
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_10;
1827
+ }
1828
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['channel'])
1829
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['image'])
1830
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['item'])
1831
+ || isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['textinput']))
1832
+ {
1833
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_090;
1834
+ }
1835
+ }
1836
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss']))
1837
+ {
1838
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_ALL;
1839
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1840
+ {
1841
+ switch (trim($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
1842
+ {
1843
+ case '0.91':
1844
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_091;
1845
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1846
+ {
1847
+ switch (trim($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
1848
+ {
1849
+ case '0':
1850
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_091_NETSCAPE;
1851
+ break;
1852
+
1853
+ case '24':
1854
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_091_USERLAND;
1855
+ break;
1856
+ }
1857
+ }
1858
+ break;
1859
+
1860
+ case '0.92':
1861
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_092;
1862
+ break;
1863
+
1864
+ case '0.93':
1865
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_093;
1866
+ break;
1867
+
1868
+ case '0.94':
1869
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_094;
1870
+ break;
1871
+
1872
+ case '2.0':
1873
+ $this->data['type'] &= SIMPLECLUVPIE_TYPE_RSS_20;
1874
+ break;
1875
+ }
1876
+ }
1877
+ }
1878
+ else
1879
+ {
1880
+ $this->data['type'] = SIMPLECLUVPIE_TYPE_NONE;
1881
+ }
1882
+ }
1883
+ return $this->data['type'];
1884
+ }
1885
+
1886
+ /**
1887
+ * Get the URL for the feed
1888
+ *
1889
+ * When the 'permanent' mode is enabled, returns the original feed URL,
1890
+ * except in the case of an `HTTP 301 Moved Permanently` status response,
1891
+ * in which case the location of the first redirection is returned.
1892
+ *
1893
+ * When the 'permanent' mode is disabled (default),
1894
+ * may or may not be different from the URL passed to {@see set_feed_url()},
1895
+ * depending on whether auto-discovery was used.
1896
+ *
1897
+ * @since Preview Release (previously called `get_feed_url()` since SimpleCluvPie 0.8.)
1898
+ * @todo Support <itunes:new-feed-url>
1899
+ * @todo Also, |atom:link|@rel=self
1900
+ * @param bool $permanent Permanent mode to return only the original URL or the first redirection
1901
+ * iff it is a 301 redirection
1902
+ * @return string|null
1903
+ */
1904
+ public function subscribe_url($permanent = false)
1905
+ {
1906
+ if ($permanent)
1907
+ {
1908
+ if ($this->permanent_url !== null)
1909
+ {
1910
+ // sanitize encodes ampersands which are required when used in a url.
1911
+ return str_replace('&amp;', '&',
1912
+ $this->sanitize($this->permanent_url,
1913
+ SIMPLECLUVPIE_CONSTRUCT_IRI));
1914
+ }
1915
+ }
1916
+ else
1917
+ {
1918
+ if ($this->feed_url !== null)
1919
+ {
1920
+ return str_replace('&amp;', '&',
1921
+ $this->sanitize($this->feed_url,
1922
+ SIMPLECLUVPIE_CONSTRUCT_IRI));
1923
+ }
1924
+ }
1925
+ return null;
1926
+ }
1927
+
1928
+ /**
1929
+ * Get data for an feed-level element
1930
+ *
1931
+ * This method allows you to get access to ANY element/attribute that is a
1932
+ * sub-element of the opening feed tag.
1933
+ *
1934
+ * The return value is an indexed array of elements matching the given
1935
+ * namespace and tag name. Each element has `attribs`, `data` and `child`
1936
+ * subkeys. For `attribs` and `child`, these contain namespace subkeys.
1937
+ * `attribs` then has one level of associative name => value data (where
1938
+ * `value` is a string) after the namespace. `child` has tag-indexed keys
1939
+ * after the namespace, each member of which is an indexed array matching
1940
+ * this same format.
1941
+ *
1942
+ * For example:
1943
+ * <pre>
1944
+ * // This is probably a bad example because we already support
1945
+ * // <media:content> natively, but it shows you how to parse through
1946
+ * // the nodes.
1947
+ * $group = $item->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'group');
1948
+ * $content = $group[0]['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['content'];
1949
+ * $file = $content[0]['attribs']['']['url'];
1950
+ * echo $file;
1951
+ * </pre>
1952
+ *
1953
+ * @since 1.0
1954
+ * @see http://simplecluvpie.org/wiki/faq/supported_xml_namespaces
1955
+ * @param string $namespace The URL of the XML namespace of the elements you're trying to access
1956
+ * @param string $tag Tag name
1957
+ * @return array
1958
+ */
1959
+ public function get_feed_tags($namespace, $tag)
1960
+ {
1961
+ $type = $this->get_type();
1962
+ if ($type & SIMPLECLUVPIE_TYPE_ATOM_10)
1963
+ {
1964
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
1965
+ {
1966
+ return $this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
1967
+ }
1968
+ }
1969
+ if ($type & SIMPLECLUVPIE_TYPE_ATOM_03)
1970
+ {
1971
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
1972
+ {
1973
+ return $this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
1974
+ }
1975
+ }
1976
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_RDF)
1977
+ {
1978
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
1979
+ {
1980
+ return $this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
1981
+ }
1982
+ }
1983
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION)
1984
+ {
1985
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
1986
+ {
1987
+ return $this->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
1988
+ }
1989
+ }
1990
+ return null;
1991
+ }
1992
+
1993
+ /**
1994
+ * Get data for an channel-level element
1995
+ *
1996
+ * This method allows you to get access to ANY element/attribute in the
1997
+ * channel/header section of the feed.
1998
+ *
1999
+ * See {@see SimpleCluvPie::get_feed_tags()} for a description of the return value
2000
+ *
2001
+ * @since 1.0
2002
+ * @see http://simplecluvpie.org/wiki/faq/supported_xml_namespaces
2003
+ * @param string $namespace The URL of the XML namespace of the elements you're trying to access
2004
+ * @param string $tag Tag name
2005
+ * @return array
2006
+ */
2007
+ public function get_channel_tags($namespace, $tag)
2008
+ {
2009
+ $type = $this->get_type();
2010
+ if ($type & SIMPLECLUVPIE_TYPE_ATOM_ALL)
2011
+ {
2012
+ if ($return = $this->get_feed_tags($namespace, $tag))
2013
+ {
2014
+ return $return;
2015
+ }
2016
+ }
2017
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_10)
2018
+ {
2019
+ if ($channel = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'channel'))
2020
+ {
2021
+ if (isset($channel[0]['child'][$namespace][$tag]))
2022
+ {
2023
+ return $channel[0]['child'][$namespace][$tag];
2024
+ }
2025
+ }
2026
+ }
2027
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_090)
2028
+ {
2029
+ if ($channel = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'channel'))
2030
+ {
2031
+ if (isset($channel[0]['child'][$namespace][$tag]))
2032
+ {
2033
+ return $channel[0]['child'][$namespace][$tag];
2034
+ }
2035
+ }
2036
+ }
2037
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION)
2038
+ {
2039
+ if ($channel = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'channel'))
2040
+ {
2041
+ if (isset($channel[0]['child'][$namespace][$tag]))
2042
+ {
2043
+ return $channel[0]['child'][$namespace][$tag];
2044
+ }
2045
+ }
2046
+ }
2047
+ return null;
2048
+ }
2049
+
2050
+ /**
2051
+ * Get data for an channel-level element
2052
+ *
2053
+ * This method allows you to get access to ANY element/attribute in the
2054
+ * image/logo section of the feed.
2055
+ *
2056
+ * See {@see SimpleCluvPie::get_feed_tags()} for a description of the return value
2057
+ *
2058
+ * @since 1.0
2059
+ * @see http://simplecluvpie.org/wiki/faq/supported_xml_namespaces
2060
+ * @param string $namespace The URL of the XML namespace of the elements you're trying to access
2061
+ * @param string $tag Tag name
2062
+ * @return array
2063
+ */
2064
+ public function get_image_tags($namespace, $tag)
2065
+ {
2066
+ $type = $this->get_type();
2067
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_10)
2068
+ {
2069
+ if ($image = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'image'))
2070
+ {
2071
+ if (isset($image[0]['child'][$namespace][$tag]))
2072
+ {
2073
+ return $image[0]['child'][$namespace][$tag];
2074
+ }
2075
+ }
2076
+ }
2077
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_090)
2078
+ {
2079
+ if ($image = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'image'))
2080
+ {
2081
+ if (isset($image[0]['child'][$namespace][$tag]))
2082
+ {
2083
+ return $image[0]['child'][$namespace][$tag];
2084
+ }
2085
+ }
2086
+ }
2087
+ if ($type & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION)
2088
+ {
2089
+ if ($image = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'image'))
2090
+ {
2091
+ if (isset($image[0]['child'][$namespace][$tag]))
2092
+ {
2093
+ return $image[0]['child'][$namespace][$tag];
2094
+ }
2095
+ }
2096
+ }
2097
+ return null;
2098
+ }
2099
+
2100
+ /**
2101
+ * Get the base URL value from the feed
2102
+ *
2103
+ * Uses `<xml:base>` if available, otherwise uses the first link in the
2104
+ * feed, or failing that, the URL of the feed itself.
2105
+ *
2106
+ * @see get_link
2107
+ * @see subscribe_url
2108
+ *
2109
+ * @param array $element
2110
+ * @return string
2111
+ */
2112
+ public function get_base($element = array())
2113
+ {
2114
+ if (!($this->get_type() & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
2115
+ {
2116
+ return $element['xml_base'];
2117
+ }
2118
+ elseif ($this->get_link() !== null)
2119
+ {
2120
+ return $this->get_link();
2121
+ }
2122
+ else
2123
+ {
2124
+ return $this->subscribe_url();
2125
+ }
2126
+ }
2127
+
2128
+ /**
2129
+ * Sanitize feed data
2130
+ *
2131
+ * @access private
2132
+ * @see SimpleCluvPie_Sanitize::sanitize()
2133
+ * @param string $data Data to sanitize
2134
+ * @param int $type One of the SIMPLECLUVPIE_CONSTRUCT_* constants
2135
+ * @param string $base Base URL to resolve URLs against
2136
+ * @return string Sanitized data
2137
+ */
2138
+ public function sanitize($data, $type, $base = '')
2139
+ {
2140
+ try
2141
+ {
2142
+ return $this->sanitize->sanitize($data, $type, $base);
2143
+ }
2144
+ catch (SimpleCluvPie_Exception $e)
2145
+ {
2146
+ if (!$this->enable_exceptions)
2147
+ {
2148
+ $this->error = $e->getMessage();
2149
+ $this->registry->call('Misc', 'error', array($this->error, E_USER_WARNING, $e->getFile(), $e->getLine()));
2150
+ return '';
2151
+ }
2152
+
2153
+ throw $e;
2154
+ }
2155
+ }
2156
+
2157
+ /**
2158
+ * Get the title of the feed
2159
+ *
2160
+ * Uses `<atom:title>`, `<title>` or `<dc:title>`
2161
+ *
2162
+ * @since 1.0 (previously called `get_feed_title` since 0.8)
2163
+ * @return string|null
2164
+ */
2165
+ public function get_title()
2166
+ {
2167
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'title'))
2168
+ {
2169
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2170
+ }
2171
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'title'))
2172
+ {
2173
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2174
+ }
2175
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'title'))
2176
+ {
2177
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2178
+ }
2179
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'title'))
2180
+ {
2181
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2182
+ }
2183
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'title'))
2184
+ {
2185
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2186
+ }
2187
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'title'))
2188
+ {
2189
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2190
+ }
2191
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'title'))
2192
+ {
2193
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2194
+ }
2195
+ else
2196
+ {
2197
+ return null;
2198
+ }
2199
+ }
2200
+
2201
+ /**
2202
+ * Get a category for the feed
2203
+ *
2204
+ * @since Unknown
2205
+ * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
2206
+ * @return SimpleCluvPie_Category|null
2207
+ */
2208
+ public function get_category($key = 0)
2209
+ {
2210
+ $categories = $this->get_categories();
2211
+ if (isset($categories[$key]))
2212
+ {
2213
+ return $categories[$key];
2214
+ }
2215
+ else
2216
+ {
2217
+ return null;
2218
+ }
2219
+ }
2220
+
2221
+ /**
2222
+ * Get all categories for the feed
2223
+ *
2224
+ * Uses `<atom:category>`, `<category>` or `<dc:subject>`
2225
+ *
2226
+ * @since Unknown
2227
+ * @return array|null List of {@see SimpleCluvPie_Category} objects
2228
+ */
2229
+ public function get_categories()
2230
+ {
2231
+ $categories = array();
2232
+
2233
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'category') as $category)
2234
+ {
2235
+ $term = null;
2236
+ $scheme = null;
2237
+ $label = null;
2238
+ if (isset($category['attribs']['']['term']))
2239
+ {
2240
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2241
+ }
2242
+ if (isset($category['attribs']['']['scheme']))
2243
+ {
2244
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2245
+ }
2246
+ if (isset($category['attribs']['']['label']))
2247
+ {
2248
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2249
+ }
2250
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
2251
+ }
2252
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'category') as $category)
2253
+ {
2254
+ // This is really the label, but keep this as the term also for BC.
2255
+ // Label will also work on retrieving because that falls back to term.
2256
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2257
+ if (isset($category['attribs']['']['domain']))
2258
+ {
2259
+ $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2260
+ }
2261
+ else
2262
+ {
2263
+ $scheme = null;
2264
+ }
2265
+ $categories[] = $this->registry->create('Category', array($term, $scheme, null));
2266
+ }
2267
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'subject') as $category)
2268
+ {
2269
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
2270
+ }
2271
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'subject') as $category)
2272
+ {
2273
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
2274
+ }
2275
+
2276
+ if (!empty($categories))
2277
+ {
2278
+ return array_unique($categories);
2279
+ }
2280
+ else
2281
+ {
2282
+ return null;
2283
+ }
2284
+ }
2285
+
2286
+ /**
2287
+ * Get an author for the feed
2288
+ *
2289
+ * @since 1.1
2290
+ * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
2291
+ * @return SimpleCluvPie_Author|null
2292
+ */
2293
+ public function get_author($key = 0)
2294
+ {
2295
+ $authors = $this->get_authors();
2296
+ if (isset($authors[$key]))
2297
+ {
2298
+ return $authors[$key];
2299
+ }
2300
+ else
2301
+ {
2302
+ return null;
2303
+ }
2304
+ }
2305
+
2306
+ /**
2307
+ * Get all authors for the feed
2308
+ *
2309
+ * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
2310
+ *
2311
+ * @since 1.1
2312
+ * @return array|null List of {@see SimpleCluvPie_Author} objects
2313
+ */
2314
+ public function get_authors()
2315
+ {
2316
+ $authors = array();
2317
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'author') as $author)
2318
+ {
2319
+ $name = null;
2320
+ $uri = null;
2321
+ $email = null;
2322
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2323
+ {
2324
+ $name = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2325
+ }
2326
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2327
+ {
2328
+ $uri = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
2329
+ }
2330
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2331
+ {
2332
+ $email = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2333
+ }
2334
+ if ($name !== null || $email !== null || $uri !== null)
2335
+ {
2336
+ $authors[] = $this->registry->create('Author', array($name, $uri, $email));
2337
+ }
2338
+ }
2339
+ if ($author = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'author'))
2340
+ {
2341
+ $name = null;
2342
+ $url = null;
2343
+ $email = null;
2344
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2345
+ {
2346
+ $name = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2347
+ }
2348
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2349
+ {
2350
+ $url = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
2351
+ }
2352
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2353
+ {
2354
+ $email = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2355
+ }
2356
+ if ($name !== null || $email !== null || $url !== null)
2357
+ {
2358
+ $authors[] = $this->registry->create('Author', array($name, $url, $email));
2359
+ }
2360
+ }
2361
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'creator') as $author)
2362
+ {
2363
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
2364
+ }
2365
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'creator') as $author)
2366
+ {
2367
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
2368
+ }
2369
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'author') as $author)
2370
+ {
2371
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
2372
+ }
2373
+
2374
+ if (!empty($authors))
2375
+ {
2376
+ return array_unique($authors);
2377
+ }
2378
+ else
2379
+ {
2380
+ return null;
2381
+ }
2382
+ }
2383
+
2384
+ /**
2385
+ * Get a contributor for the feed
2386
+ *
2387
+ * @since 1.1
2388
+ * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
2389
+ * @return SimpleCluvPie_Author|null
2390
+ */
2391
+ public function get_contributor($key = 0)
2392
+ {
2393
+ $contributors = $this->get_contributors();
2394
+ if (isset($contributors[$key]))
2395
+ {
2396
+ return $contributors[$key];
2397
+ }
2398
+ else
2399
+ {
2400
+ return null;
2401
+ }
2402
+ }
2403
+
2404
+ /**
2405
+ * Get all contributors for the feed
2406
+ *
2407
+ * Uses `<atom:contributor>`
2408
+ *
2409
+ * @since 1.1
2410
+ * @return array|null List of {@see SimpleCluvPie_Author} objects
2411
+ */
2412
+ public function get_contributors()
2413
+ {
2414
+ $contributors = array();
2415
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
2416
+ {
2417
+ $name = null;
2418
+ $uri = null;
2419
+ $email = null;
2420
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
2421
+ {
2422
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2423
+ }
2424
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
2425
+ {
2426
+ $uri = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
2427
+ }
2428
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
2429
+ {
2430
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2431
+ }
2432
+ if ($name !== null || $email !== null || $uri !== null)
2433
+ {
2434
+ $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
2435
+ }
2436
+ }
2437
+ foreach ((array) $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
2438
+ {
2439
+ $name = null;
2440
+ $url = null;
2441
+ $email = null;
2442
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
2443
+ {
2444
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2445
+ }
2446
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
2447
+ {
2448
+ $url = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
2449
+ }
2450
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
2451
+ {
2452
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2453
+ }
2454
+ if ($name !== null || $email !== null || $url !== null)
2455
+ {
2456
+ $contributors[] = $this->registry->create('Author', array($name, $url, $email));
2457
+ }
2458
+ }
2459
+
2460
+ if (!empty($contributors))
2461
+ {
2462
+ return array_unique($contributors);
2463
+ }
2464
+ else
2465
+ {
2466
+ return null;
2467
+ }
2468
+ }
2469
+
2470
+ /**
2471
+ * Get a single link for the feed
2472
+ *
2473
+ * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2474
+ * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
2475
+ * @param string $rel The relationship of the link to return
2476
+ * @return string|null Link URL
2477
+ */
2478
+ public function get_link($key = 0, $rel = 'alternate')
2479
+ {
2480
+ $links = $this->get_links($rel);
2481
+ if (isset($links[$key]))
2482
+ {
2483
+ return $links[$key];
2484
+ }
2485
+ else
2486
+ {
2487
+ return null;
2488
+ }
2489
+ }
2490
+
2491
+ /**
2492
+ * Get the permalink for the item
2493
+ *
2494
+ * Returns the first link available with a relationship of "alternate".
2495
+ * Identical to {@see get_link()} with key 0
2496
+ *
2497
+ * @see get_link
2498
+ * @since 1.0 (previously called `get_feed_link` since Preview Release, `get_feed_permalink()` since 0.8)
2499
+ * @internal Added for parity between the parent-level and the item/entry-level.
2500
+ * @return string|null Link URL
2501
+ */
2502
+ public function get_permalink()
2503
+ {
2504
+ return $this->get_link(0);
2505
+ }
2506
+
2507
+ /**
2508
+ * Get all links for the feed
2509
+ *
2510
+ * Uses `<atom:link>` or `<link>`
2511
+ *
2512
+ * @since Beta 2
2513
+ * @param string $rel The relationship of links to return
2514
+ * @return array|null Links found for the feed (strings)
2515
+ */
2516
+ public function get_links($rel = 'alternate')
2517
+ {
2518
+ if (!isset($this->data['links']))
2519
+ {
2520
+ $this->data['links'] = array();
2521
+ if ($links = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'link'))
2522
+ {
2523
+ foreach ($links as $link)
2524
+ {
2525
+ if (isset($link['attribs']['']['href']))
2526
+ {
2527
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2528
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
2529
+ }
2530
+ }
2531
+ }
2532
+ if ($links = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'link'))
2533
+ {
2534
+ foreach ($links as $link)
2535
+ {
2536
+ if (isset($link['attribs']['']['href']))
2537
+ {
2538
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
2539
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
2540
+
2541
+ }
2542
+ }
2543
+ }
2544
+ if ($links = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'link'))
2545
+ {
2546
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2547
+ }
2548
+ if ($links = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'link'))
2549
+ {
2550
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2551
+ }
2552
+ if ($links = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'link'))
2553
+ {
2554
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
2555
+ }
2556
+
2557
+ $keys = array_keys($this->data['links']);
2558
+ foreach ($keys as $key)
2559
+ {
2560
+ if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
2561
+ {
2562
+ if (isset($this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
2563
+ {
2564
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
2565
+ $this->data['links'][$key] =& $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
2566
+ }
2567
+ else
2568
+ {
2569
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
2570
+ }
2571
+ }
2572
+ elseif (substr($key, 0, 41) === SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY)
2573
+ {
2574
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
2575
+ }
2576
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
2577
+ }
2578
+ }
2579
+
2580
+ if (isset($this->data['links'][$rel]))
2581
+ {
2582
+ return $this->data['links'][$rel];
2583
+ }
2584
+ else if (isset($this->data['headers']['link']) &&
2585
+ preg_match('/<([^>]+)>; rel='.preg_quote($rel).'/',
2586
+ $this->data['headers']['link'], $match))
2587
+ {
2588
+ return array($match[1]);
2589
+ }
2590
+ else
2591
+ {
2592
+ return null;
2593
+ }
2594
+ }
2595
+
2596
+ public function get_all_discovered_feeds()
2597
+ {
2598
+ return $this->all_discovered_feeds;
2599
+ }
2600
+
2601
+ /**
2602
+ * Get the content for the item
2603
+ *
2604
+ * Uses `<atom:subtitle>`, `<atom:tagline>`, `<description>`,
2605
+ * `<dc:description>`, `<itunes:summary>` or `<itunes:subtitle>`
2606
+ *
2607
+ * @since 1.0 (previously called `get_feed_description()` since 0.8)
2608
+ * @return string|null
2609
+ */
2610
+ public function get_description()
2611
+ {
2612
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'subtitle'))
2613
+ {
2614
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2615
+ }
2616
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'tagline'))
2617
+ {
2618
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2619
+ }
2620
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'description'))
2621
+ {
2622
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2623
+ }
2624
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'description'))
2625
+ {
2626
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
2627
+ }
2628
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'description'))
2629
+ {
2630
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2631
+ }
2632
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'description'))
2633
+ {
2634
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2635
+ }
2636
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'description'))
2637
+ {
2638
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2639
+ }
2640
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'summary'))
2641
+ {
2642
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2643
+ }
2644
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'subtitle'))
2645
+ {
2646
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
2647
+ }
2648
+ else
2649
+ {
2650
+ return null;
2651
+ }
2652
+ }
2653
+
2654
+ /**
2655
+ * Get the copyright info for the feed
2656
+ *
2657
+ * Uses `<atom:rights>`, `<atom:copyright>` or `<dc:rights>`
2658
+ *
2659
+ * @since 1.0 (previously called `get_feed_copyright()` since 0.8)
2660
+ * @return string|null
2661
+ */
2662
+ public function get_copyright()
2663
+ {
2664
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'rights'))
2665
+ {
2666
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2667
+ }
2668
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'copyright'))
2669
+ {
2670
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
2671
+ }
2672
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'copyright'))
2673
+ {
2674
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2675
+ }
2676
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'rights'))
2677
+ {
2678
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2679
+ }
2680
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'rights'))
2681
+ {
2682
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2683
+ }
2684
+ else
2685
+ {
2686
+ return null;
2687
+ }
2688
+ }
2689
+
2690
+ /**
2691
+ * Get the language for the feed
2692
+ *
2693
+ * Uses `<language>`, `<dc:language>`, or @xml_lang
2694
+ *
2695
+ * @since 1.0 (previously called `get_feed_language()` since 0.8)
2696
+ * @return string|null
2697
+ */
2698
+ public function get_language()
2699
+ {
2700
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'language'))
2701
+ {
2702
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2703
+ }
2704
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'language'))
2705
+ {
2706
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2707
+ }
2708
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'language'))
2709
+ {
2710
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2711
+ }
2712
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
2713
+ {
2714
+ return $this->sanitize($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2715
+ }
2716
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
2717
+ {
2718
+ return $this->sanitize($this->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2719
+ }
2720
+ elseif (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
2721
+ {
2722
+ return $this->sanitize($this->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2723
+ }
2724
+ elseif (isset($this->data['headers']['content-language']))
2725
+ {
2726
+ return $this->sanitize($this->data['headers']['content-language'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2727
+ }
2728
+ else
2729
+ {
2730
+ return null;
2731
+ }
2732
+ }
2733
+
2734
+ /**
2735
+ * Get the latitude coordinates for the item
2736
+ *
2737
+ * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2738
+ *
2739
+ * Uses `<geo:lat>` or `<georss:point>`
2740
+ *
2741
+ * @since 1.0
2742
+ * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2743
+ * @link http://www.georss.org/ GeoRSS
2744
+ * @return string|null
2745
+ */
2746
+ public function get_latitude()
2747
+ {
2748
+
2749
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2750
+ {
2751
+ return (float) $return[0]['data'];
2752
+ }
2753
+ elseif (($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2754
+ {
2755
+ return (float) $match[1];
2756
+ }
2757
+ else
2758
+ {
2759
+ return null;
2760
+ }
2761
+ }
2762
+
2763
+ /**
2764
+ * Get the longitude coordinates for the feed
2765
+ *
2766
+ * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2767
+ *
2768
+ * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2769
+ *
2770
+ * @since 1.0
2771
+ * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2772
+ * @link http://www.georss.org/ GeoRSS
2773
+ * @return string|null
2774
+ */
2775
+ public function get_longitude()
2776
+ {
2777
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2778
+ {
2779
+ return (float) $return[0]['data'];
2780
+ }
2781
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2782
+ {
2783
+ return (float) $return[0]['data'];
2784
+ }
2785
+ elseif (($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2786
+ {
2787
+ return (float) $match[2];
2788
+ }
2789
+ else
2790
+ {
2791
+ return null;
2792
+ }
2793
+ }
2794
+
2795
+ /**
2796
+ * Get the feed logo's title
2797
+ *
2798
+ * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" title.
2799
+ *
2800
+ * Uses `<image><title>` or `<image><dc:title>`
2801
+ *
2802
+ * @return string|null
2803
+ */
2804
+ public function get_image_title()
2805
+ {
2806
+ if ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'title'))
2807
+ {
2808
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2809
+ }
2810
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'title'))
2811
+ {
2812
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2813
+ }
2814
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'title'))
2815
+ {
2816
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2817
+ }
2818
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'title'))
2819
+ {
2820
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2821
+ }
2822
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'title'))
2823
+ {
2824
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2825
+ }
2826
+ else
2827
+ {
2828
+ return null;
2829
+ }
2830
+ }
2831
+
2832
+ /**
2833
+ * Get the feed logo's URL
2834
+ *
2835
+ * RSS 0.9.0, 2.0, Atom 1.0, and feeds with iTunes RSS tags are allowed to
2836
+ * have a "feed logo" URL. This points directly to the image itself.
2837
+ *
2838
+ * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2839
+ * `<image><title>` or `<image><dc:title>`
2840
+ *
2841
+ * @return string|null
2842
+ */
2843
+ public function get_image_url()
2844
+ {
2845
+ if ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'image'))
2846
+ {
2847
+ return $this->sanitize($return[0]['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2848
+ }
2849
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'logo'))
2850
+ {
2851
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2852
+ }
2853
+ elseif ($return = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'icon'))
2854
+ {
2855
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2856
+ }
2857
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'url'))
2858
+ {
2859
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2860
+ }
2861
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'url'))
2862
+ {
2863
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2864
+ }
2865
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'url'))
2866
+ {
2867
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2868
+ }
2869
+ else
2870
+ {
2871
+ return null;
2872
+ }
2873
+ }
2874
+
2875
+
2876
+ /**
2877
+ * Get the feed logo's link
2878
+ *
2879
+ * RSS 0.9.0, 1.0 and 2.0 feeds are allowed to have a "feed logo" link. This
2880
+ * points to a human-readable page that the image should link to.
2881
+ *
2882
+ * Uses `<itunes:image>`, `<atom:logo>`, `<atom:icon>`,
2883
+ * `<image><title>` or `<image><dc:title>`
2884
+ *
2885
+ * @return string|null
2886
+ */
2887
+ public function get_image_link()
2888
+ {
2889
+ if ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'link'))
2890
+ {
2891
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2892
+ }
2893
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'link'))
2894
+ {
2895
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2896
+ }
2897
+ elseif ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'link'))
2898
+ {
2899
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
2900
+ }
2901
+ else
2902
+ {
2903
+ return null;
2904
+ }
2905
+ }
2906
+
2907
+ /**
2908
+ * Get the feed logo's link
2909
+ *
2910
+ * RSS 2.0 feeds are allowed to have a "feed logo" width.
2911
+ *
2912
+ * Uses `<image><width>` or defaults to 88.0 if no width is specified and
2913
+ * the feed is an RSS 2.0 feed.
2914
+ *
2915
+ * @return int|float|null
2916
+ */
2917
+ public function get_image_width()
2918
+ {
2919
+ if ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'width'))
2920
+ {
2921
+ return round($return[0]['data']);
2922
+ }
2923
+ elseif ($this->get_type() & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'url'))
2924
+ {
2925
+ return 88.0;
2926
+ }
2927
+ else
2928
+ {
2929
+ return null;
2930
+ }
2931
+ }
2932
+
2933
+ /**
2934
+ * Get the feed logo's height
2935
+ *
2936
+ * RSS 2.0 feeds are allowed to have a "feed logo" height.
2937
+ *
2938
+ * Uses `<image><height>` or defaults to 31.0 if no height is specified and
2939
+ * the feed is an RSS 2.0 feed.
2940
+ *
2941
+ * @return int|float|null
2942
+ */
2943
+ public function get_image_height()
2944
+ {
2945
+ if ($return = $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'height'))
2946
+ {
2947
+ return round($return[0]['data']);
2948
+ }
2949
+ elseif ($this->get_type() & SIMPLECLUVPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'url'))
2950
+ {
2951
+ return 31.0;
2952
+ }
2953
+ else
2954
+ {
2955
+ return null;
2956
+ }
2957
+ }
2958
+
2959
+ /**
2960
+ * Get the number of items in the feed
2961
+ *
2962
+ * This is well-suited for {@link http://php.net/for for()} loops with
2963
+ * {@see get_item()}
2964
+ *
2965
+ * @param int $max Maximum value to return. 0 for no limit
2966
+ * @return int Number of items in the feed
2967
+ */
2968
+ public function get_item_quantity($max = 0)
2969
+ {
2970
+ $max = (int) $max;
2971
+ $qty = count($this->get_items());
2972
+ if ($max === 0)
2973
+ {
2974
+ return $qty;
2975
+ }
2976
+ else
2977
+ {
2978
+ return ($qty > $max) ? $max : $qty;
2979
+ }
2980
+ }
2981
+
2982
+ /**
2983
+ * Get a single item from the feed
2984
+ *
2985
+ * This is better suited for {@link http://php.net/for for()} loops, whereas
2986
+ * {@see get_items()} is better suited for
2987
+ * {@link http://php.net/foreach foreach()} loops.
2988
+ *
2989
+ * @see get_item_quantity()
2990
+ * @since Beta 2
2991
+ * @param int $key The item that you want to return. Remember that arrays begin with 0, not 1
2992
+ * @return SimpleCluvPie_Item|null
2993
+ */
2994
+ public function get_item($key = 0)
2995
+ {
2996
+ $items = $this->get_items();
2997
+ if (isset($items[$key]))
2998
+ {
2999
+ return $items[$key];
3000
+ }
3001
+ else
3002
+ {
3003
+ return null;
3004
+ }
3005
+ }
3006
+
3007
+ /**
3008
+ * Get all items from the feed
3009
+ *
3010
+ * This is better suited for {@link http://php.net/for for()} loops, whereas
3011
+ * {@see get_items()} is better suited for
3012
+ * {@link http://php.net/foreach foreach()} loops.
3013
+ *
3014
+ * @see get_item_quantity
3015
+ * @since Beta 2
3016
+ * @param int $start Index to start at
3017
+ * @param int $end Number of items to return. 0 for all items after `$start`
3018
+ * @return SimpleCluvPie_Item[]|null List of {@see SimpleCluvPie_Item} objects
3019
+ */
3020
+ public function get_items($start = 0, $end = 0)
3021
+ {
3022
+ if (!isset($this->data['items']))
3023
+ {
3024
+ if (!empty($this->multifeed_objects))
3025
+ {
3026
+ $this->data['items'] = SimpleCluvPie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
3027
+ if (empty($this->data['items']))
3028
+ {
3029
+ return array();
3030
+ }
3031
+ return $this->data['items'];
3032
+ }
3033
+ $this->data['items'] = array();
3034
+ if ($items = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'entry'))
3035
+ {
3036
+ $keys = array_keys($items);
3037
+ foreach ($keys as $key)
3038
+ {
3039
+ $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3040
+ }
3041
+ }
3042
+ if ($items = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'entry'))
3043
+ {
3044
+ $keys = array_keys($items);
3045
+ foreach ($keys as $key)
3046
+ {
3047
+ $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3048
+ }
3049
+ }
3050
+ if ($items = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'item'))
3051
+ {
3052
+ $keys = array_keys($items);
3053
+ foreach ($keys as $key)
3054
+ {
3055
+ $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3056
+ }
3057
+ }
3058
+ if ($items = $this->get_feed_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'item'))
3059
+ {
3060
+ $keys = array_keys($items);
3061
+ foreach ($keys as $key)
3062
+ {
3063
+ $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3064
+ }
3065
+ }
3066
+ if ($items = $this->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'item'))
3067
+ {
3068
+ $keys = array_keys($items);
3069
+ foreach ($keys as $key)
3070
+ {
3071
+ $this->data['items'][] = $this->registry->create('Item', array($this, $items[$key]));
3072
+ }
3073
+ }
3074
+ }
3075
+
3076
+ if (empty($this->data['items']))
3077
+ {
3078
+ return array();
3079
+ }
3080
+
3081
+ if ($this->order_by_date)
3082
+ {
3083
+ if (!isset($this->data['ordered_items']))
3084
+ {
3085
+ $this->data['ordered_items'] = $this->data['items'];
3086
+ usort($this->data['ordered_items'], array(get_class($this), 'sort_items'));
3087
+ }
3088
+ $items = $this->data['ordered_items'];
3089
+ }
3090
+ else
3091
+ {
3092
+ $items = $this->data['items'];
3093
+ }
3094
+ // Slice the data as desired
3095
+ if ($end === 0)
3096
+ {
3097
+ return array_slice($items, $start);
3098
+ }
3099
+ else
3100
+ {
3101
+ return array_slice($items, $start, $end);
3102
+ }
3103
+ }
3104
+
3105
+ /**
3106
+ * Set the favicon handler
3107
+ *
3108
+ * @deprecated Use your own favicon handling instead
3109
+ */
3110
+ public function set_favicon_handler($page = false, $qs = 'i')
3111
+ {
3112
+ $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3113
+ trigger_error('Favicon handling has been removed, please use your own handling', $level);
3114
+ return false;
3115
+ }
3116
+
3117
+ /**
3118
+ * Get the favicon for the current feed
3119
+ *
3120
+ * @deprecated Use your own favicon handling instead
3121
+ */
3122
+ public function get_favicon()
3123
+ {
3124
+ $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3125
+ trigger_error('Favicon handling has been removed, please use your own handling', $level);
3126
+
3127
+ if (($url = $this->get_link()) !== null)
3128
+ {
3129
+ return 'http://g.etfv.co/' . urlencode($url);
3130
+ }
3131
+
3132
+ return false;
3133
+ }
3134
+
3135
+ /**
3136
+ * Magic method handler
3137
+ *
3138
+ * @param string $method Method name
3139
+ * @param array $args Arguments to the method
3140
+ * @return mixed
3141
+ */
3142
+ public function __call($method, $args)
3143
+ {
3144
+ if (strpos($method, 'subscribe_') === 0)
3145
+ {
3146
+ $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3147
+ trigger_error('subscribe_*() has been deprecated, implement the callback yourself', $level);
3148
+ return '';
3149
+ }
3150
+ if ($method === 'enable_xml_dump')
3151
+ {
3152
+ $level = defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_WARNING;
3153
+ trigger_error('enable_xml_dump() has been deprecated, use get_raw_data() instead', $level);
3154
+ return false;
3155
+ }
3156
+
3157
+ $class = get_class($this);
3158
+ $trace = debug_backtrace();
3159
+ $file = $trace[0]['file'];
3160
+ $line = $trace[0]['line'];
3161
+ trigger_error("Call to undefined method $class::$method() in $file on line $line", E_USER_ERROR);
3162
+ }
3163
+
3164
+ /**
3165
+ * Sorting callback for items
3166
+ *
3167
+ * @access private
3168
+ * @param SimpleCluvPie $a
3169
+ * @param SimpleCluvPie $b
3170
+ * @return boolean
3171
+ */
3172
+ public static function sort_items($a, $b)
3173
+ {
3174
+ $a_date = $a->get_date('U');
3175
+ $b_date = $b->get_date('U');
3176
+ if ($a_date && $b_date) {
3177
+ return $a_date > $b_date ? -1 : 1;
3178
+ }
3179
+ // Sort items without dates to the top.
3180
+ if ($a_date) {
3181
+ return 1;
3182
+ }
3183
+ if ($b_date) {
3184
+ return -1;
3185
+ }
3186
+ return 0;
3187
+ }
3188
+
3189
+ /**
3190
+ * Merge items from several feeds into one
3191
+ *
3192
+ * If you're merging multiple feeds together, they need to all have dates
3193
+ * for the items or else SimpleCluvPie will refuse to sort them.
3194
+ *
3195
+ * @link http://simplecluvpie.org/wiki/tutorial/sort_multiple_feeds_by_time_and_date#if_feeds_require_separate_per-feed_settings
3196
+ * @param array $urls List of SimpleCluvPie feed objects to merge
3197
+ * @param int $start Starting item
3198
+ * @param int $end Number of items to return
3199
+ * @param int $limit Maximum number of items per feed
3200
+ * @return array
3201
+ */
3202
+ public static function merge_items($urls, $start = 0, $end = 0, $limit = 0)
3203
+ {
3204
+ if (is_array($urls) && sizeof($urls) > 0)
3205
+ {
3206
+ $items = array();
3207
+ foreach ($urls as $arg)
3208
+ {
3209
+ if ($arg instanceof SimpleCluvPie)
3210
+ {
3211
+ $items = array_merge($items, $arg->get_items(0, $limit));
3212
+ }
3213
+ else
3214
+ {
3215
+ trigger_error('Arguments must be SimpleCluvPie objects', E_USER_WARNING);
3216
+ }
3217
+ }
3218
+
3219
+ usort($items, array(get_class($urls[0]), 'sort_items'));
3220
+
3221
+ if ($end === 0)
3222
+ {
3223
+ return array_slice($items, $start);
3224
+ }
3225
+ else
3226
+ {
3227
+ return array_slice($items, $start, $end);
3228
+ }
3229
+ }
3230
+ else
3231
+ {
3232
+ trigger_error('Cannot merge zero SimpleCluvPie objects', E_USER_WARNING);
3233
+ return array();
3234
+ }
3235
+ }
3236
+
3237
+ /**
3238
+ * Store PubSubHubbub links as headers
3239
+ *
3240
+ * There is no way to find PuSH links in the body of a microformats feed,
3241
+ * so they are added to the headers when found, to be used later by get_links.
3242
+ * @param SimpleCluvPie_File $file
3243
+ * @param string $hub
3244
+ * @param string $self
3245
+ */
3246
+ private function store_links(&$file, $hub, $self) {
3247
+ if (isset($file->headers['link']['hub']) ||
3248
+ (isset($file->headers['link']) &&
3249
+ preg_match('/rel=hub/', $file->headers['link'])))
3250
+ {
3251
+ return;
3252
+ }
3253
+
3254
+ if ($hub)
3255
+ {
3256
+ if (isset($file->headers['link']))
3257
+ {
3258
+ if ($file->headers['link'] !== '')
3259
+ {
3260
+ $file->headers['link'] = ', ';
3261
+ }
3262
+ }
3263
+ else
3264
+ {
3265
+ $file->headers['link'] = '';
3266
+ }
3267
+ $file->headers['link'] .= '<'.$hub.'>; rel=hub';
3268
+ if ($self)
3269
+ {
3270
+ $file->headers['link'] .= ', <'.$self.'>; rel=self';
3271
+ }
3272
+ }
3273
+ }
3274
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Author.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Manages all author-related data
46
+ *
47
+ * Used by {@see SimpleCluvPie_Item::get_author()} and {@see SimpleCluvPie::get_authors()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_author_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Author
55
+ {
56
+ /**
57
+ * Author's name
58
+ *
59
+ * @var string
60
+ * @see get_name()
61
+ */
62
+ var $name;
63
+
64
+ /**
65
+ * Author's link
66
+ *
67
+ * @var string
68
+ * @see get_link()
69
+ */
70
+ var $link;
71
+
72
+ /**
73
+ * Author's email address
74
+ *
75
+ * @var string
76
+ * @see get_email()
77
+ */
78
+ var $email;
79
+
80
+ /**
81
+ * Constructor, used to input the data
82
+ *
83
+ * @param string $name
84
+ * @param string $link
85
+ * @param string $email
86
+ */
87
+ public function __construct($name = null, $link = null, $email = null)
88
+ {
89
+ $this->name = $name;
90
+ $this->link = $link;
91
+ $this->email = $email;
92
+ }
93
+
94
+ /**
95
+ * String-ified version
96
+ *
97
+ * @return string
98
+ */
99
+ public function __toString()
100
+ {
101
+ // There is no $this->data here
102
+ return md5(serialize($this));
103
+ }
104
+
105
+ /**
106
+ * Author's name
107
+ *
108
+ * @return string|null
109
+ */
110
+ public function get_name()
111
+ {
112
+ if ($this->name !== null)
113
+ {
114
+ return $this->name;
115
+ }
116
+ else
117
+ {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Author's link
124
+ *
125
+ * @return string|null
126
+ */
127
+ public function get_link()
128
+ {
129
+ if ($this->link !== null)
130
+ {
131
+ return $this->link;
132
+ }
133
+ else
134
+ {
135
+ return null;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Author's email address
141
+ *
142
+ * @return string|null
143
+ */
144
+ public function get_email()
145
+ {
146
+ if ($this->email !== null)
147
+ {
148
+ return $this->email;
149
+ }
150
+ else
151
+ {
152
+ return null;
153
+ }
154
+ }
155
+ }
156
+
libs/SimpleCluvPie/library/SimpleCluvPie/Cache.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Used to create cache objects
46
+ *
47
+ * This class can be overloaded with {@see SimpleCluvPie::set_cache_class()},
48
+ * although the preferred way is to create your own handler
49
+ * via {@see register()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage Caching
53
+ */
54
+ class SimpleCluvPie_Cache
55
+ {
56
+ /**
57
+ * Cache handler classes
58
+ *
59
+ * These receive 3 parameters to their constructor, as documented in
60
+ * {@see register()}
61
+ * @var array
62
+ */
63
+ protected static $handlers = array(
64
+ 'mysql' => 'SimpleCluvPie_Cache_MySQL',
65
+ 'memcache' => 'SimpleCluvPie_Cache_Memcache',
66
+ 'memcached' => 'SimpleCluvPie_Cache_Memcached',
67
+ 'redis' => 'SimpleCluvPie_Cache_Redis'
68
+ );
69
+
70
+ /**
71
+ * Don't call the constructor. Please.
72
+ */
73
+ private function __construct() { }
74
+
75
+ /**
76
+ * Create a new SimpleCluvPie_Cache object
77
+ *
78
+ * @param string $location URL location (scheme is used to determine handler)
79
+ * @param string $filename Unique identifier for cache object
80
+ * @param string $extension 'spi' or 'spc'
81
+ * @return SimpleCluvPie_Cache_Base Type of object depends on scheme of `$location`
82
+ */
83
+ public static function get_handler($location, $filename, $extension)
84
+ {
85
+ $type = explode(':', $location, 2);
86
+ $type = $type[0];
87
+ if (!empty(self::$handlers[$type]))
88
+ {
89
+ $class = self::$handlers[$type];
90
+ return new $class($location, $filename, $extension);
91
+ }
92
+
93
+ return new SimpleCluvPie_Cache_File($location, $filename, $extension);
94
+ }
95
+
96
+ /**
97
+ * Create a new SimpleCluvPie_Cache object
98
+ *
99
+ * @deprecated Use {@see get_handler} instead
100
+ */
101
+ public function create($location, $filename, $extension)
102
+ {
103
+ trigger_error('Cache::create() has been replaced with Cache::get_handler(). Switch to the registry system to use this.', E_USER_DEPRECATED);
104
+ return self::get_handler($location, $filename, $extension);
105
+ }
106
+
107
+ /**
108
+ * Register a handler
109
+ *
110
+ * @param string $type DSN type to register for
111
+ * @param string $class Name of handler class. Must implement SimpleCluvPie_Cache_Base
112
+ */
113
+ public static function register($type, $class)
114
+ {
115
+ self::$handlers[$type] = $class;
116
+ }
117
+
118
+ /**
119
+ * Parse a URL into an array
120
+ *
121
+ * @param string $url
122
+ * @return array
123
+ */
124
+ public static function parse_URL($url)
125
+ {
126
+ $params = parse_url($url);
127
+ $params['extras'] = array();
128
+ if (isset($params['query']))
129
+ {
130
+ parse_str($params['query'], $params['extras']);
131
+ }
132
+ return $params;
133
+ }
134
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Base.php ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Base for cache objects
46
+ *
47
+ * Classes to be used with {@see SimpleCluvPie_Cache::register()} are expected
48
+ * to implement this interface.
49
+ *
50
+ * @package SimpleCluvPie
51
+ * @subpackage Caching
52
+ */
53
+ interface SimpleCluvPie_Cache_Base
54
+ {
55
+ /**
56
+ * Feed cache type
57
+ *
58
+ * @var string
59
+ */
60
+ const TYPE_FEED = 'spc';
61
+
62
+ /**
63
+ * Image cache type
64
+ *
65
+ * @var string
66
+ */
67
+ const TYPE_IMAGE = 'spi';
68
+
69
+ /**
70
+ * Create a new cache object
71
+ *
72
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
73
+ * @param string $name Unique ID for the cache
74
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
75
+ */
76
+ public function __construct($location, $name, $type);
77
+
78
+ /**
79
+ * Save data to the cache
80
+ *
81
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
82
+ * @return bool Successfulness
83
+ */
84
+ public function save($data);
85
+
86
+ /**
87
+ * Retrieve the data saved to the cache
88
+ *
89
+ * @return array Data for SimpleCluvPie::$data
90
+ */
91
+ public function load();
92
+
93
+ /**
94
+ * Retrieve the last modified time for the cache
95
+ *
96
+ * @return int Timestamp
97
+ */
98
+ public function mtime();
99
+
100
+ /**
101
+ * Set the last modified time to the current time
102
+ *
103
+ * @return bool Success status
104
+ */
105
+ public function touch();
106
+
107
+ /**
108
+ * Remove the cache
109
+ *
110
+ * @return bool Success status
111
+ */
112
+ public function unlink();
113
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/DB.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Base class for database-based caches
46
+ *
47
+ * @package SimpleCluvPie
48
+ * @subpackage Caching
49
+ */
50
+ abstract class SimpleCluvPie_Cache_DB implements SimpleCluvPie_Cache_Base
51
+ {
52
+ /**
53
+ * Helper for database conversion
54
+ *
55
+ * Converts a given {@see SimpleCluvPie} object into data to be stored
56
+ *
57
+ * @param SimpleCluvPie $data
58
+ * @return array First item is the serialized data for storage, second item is the unique ID for this item
59
+ */
60
+ protected static function prepare_simplecluvpie_object_for_cache($data)
61
+ {
62
+ $items = $data->get_items();
63
+ $items_by_id = array();
64
+
65
+ if (!empty($items))
66
+ {
67
+ foreach ($items as $item)
68
+ {
69
+ $items_by_id[$item->get_id()] = $item;
70
+ }
71
+
72
+ if (count($items_by_id) !== count($items))
73
+ {
74
+ $items_by_id = array();
75
+ foreach ($items as $item)
76
+ {
77
+ $items_by_id[$item->get_id(true)] = $item;
78
+ }
79
+ }
80
+
81
+ if (isset($data->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]))
82
+ {
83
+ $channel =& $data->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0];
84
+ }
85
+ elseif (isset($data->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]))
86
+ {
87
+ $channel =& $data->data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0];
88
+ }
89
+ elseif (isset($data->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]))
90
+ {
91
+ $channel =& $data->data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0];
92
+ }
93
+ elseif (isset($data->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['channel'][0]))
94
+ {
95
+ $channel =& $data->data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['channel'][0];
96
+ }
97
+ else
98
+ {
99
+ $channel = null;
100
+ }
101
+
102
+ if ($channel !== null)
103
+ {
104
+ if (isset($channel['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['entry']))
105
+ {
106
+ unset($channel['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['entry']);
107
+ }
108
+ if (isset($channel['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['entry']))
109
+ {
110
+ unset($channel['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['entry']);
111
+ }
112
+ if (isset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['item']))
113
+ {
114
+ unset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_10]['item']);
115
+ }
116
+ if (isset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['item']))
117
+ {
118
+ unset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_090]['item']);
119
+ }
120
+ if (isset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['item']))
121
+ {
122
+ unset($channel['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['item']);
123
+ }
124
+ }
125
+ if (isset($data->data['items']))
126
+ {
127
+ unset($data->data['items']);
128
+ }
129
+ if (isset($data->data['ordered_items']))
130
+ {
131
+ unset($data->data['ordered_items']);
132
+ }
133
+ }
134
+ return array(serialize($data->data), $items_by_id);
135
+ }
136
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/File.php ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Caches data to the filesystem
46
+ *
47
+ * @package SimpleCluvPie
48
+ * @subpackage Caching
49
+ */
50
+ class SimpleCluvPie_Cache_File implements SimpleCluvPie_Cache_Base
51
+ {
52
+ /**
53
+ * Location string
54
+ *
55
+ * @see SimpleCluvPie::$cache_location
56
+ * @var string
57
+ */
58
+ protected $location;
59
+
60
+ /**
61
+ * Filename
62
+ *
63
+ * @var string
64
+ */
65
+ protected $filename;
66
+
67
+ /**
68
+ * File extension
69
+ *
70
+ * @var string
71
+ */
72
+ protected $extension;
73
+
74
+ /**
75
+ * File path
76
+ *
77
+ * @var string
78
+ */
79
+ protected $name;
80
+
81
+ /**
82
+ * Create a new cache object
83
+ *
84
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
85
+ * @param string $name Unique ID for the cache
86
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
87
+ */
88
+ public function __construct($location, $name, $type)
89
+ {
90
+ $this->location = $location;
91
+ $this->filename = $name;
92
+ $this->extension = $type;
93
+ $this->name = "$this->location/$this->filename.$this->extension";
94
+ }
95
+
96
+ /**
97
+ * Save data to the cache
98
+ *
99
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
100
+ * @return bool Successfulness
101
+ */
102
+ public function save($data)
103
+ {
104
+ if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
105
+ {
106
+ if ($data instanceof SimpleCluvPie)
107
+ {
108
+ $data = $data->data;
109
+ }
110
+
111
+ $data = serialize($data);
112
+ return (bool) file_put_contents($this->name, $data);
113
+ }
114
+ return false;
115
+ }
116
+
117
+ /**
118
+ * Retrieve the data saved to the cache
119
+ *
120
+ * @return array Data for SimpleCluvPie::$data
121
+ */
122
+ public function load()
123
+ {
124
+ if (file_exists($this->name) && is_readable($this->name))
125
+ {
126
+ return unserialize(file_get_contents($this->name));
127
+ }
128
+ return false;
129
+ }
130
+
131
+ /**
132
+ * Retrieve the last modified time for the cache
133
+ *
134
+ * @return int Timestamp
135
+ */
136
+ public function mtime()
137
+ {
138
+ return @filemtime($this->name);
139
+ }
140
+
141
+ /**
142
+ * Set the last modified time to the current time
143
+ *
144
+ * @return bool Success status
145
+ */
146
+ public function touch()
147
+ {
148
+ return @touch($this->name);
149
+ }
150
+
151
+ /**
152
+ * Remove the cache
153
+ *
154
+ * @return bool Success status
155
+ */
156
+ public function unlink()
157
+ {
158
+ if (file_exists($this->name))
159
+ {
160
+ return unlink($this->name);
161
+ }
162
+ return false;
163
+ }
164
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Memcache.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Caches data to memcache
46
+ *
47
+ * Registered for URLs with the "memcache" protocol
48
+ *
49
+ * For example, `memcache://localhost:11211/?timeout=3600&prefix=sp_` will
50
+ * connect to memcache on `localhost` on port 11211. All tables will be
51
+ * prefixed with `sp_` and data will expire after 3600 seconds
52
+ *
53
+ * @package SimpleCluvPie
54
+ * @subpackage Caching
55
+ * @uses Memcache
56
+ */
57
+ class SimpleCluvPie_Cache_Memcache implements SimpleCluvPie_Cache_Base
58
+ {
59
+ /**
60
+ * Memcache instance
61
+ *
62
+ * @var Memcache
63
+ */
64
+ protected $cache;
65
+
66
+ /**
67
+ * Options
68
+ *
69
+ * @var array
70
+ */
71
+ protected $options;
72
+
73
+ /**
74
+ * Cache name
75
+ *
76
+ * @var string
77
+ */
78
+ protected $name;
79
+
80
+ /**
81
+ * Create a new cache object
82
+ *
83
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
84
+ * @param string $name Unique ID for the cache
85
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
86
+ */
87
+ public function __construct($location, $name, $type)
88
+ {
89
+ $this->options = array(
90
+ 'host' => '127.0.0.1',
91
+ 'port' => 11211,
92
+ 'extras' => array(
93
+ 'timeout' => 3600, // one hour
94
+ 'prefix' => 'simplecluvpie_',
95
+ ),
96
+ );
97
+ $this->options = SimpleCluvPie_Misc::array_merge_recursive($this->options, SimpleCluvPie_Cache::parse_URL($location));
98
+
99
+ $this->name = $this->options['extras']['prefix'] . md5("$name:$type");
100
+
101
+ $this->cache = new Memcache();
102
+ $this->cache->addServer($this->options['host'], (int) $this->options['port']);
103
+ }
104
+
105
+ /**
106
+ * Save data to the cache
107
+ *
108
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
109
+ * @return bool Successfulness
110
+ */
111
+ public function save($data)
112
+ {
113
+ if ($data instanceof SimpleCluvPie)
114
+ {
115
+ $data = $data->data;
116
+ }
117
+ return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
118
+ }
119
+
120
+ /**
121
+ * Retrieve the data saved to the cache
122
+ *
123
+ * @return array Data for SimpleCluvPie::$data
124
+ */
125
+ public function load()
126
+ {
127
+ $data = $this->cache->get($this->name);
128
+
129
+ if ($data !== false)
130
+ {
131
+ return unserialize($data);
132
+ }
133
+ return false;
134
+ }
135
+
136
+ /**
137
+ * Retrieve the last modified time for the cache
138
+ *
139
+ * @return int Timestamp
140
+ */
141
+ public function mtime()
142
+ {
143
+ $data = $this->cache->get($this->name);
144
+
145
+ if ($data !== false)
146
+ {
147
+ // essentially ignore the mtime because Memcache expires on its own
148
+ return time();
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+ /**
155
+ * Set the last modified time to the current time
156
+ *
157
+ * @return bool Success status
158
+ */
159
+ public function touch()
160
+ {
161
+ $data = $this->cache->get($this->name);
162
+
163
+ if ($data !== false)
164
+ {
165
+ return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
166
+ }
167
+
168
+ return false;
169
+ }
170
+
171
+ /**
172
+ * Remove the cache
173
+ *
174
+ * @return bool Success status
175
+ */
176
+ public function unlink()
177
+ {
178
+ return $this->cache->delete($this->name, 0);
179
+ }
180
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Memcached.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Caches data to memcached
46
+ *
47
+ * Registered for URLs with the "memcached" protocol
48
+ *
49
+ * For example, `memcached://localhost:11211/?timeout=3600&prefix=sp_` will
50
+ * connect to memcached on `localhost` on port 11211. All tables will be
51
+ * prefixed with `sp_` and data will expire after 3600 seconds
52
+ *
53
+ * @package SimpleCluvPie
54
+ * @subpackage Caching
55
+ * @author Paul L. McNeely
56
+ * @uses Memcached
57
+ */
58
+ class SimpleCluvPie_Cache_Memcached implements SimpleCluvPie_Cache_Base
59
+ {
60
+ /**
61
+ * Memcached instance
62
+ * @var Memcached
63
+ */
64
+ protected $cache;
65
+
66
+ /**
67
+ * Options
68
+ * @var array
69
+ */
70
+ protected $options;
71
+
72
+ /**
73
+ * Cache name
74
+ * @var string
75
+ */
76
+ protected $name;
77
+
78
+ /**
79
+ * Create a new cache object
80
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
81
+ * @param string $name Unique ID for the cache
82
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
83
+ */
84
+ public function __construct($location, $name, $type) {
85
+ $this->options = array(
86
+ 'host' => '127.0.0.1',
87
+ 'port' => 11211,
88
+ 'extras' => array(
89
+ 'timeout' => 3600, // one hour
90
+ 'prefix' => 'simplecluvpie_',
91
+ ),
92
+ );
93
+ $this->options = SimpleCluvPie_Misc::array_merge_recursive($this->options, SimpleCluvPie_Cache::parse_URL($location));
94
+
95
+ $this->name = $this->options['extras']['prefix'] . md5("$name:$type");
96
+
97
+ $this->cache = new Memcached();
98
+ $this->cache->addServer($this->options['host'], (int)$this->options['port']);
99
+ }
100
+
101
+ /**
102
+ * Save data to the cache
103
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
104
+ * @return bool Successfulness
105
+ */
106
+ public function save($data) {
107
+ if ($data instanceof SimpleCluvPie) {
108
+ $data = $data->data;
109
+ }
110
+
111
+ return $this->setData(serialize($data));
112
+ }
113
+
114
+ /**
115
+ * Retrieve the data saved to the cache
116
+ * @return array Data for SimpleCluvPie::$data
117
+ */
118
+ public function load() {
119
+ $data = $this->cache->get($this->name);
120
+
121
+ if ($data !== false) {
122
+ return unserialize($data);
123
+ }
124
+ return false;
125
+ }
126
+
127
+ /**
128
+ * Retrieve the last modified time for the cache
129
+ * @return int Timestamp
130
+ */
131
+ public function mtime() {
132
+ $data = $this->cache->get($this->name . '_mtime');
133
+ return (int) $data;
134
+ }
135
+
136
+ /**
137
+ * Set the last modified time to the current time
138
+ * @return bool Success status
139
+ */
140
+ public function touch() {
141
+ $data = $this->cache->get($this->name);
142
+ return $this->setData($data);
143
+ }
144
+
145
+ /**
146
+ * Remove the cache
147
+ * @return bool Success status
148
+ */
149
+ public function unlink() {
150
+ return $this->cache->delete($this->name, 0);
151
+ }
152
+
153
+ /**
154
+ * Set the last modified time and data to Memcached
155
+ * @return bool Success status
156
+ */
157
+ private function setData($data) {
158
+
159
+ if ($data !== false) {
160
+ $this->cache->set($this->name . '_mtime', time(), (int)$this->options['extras']['timeout']);
161
+ return $this->cache->set($this->name, $data, (int)$this->options['extras']['timeout']);
162
+ }
163
+
164
+ return false;
165
+ }
166
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/MySQL.php ADDED
@@ -0,0 +1,454 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Caches data to a MySQL database
46
+ *
47
+ * Registered for URLs with the "mysql" protocol
48
+ *
49
+ * For example, `mysql://root:password@localhost:3306/mydb?prefix=sp_` will
50
+ * connect to the `mydb` database on `localhost` on port 3306, with the user
51
+ * `root` and the password `password`. All tables will be prefixed with `sp_`
52
+ *
53
+ * @package SimpleCluvPie
54
+ * @subpackage Caching
55
+ */
56
+ class SimpleCluvPie_Cache_MySQL extends SimpleCluvPie_Cache_DB
57
+ {
58
+ /**
59
+ * PDO instance
60
+ *
61
+ * @var PDO
62
+ */
63
+ protected $mysql;
64
+
65
+ /**
66
+ * Options
67
+ *
68
+ * @var array
69
+ */
70
+ protected $options;
71
+
72
+ /**
73
+ * Cache ID
74
+ *
75
+ * @var string
76
+ */
77
+ protected $id;
78
+
79
+ /**
80
+ * Create a new cache object
81
+ *
82
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
83
+ * @param string $name Unique ID for the cache
84
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
85
+ */
86
+ public function __construct($location, $name, $type)
87
+ {
88
+ $this->options = array(
89
+ 'user' => null,
90
+ 'pass' => null,
91
+ 'host' => '127.0.0.1',
92
+ 'port' => '3306',
93
+ 'path' => '',
94
+ 'extras' => array(
95
+ 'prefix' => '',
96
+ 'cache_purge_time' => 2592000
97
+ ),
98
+ );
99
+
100
+ $this->options = SimpleCluvPie_Misc::array_merge_recursive($this->options, SimpleCluvPie_Cache::parse_URL($location));
101
+
102
+ // Path is prefixed with a "/"
103
+ $this->options['dbname'] = substr($this->options['path'], 1);
104
+
105
+ try
106
+ {
107
+ $this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
108
+ }
109
+ catch (PDOException $e)
110
+ {
111
+ $this->mysql = null;
112
+ return;
113
+ }
114
+
115
+ $this->id = $name . $type;
116
+
117
+ if (!$query = $this->mysql->query('SHOW TABLES'))
118
+ {
119
+ $this->mysql = null;
120
+ return;
121
+ }
122
+
123
+ $db = array();
124
+ while ($row = $query->fetchColumn())
125
+ {
126
+ $db[] = $row;
127
+ }
128
+
129
+ if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))
130
+ {
131
+ $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');
132
+ if ($query === false)
133
+ {
134
+ trigger_error("Can't create " . $this->options['extras']['prefix'] . "cache_data table, check permissions", E_USER_WARNING);
135
+ $this->mysql = null;
136
+ return;
137
+ }
138
+ }
139
+
140
+ if (!in_array($this->options['extras']['prefix'] . 'items', $db))
141
+ {
142
+ $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` MEDIUMBLOB NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');
143
+ if ($query === false)
144
+ {
145
+ trigger_error("Can't create " . $this->options['extras']['prefix'] . "items table, check permissions", E_USER_WARNING);
146
+ $this->mysql = null;
147
+ return;
148
+ }
149
+ }
150
+ }
151
+
152
+ /**
153
+ * Save data to the cache
154
+ *
155
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
156
+ * @return bool Successfulness
157
+ */
158
+ public function save($data)
159
+ {
160
+ if ($this->mysql === null)
161
+ {
162
+ return false;
163
+ }
164
+
165
+ $query = $this->mysql->prepare('DELETE i, cd FROM `' . $this->options['extras']['prefix'] . 'cache_data` cd, ' .
166
+ '`' . $this->options['extras']['prefix'] . 'items` i ' .
167
+ 'WHERE cd.id = i.feed_id ' .
168
+ 'AND cd.mtime < (unix_timestamp() - :purge_time)');
169
+ $query->bindValue(':purge_time', $this->options['extras']['cache_purge_time']);
170
+
171
+ if (!$query->execute())
172
+ {
173
+ return false;
174
+ }
175
+
176
+ if ($data instanceof SimpleCluvPie)
177
+ {
178
+ $data = clone $data;
179
+
180
+ $prepared = self::prepare_simplecluvpie_object_for_cache($data);
181
+
182
+ $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
183
+ $query->bindValue(':feed', $this->id);
184
+ if ($query->execute())
185
+ {
186
+ if ($query->fetchColumn() > 0)
187
+ {
188
+ $items = count($prepared[1]);
189
+ if ($items)
190
+ {
191
+ $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
192
+ $query = $this->mysql->prepare($sql);
193
+ $query->bindValue(':items', $items);
194
+ }
195
+ else
196
+ {
197
+ $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
198
+ $query = $this->mysql->prepare($sql);
199
+ }
200
+
201
+ $query->bindValue(':data', $prepared[0]);
202
+ $query->bindValue(':time', time());
203
+ $query->bindValue(':feed', $this->id);
204
+ if (!$query->execute())
205
+ {
206
+ return false;
207
+ }
208
+ }
209
+ else
210
+ {
211
+ $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
212
+ $query->bindValue(':feed', $this->id);
213
+ $query->bindValue(':count', count($prepared[1]));
214
+ $query->bindValue(':data', $prepared[0]);
215
+ $query->bindValue(':time', time());
216
+ if (!$query->execute())
217
+ {
218
+ return false;
219
+ }
220
+ }
221
+
222
+ $ids = array_keys($prepared[1]);
223
+ if (!empty($ids))
224
+ {
225
+ foreach ($ids as $id)
226
+ {
227
+ $database_ids[] = $this->mysql->quote($id);
228
+ }
229
+
230
+ $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
231
+ $query->bindValue(':feed', $this->id);
232
+
233
+ if ($query->execute())
234
+ {
235
+ $existing_ids = array();
236
+ while ($row = $query->fetchColumn())
237
+ {
238
+ $existing_ids[] = $row;
239
+ }
240
+
241
+ $new_ids = array_diff($ids, $existing_ids);
242
+
243
+ foreach ($new_ids as $new_id)
244
+ {
245
+ if (!($date = $prepared[1][$new_id]->get_date('U')))
246
+ {
247
+ $date = time();
248
+ }
249
+
250
+ $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
251
+ $query->bindValue(':feed', $this->id);
252
+ $query->bindValue(':id', $new_id);
253
+ $query->bindValue(':data', serialize($prepared[1][$new_id]->data));
254
+ $query->bindValue(':date', $date);
255
+ if (!$query->execute())
256
+ {
257
+ return false;
258
+ }
259
+ }
260
+ return true;
261
+ }
262
+ }
263
+ else
264
+ {
265
+ return true;
266
+ }
267
+ }
268
+ }
269
+ else
270
+ {
271
+ $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
272
+ $query->bindValue(':feed', $this->id);
273
+ if ($query->execute())
274
+ {
275
+ if ($query->rowCount() > 0)
276
+ {
277
+ $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
278
+ $query->bindValue(':data', serialize($data));
279
+ $query->bindValue(':time', time());
280
+ $query->bindValue(':feed', $this->id);
281
+ if ($this->execute())
282
+ {
283
+ return true;
284
+ }
285
+ }
286
+ else
287
+ {
288
+ $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
289
+ $query->bindValue(':id', $this->id);
290
+ $query->bindValue(':data', serialize($data));
291
+ $query->bindValue(':time', time());
292
+ if ($query->execute())
293
+ {
294
+ return true;
295
+ }
296
+ }
297
+ }
298
+ }
299
+ return false;
300
+ }
301
+
302
+ /**
303
+ * Retrieve the data saved to the cache
304
+ *
305
+ * @return array Data for SimpleCluvPie::$data
306
+ */
307
+ public function load()
308
+ {
309
+ if ($this->mysql === null)
310
+ {
311
+ return false;
312
+ }
313
+
314
+ $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
315
+ $query->bindValue(':id', $this->id);
316
+ if ($query->execute() && ($row = $query->fetch()))
317
+ {
318
+ $data = unserialize($row[1]);
319
+
320
+ if (isset($this->options['items'][0]))
321
+ {
322
+ $items = (int) $this->options['items'][0];
323
+ }
324
+ else
325
+ {
326
+ $items = (int) $row[0];
327
+ }
328
+
329
+ if ($items !== 0)
330
+ {
331
+ if (isset($data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0]))
332
+ {
333
+ $feed =& $data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['feed'][0];
334
+ }
335
+ elseif (isset($data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0]))
336
+ {
337
+ $feed =& $data['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['feed'][0];
338
+ }
339
+ elseif (isset($data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0]))
340
+ {
341
+ $feed =& $data['child'][SIMPLECLUVPIE_NAMESPACE_RDF]['RDF'][0];
342
+ }
343
+ elseif (isset($data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0]))
344
+ {
345
+ $feed =& $data['child'][SIMPLECLUVPIE_NAMESPACE_RSS_20]['rss'][0];
346
+ }
347
+ else
348
+ {
349
+ $feed = null;
350
+ }
351
+
352
+ if ($feed !== null)
353
+ {
354
+ $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
355
+ if ($items > 0)
356
+ {
357
+ $sql .= ' LIMIT ' . $items;
358
+ }
359
+
360
+ $query = $this->mysql->prepare($sql);
361
+ $query->bindValue(':feed', $this->id);
362
+ if ($query->execute())
363
+ {
364
+ while ($row = $query->fetchColumn())
365
+ {
366
+ $feed['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);
367
+ }
368
+ }
369
+ else
370
+ {
371
+ return false;
372
+ }
373
+ }
374
+ }
375
+ return $data;
376
+ }
377
+ return false;
378
+ }
379
+
380
+ /**
381
+ * Retrieve the last modified time for the cache
382
+ *
383
+ * @return int Timestamp
384
+ */
385
+ public function mtime()
386
+ {
387
+ if ($this->mysql === null)
388
+ {
389
+ return false;
390
+ }
391
+
392
+ $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
393
+ $query->bindValue(':id', $this->id);
394
+ if ($query->execute() && ($time = $query->fetchColumn()))
395
+ {
396
+ return $time;
397
+ }
398
+ else
399
+ {
400
+ return false;
401
+ }
402
+ }
403
+
404
+ /**
405
+ * Set the last modified time to the current time
406
+ *
407
+ * @return bool Success status
408
+ */
409
+ public function touch()
410
+ {
411
+ if ($this->mysql === null)
412
+ {
413
+ return false;
414
+ }
415
+
416
+ $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
417
+ $query->bindValue(':time', time());
418
+ $query->bindValue(':id', $this->id);
419
+ if ($query->execute() && $query->rowCount() > 0)
420
+ {
421
+ return true;
422
+ }
423
+ else
424
+ {
425
+ return false;
426
+ }
427
+ }
428
+
429
+ /**
430
+ * Remove the cache
431
+ *
432
+ * @return bool Success status
433
+ */
434
+ public function unlink()
435
+ {
436
+ if ($this->mysql === null)
437
+ {
438
+ return false;
439
+ }
440
+
441
+ $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
442
+ $query->bindValue(':id', $this->id);
443
+ $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
444
+ $query2->bindValue(':id', $this->id);
445
+ if ($query->execute() && $query2->execute())
446
+ {
447
+ return true;
448
+ }
449
+ else
450
+ {
451
+ return false;
452
+ }
453
+ }
454
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Cache/Redis.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * SimpleCluvPie Redis Cache Extension
5
+ *
6
+ * @package SimpleCluvPie
7
+ * @author Jan Kozak <galvani78@gmail.com>
8
+ * @link http://galvani.cz/
9
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
10
+ * @version 0.2.9
11
+ */
12
+
13
+
14
+ /**
15
+ * Caches data to redis
16
+ *
17
+ * Registered for URLs with the "redis" protocol
18
+ *
19
+ * For example, `redis://localhost:6379/?timeout=3600&prefix=sp_&dbIndex=0` will
20
+ * connect to redis on `localhost` on port 6379. All tables will be
21
+ * prefixed with `simple_primary-` and data will expire after 3600 seconds
22
+ *
23
+ * @package SimpleCluvPie
24
+ * @subpackage Caching
25
+ * @uses Redis
26
+ */
27
+ class SimpleCluvPie_Cache_Redis implements SimpleCluvPie_Cache_Base {
28
+ /**
29
+ * Redis instance
30
+ *
31
+ * @var \Redis
32
+ */
33
+ protected $cache;
34
+
35
+ /**
36
+ * Options
37
+ *
38
+ * @var array
39
+ */
40
+ protected $options;
41
+
42
+ /**
43
+ * Cache name
44
+ *
45
+ * @var string
46
+ */
47
+ protected $name;
48
+
49
+ /**
50
+ * Cache Data
51
+ *
52
+ * @var type
53
+ */
54
+ protected $data;
55
+
56
+ /**
57
+ * Create a new cache object
58
+ *
59
+ * @param string $location Location string (from SimpleCluvPie::$cache_location)
60
+ * @param string $name Unique ID for the cache
61
+ * @param string $type Either TYPE_FEED for SimpleCluvPie data, or TYPE_IMAGE for image data
62
+ */
63
+ public function __construct($location, $name, $options = null) {
64
+ //$this->cache = \flow\simple\cache\Redis::getRedisClientInstance();
65
+ $parsed = SimpleCluvPie_Cache::parse_URL($location);
66
+ $redis = new Redis();
67
+ $redis->connect($parsed['host'], $parsed['port']);
68
+ $this->cache = $redis;
69
+
70
+ if (!is_null($options) && is_array($options)) {
71
+ $this->options = $options;
72
+ } else {
73
+ $this->options = array (
74
+ 'prefix' => 'rss:simple_primary:',
75
+ 'expire' => 0,
76
+ );
77
+ }
78
+
79
+ $this->name = $this->options['prefix'] . $name;
80
+ }
81
+
82
+ /**
83
+ * @param \Redis $cache
84
+ */
85
+ public function setRedisClient(\Redis $cache) {
86
+ $this->cache = $cache;
87
+ }
88
+
89
+ /**
90
+ * Save data to the cache
91
+ *
92
+ * @param array|SimpleCluvPie $data Data to store in the cache. If passed a SimpleCluvPie object, only cache the $data property
93
+ * @return bool Successfulness
94
+ */
95
+ public function save($data) {
96
+ if ($data instanceof SimpleCluvPie) {
97
+ $data = $data->data;
98
+ }
99
+ $response = $this->cache->set($this->name, serialize($data));
100
+ if ($this->options['expire']) {
101
+ $this->cache->expire($this->name, $this->options['expire']);
102
+ }
103
+
104
+ return $response;
105
+ }
106
+
107
+ /**
108
+ * Retrieve the data saved to the cache
109
+ *
110
+ * @return array Data for SimpleCluvPie::$data
111
+ */
112
+ public function load() {
113
+ $data = $this->cache->get($this->name);
114
+
115
+ if ($data !== false) {
116
+ return unserialize($data);
117
+ }
118
+ return false;
119
+ }
120
+
121
+ /**
122
+ * Retrieve the last modified time for the cache
123
+ *
124
+ * @return int Timestamp
125
+ */
126
+ public function mtime() {
127
+
128
+ $data = $this->cache->get($this->name);
129
+
130
+ if ($data !== false) {
131
+ return time();
132
+ }
133
+
134
+ return false;
135
+ }
136
+
137
+ /**
138
+ * Set the last modified time to the current time
139
+ *
140
+ * @return bool Success status
141
+ */
142
+ public function touch() {
143
+
144
+ $data = $this->cache->get($this->name);
145
+
146
+ if ($data !== false) {
147
+ $return = $this->cache->set($this->name, $data);
148
+ if ($this->options['expire']) {
149
+ return $this->cache->expire($this->name, $this->ttl);
150
+ }
151
+ return $return;
152
+ }
153
+
154
+ return false;
155
+ }
156
+
157
+ /**
158
+ * Remove the cache
159
+ *
160
+ * @return bool Success status
161
+ */
162
+ public function unlink() {
163
+ return $this->cache->set($this->name, null);
164
+ }
165
+
166
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Caption.php ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Handles `<media:text>` captions as defined in Media RSS.
47
+ *
48
+ * Used by {@see SimpleCluvPie_Enclosure::get_caption()} and {@see SimpleCluvPie_Enclosure::get_captions()}
49
+ *
50
+ * This class can be overloaded with {@see SimpleCluvPie::set_caption_class()}
51
+ *
52
+ * @package SimpleCluvPie
53
+ * @subpackage API
54
+ */
55
+ class SimpleCluvPie_Caption
56
+ {
57
+ /**
58
+ * Content type
59
+ *
60
+ * @var string
61
+ * @see get_type()
62
+ */
63
+ var $type;
64
+
65
+ /**
66
+ * Language
67
+ *
68
+ * @var string
69
+ * @see get_language()
70
+ */
71
+ var $lang;
72
+
73
+ /**
74
+ * Start time
75
+ *
76
+ * @var string
77
+ * @see get_starttime()
78
+ */
79
+ var $startTime;
80
+
81
+ /**
82
+ * End time
83
+ *
84
+ * @var string
85
+ * @see get_endtime()
86
+ */
87
+ var $endTime;
88
+
89
+ /**
90
+ * Caption text
91
+ *
92
+ * @var string
93
+ * @see get_text()
94
+ */
95
+ var $text;
96
+
97
+ /**
98
+ * Constructor, used to input the data
99
+ *
100
+ * For documentation on all the parameters, see the corresponding
101
+ * properties and their accessors
102
+ */
103
+ public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
104
+ {
105
+ $this->type = $type;
106
+ $this->lang = $lang;
107
+ $this->startTime = $startTime;
108
+ $this->endTime = $endTime;
109
+ $this->text = $text;
110
+ }
111
+
112
+ /**
113
+ * String-ified version
114
+ *
115
+ * @return string
116
+ */
117
+ public function __toString()
118
+ {
119
+ // There is no $this->data here
120
+ return md5(serialize($this));
121
+ }
122
+
123
+ /**
124
+ * Get the end time
125
+ *
126
+ * @return string|null Time in the format 'hh:mm:ss.SSS'
127
+ */
128
+ public function get_endtime()
129
+ {
130
+ if ($this->endTime !== null)
131
+ {
132
+ return $this->endTime;
133
+ }
134
+ else
135
+ {
136
+ return null;
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Get the language
142
+ *
143
+ * @link http://tools.ietf.org/html/rfc3066
144
+ * @return string|null Language code as per RFC 3066
145
+ */
146
+ public function get_language()
147
+ {
148
+ if ($this->lang !== null)
149
+ {
150
+ return $this->lang;
151
+ }
152
+ else
153
+ {
154
+ return null;
155
+ }
156
+ }
157
+
158
+ /**
159
+ * Get the start time
160
+ *
161
+ * @return string|null Time in the format 'hh:mm:ss.SSS'
162
+ */
163
+ public function get_starttime()
164
+ {
165
+ if ($this->startTime !== null)
166
+ {
167
+ return $this->startTime;
168
+ }
169
+ else
170
+ {
171
+ return null;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Get the text of the caption
177
+ *
178
+ * @return string|null
179
+ */
180
+ public function get_text()
181
+ {
182
+ if ($this->text !== null)
183
+ {
184
+ return $this->text;
185
+ }
186
+ else
187
+ {
188
+ return null;
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Get the content type (not MIME type)
194
+ *
195
+ * @return string|null Either 'text' or 'html'
196
+ */
197
+ public function get_type()
198
+ {
199
+ if ($this->type !== null)
200
+ {
201
+ return $this->type;
202
+ }
203
+ else
204
+ {
205
+ return null;
206
+ }
207
+ }
208
+ }
209
+
libs/SimpleCluvPie/library/SimpleCluvPie/Category.php ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Manages all category-related data
46
+ *
47
+ * Used by {@see SimpleCluvPie_Item::get_category()} and {@see SimpleCluvPie_Item::get_categories()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_category_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Category
55
+ {
56
+ /**
57
+ * Category identifier
58
+ *
59
+ * @var string
60
+ * @see get_term
61
+ */
62
+ var $term;
63
+
64
+ /**
65
+ * Categorization scheme identifier
66
+ *
67
+ * @var string
68
+ * @see get_scheme()
69
+ */
70
+ var $scheme;
71
+
72
+ /**
73
+ * Human readable label
74
+ *
75
+ * @var string
76
+ * @see get_label()
77
+ */
78
+ var $label;
79
+
80
+ /**
81
+ * Constructor, used to input the data
82
+ *
83
+ * @param string $term
84
+ * @param string $scheme
85
+ * @param string $label
86
+ */
87
+ public function __construct($term = null, $scheme = null, $label = null)
88
+ {
89
+ $this->term = $term;
90
+ $this->scheme = $scheme;
91
+ $this->label = $label;
92
+ }
93
+
94
+ /**
95
+ * String-ified version
96
+ *
97
+ * @return string
98
+ */
99
+ public function __toString()
100
+ {
101
+ // There is no $this->data here
102
+ return md5(serialize($this));
103
+ }
104
+
105
+ /**
106
+ * Get the category identifier
107
+ *
108
+ * @return string|null
109
+ */
110
+ public function get_term()
111
+ {
112
+ if ($this->term !== null)
113
+ {
114
+ return $this->term;
115
+ }
116
+ else
117
+ {
118
+ return null;
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Get the categorization scheme identifier
124
+ *
125
+ * @return string|null
126
+ */
127
+ public function get_scheme()
128
+ {
129
+ if ($this->scheme !== null)
130
+ {
131
+ return $this->scheme;
132
+ }
133
+ else
134
+ {
135
+ return null;
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Get the human readable label
141
+ *
142
+ * @return string|null
143
+ */
144
+ public function get_label()
145
+ {
146
+ if ($this->label !== null)
147
+ {
148
+ return $this->label;
149
+ }
150
+ else
151
+ {
152
+ return $this->get_term();
153
+ }
154
+ }
155
+ }
156
+
libs/SimpleCluvPie/library/SimpleCluvPie/Content/Type/Sniffer.php ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Content-type sniffing
47
+ *
48
+ * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06
49
+ *
50
+ * This is used since we can't always trust Content-Type headers, and is based
51
+ * upon the HTML5 parsing rules.
52
+ *
53
+ *
54
+ * This class can be overloaded with {@see SimpleCluvPie::set_content_type_sniffer_class()}
55
+ *
56
+ * @package SimpleCluvPie
57
+ * @subpackage HTTP
58
+ */
59
+ class SimpleCluvPie_Content_Type_Sniffer
60
+ {
61
+ /**
62
+ * File object
63
+ *
64
+ * @var SimpleCluvPie_File
65
+ */
66
+ var $file;
67
+
68
+ /**
69
+ * Create an instance of the class with the input file
70
+ *
71
+ * @param SimpleCluvPie_Content_Type_Sniffer $file Input file
72
+ */
73
+ public function __construct($file)
74
+ {
75
+ $this->file = $file;
76
+ }
77
+
78
+ /**
79
+ * Get the Content-Type of the specified file
80
+ *
81
+ * @return string Actual Content-Type
82
+ */
83
+ public function get_type()
84
+ {
85
+ if (isset($this->file->headers['content-type']))
86
+ {
87
+ if (!isset($this->file->headers['content-encoding'])
88
+ && ($this->file->headers['content-type'] === 'text/plain'
89
+ || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
90
+ || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'
91
+ || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8'))
92
+ {
93
+ return $this->text_or_binary();
94
+ }
95
+
96
+ if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
97
+ {
98
+ $official = substr($this->file->headers['content-type'], 0, $pos);
99
+ }
100
+ else
101
+ {
102
+ $official = $this->file->headers['content-type'];
103
+ }
104
+ $official = trim(strtolower($official));
105
+
106
+ if ($official === 'unknown/unknown'
107
+ || $official === 'application/unknown')
108
+ {
109
+ return $this->unknown();
110
+ }
111
+ elseif (substr($official, -4) === '+xml'
112
+ || $official === 'text/xml'
113
+ || $official === 'application/xml')
114
+ {
115
+ return $official;
116
+ }
117
+ elseif (substr($official, 0, 6) === 'image/')
118
+ {
119
+ if ($return = $this->image())
120
+ {
121
+ return $return;
122
+ }
123
+ else
124
+ {
125
+ return $official;
126
+ }
127
+ }
128
+ elseif ($official === 'text/html')
129
+ {
130
+ return $this->feed_or_html();
131
+ }
132
+ else
133
+ {
134
+ return $official;
135
+ }
136
+ }
137
+ else
138
+ {
139
+ return $this->unknown();
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Sniff text or binary
145
+ *
146
+ * @return string Actual Content-Type
147
+ */
148
+ public function text_or_binary()
149
+ {
150
+ if (substr($this->file->body, 0, 2) === "\xFE\xFF"
151
+ || substr($this->file->body, 0, 2) === "\xFF\xFE"
152
+ || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
153
+ || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
154
+ {
155
+ return 'text/plain';
156
+ }
157
+ elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
158
+ {
159
+ return 'application/octect-stream';
160
+ }
161
+ else
162
+ {
163
+ return 'text/plain';
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Sniff unknown
169
+ *
170
+ * @return string Actual Content-Type
171
+ */
172
+ public function unknown()
173
+ {
174
+ $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
175
+ if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
176
+ || strtolower(substr($this->file->body, $ws, 5)) === '<html'
177
+ || strtolower(substr($this->file->body, $ws, 7)) === '<script')
178
+ {
179
+ return 'text/html';
180
+ }
181
+ elseif (substr($this->file->body, 0, 5) === '%PDF-')
182
+ {
183
+ return 'application/pdf';
184
+ }
185
+ elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
186
+ {
187
+ return 'application/postscript';
188
+ }
189
+ elseif (substr($this->file->body, 0, 6) === 'GIF87a'
190
+ || substr($this->file->body, 0, 6) === 'GIF89a')
191
+ {
192
+ return 'image/gif';
193
+ }
194
+ elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
195
+ {
196
+ return 'image/png';
197
+ }
198
+ elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
199
+ {
200
+ return 'image/jpeg';
201
+ }
202
+ elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
203
+ {
204
+ return 'image/bmp';
205
+ }
206
+ elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
207
+ {
208
+ return 'image/vnd.microsoft.icon';
209
+ }
210
+ else
211
+ {
212
+ return $this->text_or_binary();
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Sniff images
218
+ *
219
+ * @return string Actual Content-Type
220
+ */
221
+ public function image()
222
+ {
223
+ if (substr($this->file->body, 0, 6) === 'GIF87a'
224
+ || substr($this->file->body, 0, 6) === 'GIF89a')
225
+ {
226
+ return 'image/gif';
227
+ }
228
+ elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
229
+ {
230
+ return 'image/png';
231
+ }
232
+ elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
233
+ {
234
+ return 'image/jpeg';
235
+ }
236
+ elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
237
+ {
238
+ return 'image/bmp';
239
+ }
240
+ elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
241
+ {
242
+ return 'image/vnd.microsoft.icon';
243
+ }
244
+ else
245
+ {
246
+ return false;
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Sniff HTML
252
+ *
253
+ * @return string Actual Content-Type
254
+ */
255
+ public function feed_or_html()
256
+ {
257
+ $len = strlen($this->file->body);
258
+ $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
259
+
260
+ while ($pos < $len)
261
+ {
262
+ switch ($this->file->body[$pos])
263
+ {
264
+ case "\x09":
265
+ case "\x0A":
266
+ case "\x0D":
267
+ case "\x20":
268
+ $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
269
+ continue 2;
270
+
271
+ case '<':
272
+ $pos++;
273
+ break;
274
+
275
+ default:
276
+ return 'text/html';
277
+ }
278
+
279
+ if (substr($this->file->body, $pos, 3) === '!--')
280
+ {
281
+ $pos += 3;
282
+ if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
283
+ {
284
+ $pos += 3;
285
+ }
286
+ else
287
+ {
288
+ return 'text/html';
289
+ }
290
+ }
291
+ elseif (substr($this->file->body, $pos, 1) === '!')
292
+ {
293
+ if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
294
+ {
295
+ $pos++;
296
+ }
297
+ else
298
+ {
299
+ return 'text/html';
300
+ }
301
+ }
302
+ elseif (substr($this->file->body, $pos, 1) === '?')
303
+ {
304
+ if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
305
+ {
306
+ $pos += 2;
307
+ }
308
+ else
309
+ {
310
+ return 'text/html';
311
+ }
312
+ }
313
+ elseif (substr($this->file->body, $pos, 3) === 'rss'
314
+ || substr($this->file->body, $pos, 7) === 'rdf:RDF')
315
+ {
316
+ return 'application/rss+xml';
317
+ }
318
+ elseif (substr($this->file->body, $pos, 4) === 'feed')
319
+ {
320
+ return 'application/atom+xml';
321
+ }
322
+ else
323
+ {
324
+ return 'text/html';
325
+ }
326
+ }
327
+
328
+ return 'text/html';
329
+ }
330
+ }
331
+
libs/SimpleCluvPie/library/SimpleCluvPie/Copyright.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Manages `<media:copyright>` copyright tags as defined in Media RSS
46
+ *
47
+ * Used by {@see SimpleCluvPie_Enclosure::get_copyright()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_copyright_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Copyright
55
+ {
56
+ /**
57
+ * Copyright URL
58
+ *
59
+ * @var string
60
+ * @see get_url()
61
+ */
62
+ var $url;
63
+
64
+ /**
65
+ * Attribution
66
+ *
67
+ * @var string
68
+ * @see get_attribution()
69
+ */
70
+ var $label;
71
+
72
+ /**
73
+ * Constructor, used to input the data
74
+ *
75
+ * For documentation on all the parameters, see the corresponding
76
+ * properties and their accessors
77
+ */
78
+ public function __construct($url = null, $label = null)
79
+ {
80
+ $this->url = $url;
81
+ $this->label = $label;
82
+ }
83
+
84
+ /**
85
+ * String-ified version
86
+ *
87
+ * @return string
88
+ */
89
+ public function __toString()
90
+ {
91
+ // There is no $this->data here
92
+ return md5(serialize($this));
93
+ }
94
+
95
+ /**
96
+ * Get the copyright URL
97
+ *
98
+ * @return string|null URL to copyright information
99
+ */
100
+ public function get_url()
101
+ {
102
+ if ($this->url !== null)
103
+ {
104
+ return $this->url;
105
+ }
106
+ else
107
+ {
108
+ return null;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Get the attribution text
114
+ *
115
+ * @return string|null
116
+ */
117
+ public function get_attribution()
118
+ {
119
+ if ($this->label !== null)
120
+ {
121
+ return $this->label;
122
+ }
123
+ else
124
+ {
125
+ return null;
126
+ }
127
+ }
128
+ }
129
+
libs/SimpleCluvPie/library/SimpleCluvPie/Core.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * SimpleCluvPie class.
46
+ *
47
+ * Class for backward compatibility.
48
+ *
49
+ * @deprecated Use {@see SimpleCluvPie} directly
50
+ * @package SimpleCluvPie
51
+ * @subpackage API
52
+ */
53
+ class SimpleCluvPie_Core extends SimpleCluvPie
54
+ {
55
+
56
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Credit.php ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles `<media:credit>` as defined in Media RSS
46
+ *
47
+ * Used by {@see SimpleCluvPie_Enclosure::get_credit()} and {@see SimpleCluvPie_Enclosure::get_credits()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_credit_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Credit
55
+ {
56
+ /**
57
+ * Credited role
58
+ *
59
+ * @var string
60
+ * @see get_role()
61
+ */
62
+ var $role;
63
+
64
+ /**
65
+ * Organizational scheme
66
+ *
67
+ * @var string
68
+ * @see get_scheme()
69
+ */
70
+ var $scheme;
71
+
72
+ /**
73
+ * Credited name
74
+ *
75
+ * @var string
76
+ * @see get_name()
77
+ */
78
+ var $name;
79
+
80
+ /**
81
+ * Constructor, used to input the data
82
+ *
83
+ * For documentation on all the parameters, see the corresponding
84
+ * properties and their accessors
85
+ */
86
+ public function __construct($role = null, $scheme = null, $name = null)
87
+ {
88
+ $this->role = $role;
89
+ $this->scheme = $scheme;
90
+ $this->name = $name;
91
+ }
92
+
93
+ /**
94
+ * String-ified version
95
+ *
96
+ * @return string
97
+ */
98
+ public function __toString()
99
+ {
100
+ // There is no $this->data here
101
+ return md5(serialize($this));
102
+ }
103
+
104
+ /**
105
+ * Get the role of the person receiving credit
106
+ *
107
+ * @return string|null
108
+ */
109
+ public function get_role()
110
+ {
111
+ if ($this->role !== null)
112
+ {
113
+ return $this->role;
114
+ }
115
+ else
116
+ {
117
+ return null;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Get the organizational scheme
123
+ *
124
+ * @return string|null
125
+ */
126
+ public function get_scheme()
127
+ {
128
+ if ($this->scheme !== null)
129
+ {
130
+ return $this->scheme;
131
+ }
132
+ else
133
+ {
134
+ return null;
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Get the credited person/entity's name
140
+ *
141
+ * @return string|null
142
+ */
143
+ public function get_name()
144
+ {
145
+ if ($this->name !== null)
146
+ {
147
+ return $this->name;
148
+ }
149
+ else
150
+ {
151
+ return null;
152
+ }
153
+ }
154
+ }
155
+
libs/SimpleCluvPie/library/SimpleCluvPie/Decode/HTML/Entities.php ADDED
@@ -0,0 +1,615 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Decode HTML Entities
47
+ *
48
+ * This implements HTML5 as of revision 967 (2007-06-28)
49
+ *
50
+ * @deprecated Use DOMDocument instead!
51
+ * @package SimpleCluvPie
52
+ */
53
+ class SimpleCluvPie_Decode_HTML_Entities
54
+ {
55
+ /**
56
+ * Data to be parsed
57
+ *
58
+ * @access private
59
+ * @var string
60
+ */
61
+ var $data = '';
62
+
63
+ /**
64
+ * Currently consumed bytes
65
+ *
66
+ * @access private
67
+ * @var string
68
+ */
69
+ var $consumed = '';
70
+
71
+ /**
72
+ * Position of the current byte being parsed
73
+ *
74
+ * @access private
75
+ * @var int
76
+ */
77
+ var $position = 0;
78
+
79
+ /**
80
+ * Create an instance of the class with the input data
81
+ *
82
+ * @access public
83
+ * @param string $data Input data
84
+ */
85
+ public function __construct($data)
86
+ {
87
+ $this->data = $data;
88
+ }
89
+
90
+ /**
91
+ * Parse the input data
92
+ *
93
+ * @access public
94
+ * @return string Output data
95
+ */
96
+ public function parse()
97
+ {
98
+ while (($this->position = strpos($this->data, '&', $this->position)) !== false)
99
+ {
100
+ $this->consume();
101
+ $this->entity();
102
+ $this->consumed = '';
103
+ }
104
+ return $this->data;
105
+ }
106
+
107
+ /**
108
+ * Consume the next byte
109
+ *
110
+ * @access private
111
+ * @return mixed The next byte, or false, if there is no more data
112
+ */
113
+ public function consume()
114
+ {
115
+ if (isset($this->data[$this->position]))
116
+ {
117
+ $this->consumed .= $this->data[$this->position];
118
+ return $this->data[$this->position++];
119
+ }
120
+ else
121
+ {
122
+ return false;
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Consume a range of characters
128
+ *
129
+ * @access private
130
+ * @param string $chars Characters to consume
131
+ * @return mixed A series of characters that match the range, or false
132
+ */
133
+ public function consume_range($chars)
134
+ {
135
+ if ($len = strspn($this->data, $chars, $this->position))
136
+ {
137
+ $data = substr($this->data, $this->position, $len);
138
+ $this->consumed .= $data;
139
+ $this->position += $len;
140
+ return $data;
141
+ }
142
+ else
143
+ {
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Unconsume one byte
150
+ *
151
+ * @access private
152
+ */
153
+ public function unconsume()
154
+ {
155
+ $this->consumed = substr($this->consumed, 0, -1);
156
+ $this->position--;
157
+ }
158
+
159
+ /**
160
+ * Decode an entity
161
+ *
162
+ * @access private
163
+ */
164
+ public function entity()
165
+ {
166
+ switch ($this->consume())
167
+ {
168
+ case "\x09":
169
+ case "\x0A":
170
+ case "\x0B":
171
+ case "\x0C":
172
+ case "\x20":
173
+ case "\x3C":
174
+ case "\x26":
175
+ case false:
176
+ break;
177
+
178
+ case "\x23":
179
+ switch ($this->consume())
180
+ {
181
+ case "\x78":
182
+ case "\x58":
183
+ $range = '0123456789ABCDEFabcdef';
184
+ $hex = true;
185
+ break;
186
+
187
+ default:
188
+ $range = '0123456789';
189
+ $hex = false;
190
+ $this->unconsume();
191
+ break;
192
+ }
193
+
194
+ if ($codepoint = $this->consume_range($range))
195
+ {
196
+ 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");
197
+
198
+ if ($hex)
199
+ {
200
+ $codepoint = hexdec($codepoint);
201
+ }
202
+ else
203
+ {
204
+ $codepoint = intval($codepoint);
205
+ }
206
+
207
+ if (isset($windows_1252_specials[$codepoint]))
208
+ {
209
+ $replacement = $windows_1252_specials[$codepoint];
210
+ }
211
+ else
212
+ {
213
+ $replacement = SimpleCluvPie_Misc::codepoint_to_utf8($codepoint);
214
+ }
215
+
216
+ if (!in_array($this->consume(), array(';', false), true))
217
+ {
218
+ $this->unconsume();
219
+ }
220
+
221
+ $consumed_length = strlen($this->consumed);
222
+ $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
223
+ $this->position += strlen($replacement) - $consumed_length;
224
+ }
225
+ break;
226
+
227
+ default:
228
+ static $entities = array(
229
+ 'Aacute' => "\xC3\x81",
230
+ 'aacute' => "\xC3\xA1",
231
+ 'Aacute;' => "\xC3\x81",
232
+ 'aacute;' => "\xC3\xA1",
233
+ 'Acirc' => "\xC3\x82",
234
+ 'acirc' => "\xC3\xA2",
235
+ 'Acirc;' => "\xC3\x82",
236
+ 'acirc;' => "\xC3\xA2",
237
+ 'acute' => "\xC2\xB4",
238
+ 'acute;' => "\xC2\xB4",
239
+ 'AElig' => "\xC3\x86",
240
+ 'aelig' => "\xC3\xA6",
241
+ 'AElig;' => "\xC3\x86",
242
+ 'aelig;' => "\xC3\xA6",
243
+ 'Agrave' => "\xC3\x80",
244
+ 'agrave' => "\xC3\xA0",
245
+ 'Agrave;' => "\xC3\x80",
246
+ 'agrave;' => "\xC3\xA0",
247
+ 'alefsym;' => "\xE2\x84\xB5",
248
+ 'Alpha;' => "\xCE\x91",
249
+ 'alpha;' => "\xCE\xB1",
250
+ 'AMP' => "\x26",
251
+ 'amp' => "\x26",
252
+ 'AMP;' => "\x26",
253
+ 'amp;' => "\x26",
254
+ 'and;' => "\xE2\x88\xA7",
255
+ 'ang;' => "\xE2\x88\xA0",
256
+ 'apos;' => "\x27",
257
+ 'Aring' => "\xC3\x85",
258
+ 'aring' => "\xC3\xA5",
259
+ 'Aring;' => "\xC3\x85",
260
+ 'aring;' => "\xC3\xA5",
261
+ 'asymp;' => "\xE2\x89\x88",
262
+ 'Atilde' => "\xC3\x83",
263
+ 'atilde' => "\xC3\xA3",
264
+ 'Atilde;' => "\xC3\x83",
265
+ 'atilde;' => "\xC3\xA3",
266
+ 'Auml' => "\xC3\x84",
267
+ 'auml' => "\xC3\xA4",
268
+ 'Auml;' => "\xC3\x84",
269
+ 'auml;' => "\xC3\xA4",
270
+ 'bdquo;' => "\xE2\x80\x9E",
271
+ 'Beta;' => "\xCE\x92",
272
+ 'beta;' => "\xCE\xB2",
273
+ 'brvbar' => "\xC2\xA6",
274
+ 'brvbar;' => "\xC2\xA6",
275
+ 'bull;' => "\xE2\x80\xA2",
276
+ 'cap;' => "\xE2\x88\xA9",
277
+ 'Ccedil' => "\xC3\x87",
278
+ 'ccedil' => "\xC3\xA7",
279
+ 'Ccedil;' => "\xC3\x87",
280
+ 'ccedil;' => "\xC3\xA7",
281
+ 'cedil' => "\xC2\xB8",
282
+ 'cedil;' => "\xC2\xB8",
283
+ 'cent' => "\xC2\xA2",
284
+ 'cent;' => "\xC2\xA2",
285
+ 'Chi;' => "\xCE\xA7",
286
+ 'chi;' => "\xCF\x87",
287
+ 'circ;' => "\xCB\x86",
288
+ 'clubs;' => "\xE2\x99\xA3",
289
+ 'cong;' => "\xE2\x89\x85",
290
+ 'COPY' => "\xC2\xA9",
291
+ 'copy' => "\xC2\xA9",
292
+ 'COPY;' => "\xC2\xA9",
293
+ 'copy;' => "\xC2\xA9",
294
+ 'crarr;' => "\xE2\x86\xB5",
295
+ 'cup;' => "\xE2\x88\xAA",
296
+ 'curren' => "\xC2\xA4",
297
+ 'curren;' => "\xC2\xA4",
298
+ 'Dagger;' => "\xE2\x80\xA1",
299
+ 'dagger;' => "\xE2\x80\xA0",
300
+ 'dArr;' => "\xE2\x87\x93",
301
+ 'darr;' => "\xE2\x86\x93",
302
+ 'deg' => "\xC2\xB0",
303
+ 'deg;' => "\xC2\xB0",
304
+ 'Delta;' => "\xCE\x94",
305
+ 'delta;' => "\xCE\xB4",
306
+ 'diams;' => "\xE2\x99\xA6",
307
+ 'divide' => "\xC3\xB7",
308
+ 'divide;' => "\xC3\xB7",
309
+ 'Eacute' => "\xC3\x89",
310
+ 'eacute' => "\xC3\xA9",
311
+ 'Eacute;' => "\xC3\x89",
312
+ 'eacute;' => "\xC3\xA9",
313
+ 'Ecirc' => "\xC3\x8A",
314
+ 'ecirc' => "\xC3\xAA",
315
+ 'Ecirc;' => "\xC3\x8A",
316
+ 'ecirc;' => "\xC3\xAA",
317
+ 'Egrave' => "\xC3\x88",
318
+ 'egrave' => "\xC3\xA8",
319
+ 'Egrave;' => "\xC3\x88",
320
+ 'egrave;' => "\xC3\xA8",
321
+ 'empty;' => "\xE2\x88\x85",
322
+ 'emsp;' => "\xE2\x80\x83",
323
+ 'ensp;' => "\xE2\x80\x82",
324
+ 'Epsilon;' => "\xCE\x95",
325
+ 'epsilon;' => "\xCE\xB5",
326
+ 'equiv;' => "\xE2\x89\xA1",
327
+ 'Eta;' => "\xCE\x97",
328
+ 'eta;' => "\xCE\xB7",
329
+ 'ETH' => "\xC3\x90",
330
+ 'eth' => "\xC3\xB0",
331
+ 'ETH;' => "\xC3\x90",
332
+ 'eth;' => "\xC3\xB0",
333
+ 'Euml' => "\xC3\x8B",
334
+ 'euml' => "\xC3\xAB",
335
+ 'Euml;' => "\xC3\x8B",
336
+ 'euml;' => "\xC3\xAB",
337
+ 'euro;' => "\xE2\x82\xAC",
338
+ 'exist;' => "\xE2\x88\x83",
339
+ 'fnof;' => "\xC6\x92",
340
+ 'forall;' => "\xE2\x88\x80",
341
+ 'frac12' => "\xC2\xBD",
342
+ 'frac12;' => "\xC2\xBD",
343
+ 'frac14' => "\xC2\xBC",
344
+ 'frac14;' => "\xC2\xBC",
345
+ 'frac34' => "\xC2\xBE",
346
+ 'frac34;' => "\xC2\xBE",
347
+ 'frasl;' => "\xE2\x81\x84",
348
+ 'Gamma;' => "\xCE\x93",
349
+ 'gamma;' => "\xCE\xB3",
350
+ 'ge;' => "\xE2\x89\xA5",
351
+ 'GT' => "\x3E",
352
+ 'gt' => "\x3E",
353
+ 'GT;' => "\x3E",
354
+ 'gt;' => "\x3E",
355
+ 'hArr;' => "\xE2\x87\x94",
356
+ 'harr;' => "\xE2\x86\x94",
357
+ 'hearts;' => "\xE2\x99\xA5",
358
+ 'hellip;' => "\xE2\x80\xA6",
359
+ 'Iacute' => "\xC3\x8D",
360
+ 'iacute' => "\xC3\xAD",
361
+ 'Iacute;' => "\xC3\x8D",
362
+ 'iacute;' => "\xC3\xAD",
363
+ 'Icirc' => "\xC3\x8E",
364
+ 'icirc' => "\xC3\xAE",
365
+ 'Icirc;' => "\xC3\x8E",
366
+ 'icirc;' => "\xC3\xAE",
367
+ 'iexcl' => "\xC2\xA1",
368
+ 'iexcl;' => "\xC2\xA1",
369
+ 'Igrave' => "\xC3\x8C",
370
+ 'igrave' => "\xC3\xAC",
371
+ 'Igrave;' => "\xC3\x8C",
372
+ 'igrave;' => "\xC3\xAC",
373
+ 'image;' => "\xE2\x84\x91",
374
+ 'infin;' => "\xE2\x88\x9E",
375
+ 'int;' => "\xE2\x88\xAB",
376
+ 'Iota;' => "\xCE\x99",
377
+ 'iota;' => "\xCE\xB9",
378
+ 'iquest' => "\xC2\xBF",
379
+ 'iquest;' => "\xC2\xBF",
380
+ 'isin;' => "\xE2\x88\x88",
381
+ 'Iuml' => "\xC3\x8F",
382
+ 'iuml' => "\xC3\xAF",
383
+ 'Iuml;' => "\xC3\x8F",
384
+ 'iuml;' => "\xC3\xAF",
385
+ 'Kappa;' => "\xCE\x9A",
386
+ 'kappa;' => "\xCE\xBA",
387
+ 'Lambda;' => "\xCE\x9B",
388
+ 'lambda;' => "\xCE\xBB",
389
+ 'lang;' => "\xE3\x80\x88",
390
+ 'laquo' => "\xC2\xAB",
391
+ 'laquo;' => "\xC2\xAB",
392
+ 'lArr;' => "\xE2\x87\x90",
393
+ 'larr;' => "\xE2\x86\x90",
394
+ 'lceil;' => "\xE2\x8C\x88",
395
+ 'ldquo;' => "\xE2\x80\x9C",
396
+ 'le;' => "\xE2\x89\xA4",
397
+ 'lfloor;' => "\xE2\x8C\x8A",
398
+ 'lowast;' => "\xE2\x88\x97",
399
+ 'loz;' => "\xE2\x97\x8A",
400
+ 'lrm;' => "\xE2\x80\x8E",
401
+ 'lsaquo;' => "\xE2\x80\xB9",
402
+ 'lsquo;' => "\xE2\x80\x98",
403
+ 'LT' => "\x3C",
404
+ 'lt' => "\x3C",
405
+ 'LT;' => "\x3C",
406
+ 'lt;' => "\x3C",
407
+ 'macr' => "\xC2\xAF",
408
+ 'macr;' => "\xC2\xAF",
409
+ 'mdash;' => "\xE2\x80\x94",
410
+ 'micro' => "\xC2\xB5",
411
+ 'micro;' => "\xC2\xB5",
412
+ 'middot' => "\xC2\xB7",
413
+ 'middot;' => "\xC2\xB7",
414
+ 'minus;' => "\xE2\x88\x92",
415
+ 'Mu;' => "\xCE\x9C",
416
+ 'mu;' => "\xCE\xBC",
417
+ 'nabla;' => "\xE2\x88\x87",
418
+ 'nbsp' => "\xC2\xA0",
419
+ 'nbsp;' => "\xC2\xA0",
420
+ 'ndash;' => "\xE2\x80\x93",
421
+ 'ne;' => "\xE2\x89\xA0",
422
+ 'ni;' => "\xE2\x88\x8B",
423
+ 'not' => "\xC2\xAC",
424
+ 'not;' => "\xC2\xAC",
425
+ 'notin;' => "\xE2\x88\x89",
426
+ 'nsub;' => "\xE2\x8A\x84",
427
+ 'Ntilde' => "\xC3\x91",
428
+ 'ntilde' => "\xC3\xB1",
429
+ 'Ntilde;' => "\xC3\x91",
430
+ 'ntilde;' => "\xC3\xB1",
431
+ 'Nu;' => "\xCE\x9D",
432
+ 'nu;' => "\xCE\xBD",
433
+ 'Oacute' => "\xC3\x93",
434
+ 'oacute' => "\xC3\xB3",
435
+ 'Oacute;' => "\xC3\x93",
436
+ 'oacute;' => "\xC3\xB3",
437
+ 'Ocirc' => "\xC3\x94",
438
+ 'ocirc' => "\xC3\xB4",
439
+ 'Ocirc;' => "\xC3\x94",
440
+ 'ocirc;' => "\xC3\xB4",
441
+ 'OElig;' => "\xC5\x92",
442
+ 'oelig;' => "\xC5\x93",
443
+ 'Ograve' => "\xC3\x92",
444
+ 'ograve' => "\xC3\xB2",
445
+ 'Ograve;' => "\xC3\x92",
446
+ 'ograve;' => "\xC3\xB2",
447
+ 'oline;' => "\xE2\x80\xBE",
448
+ 'Omega;' => "\xCE\xA9",
449
+ 'omega;' => "\xCF\x89",
450
+ 'Omicron;' => "\xCE\x9F",
451
+ 'omicron;' => "\xCE\xBF",
452
+ 'oplus;' => "\xE2\x8A\x95",
453
+ 'or;' => "\xE2\x88\xA8",
454
+ 'ordf' => "\xC2\xAA",
455
+ 'ordf;' => "\xC2\xAA",
456
+ 'ordm' => "\xC2\xBA",
457
+ 'ordm;' => "\xC2\xBA",
458
+ 'Oslash' => "\xC3\x98",
459
+ 'oslash' => "\xC3\xB8",
460
+ 'Oslash;' => "\xC3\x98",
461
+ 'oslash;' => "\xC3\xB8",
462
+ 'Otilde' => "\xC3\x95",
463
+ 'otilde' => "\xC3\xB5",
464
+ 'Otilde;' => "\xC3\x95",
465
+ 'otilde;' => "\xC3\xB5",
466
+ 'otimes;' => "\xE2\x8A\x97",
467
+ 'Ouml' => "\xC3\x96",
468
+ 'ouml' => "\xC3\xB6",
469
+ 'Ouml;' => "\xC3\x96",
470
+ 'ouml;' => "\xC3\xB6",
471
+ 'para' => "\xC2\xB6",
472
+ 'para;' => "\xC2\xB6",
473
+ 'part;' => "\xE2\x88\x82",
474
+ 'permil;' => "\xE2\x80\xB0",
475
+ 'perp;' => "\xE2\x8A\xA5",
476
+ 'Phi;' => "\xCE\xA6",
477
+ 'phi;' => "\xCF\x86",
478
+ 'Pi;' => "\xCE\xA0",
479
+ 'pi;' => "\xCF\x80",
480
+ 'piv;' => "\xCF\x96",
481
+ 'plusmn' => "\xC2\xB1",
482
+ 'plusmn;' => "\xC2\xB1",
483
+ 'pound' => "\xC2\xA3",
484
+ 'pound;' => "\xC2\xA3",
485
+ 'Prime;' => "\xE2\x80\xB3",
486
+ 'prime;' => "\xE2\x80\xB2",
487
+ 'prod;' => "\xE2\x88\x8F",
488
+ 'prop;' => "\xE2\x88\x9D",
489
+ 'Psi;' => "\xCE\xA8",
490
+ 'psi;' => "\xCF\x88",
491
+ 'QUOT' => "\x22",
492
+ 'quot' => "\x22",
493
+ 'QUOT;' => "\x22",
494
+ 'quot;' => "\x22",
495
+ 'radic;' => "\xE2\x88\x9A",
496
+ 'rang;' => "\xE3\x80\x89",
497
+ 'raquo' => "\xC2\xBB",
498
+ 'raquo;' => "\xC2\xBB",
499
+ 'rArr;' => "\xE2\x87\x92",
500
+ 'rarr;' => "\xE2\x86\x92",
501
+ 'rceil;' => "\xE2\x8C\x89",
502
+ 'rdquo;' => "\xE2\x80\x9D",
503
+ 'real;' => "\xE2\x84\x9C",
504
+ 'REG' => "\xC2\xAE",
505
+ 'reg' => "\xC2\xAE",
506
+ 'REG;' => "\xC2\xAE",
507
+ 'reg;' => "\xC2\xAE",
508
+ 'rfloor;' => "\xE2\x8C\x8B",
509
+ 'Rho;' => "\xCE\xA1",
510
+ 'rho;' => "\xCF\x81",
511
+ 'rlm;' => "\xE2\x80\x8F",
512
+ 'rsaquo;' => "\xE2\x80\xBA",
513
+ 'rsquo;' => "\xE2\x80\x99",
514
+ 'sbquo;' => "\xE2\x80\x9A",
515
+ 'Scaron;' => "\xC5\xA0",
516
+ 'scaron;' => "\xC5\xA1",
517
+ 'sdot;' => "\xE2\x8B\x85",
518
+ 'sect' => "\xC2\xA7",
519
+ 'sect;' => "\xC2\xA7",
520
+ 'shy' => "\xC2\xAD",
521
+ 'shy;' => "\xC2\xAD",
522
+ 'Sigma;' => "\xCE\xA3",
523
+ 'sigma;' => "\xCF\x83",
524
+ 'sigmaf;' => "\xCF\x82",
525
+ 'sim;' => "\xE2\x88\xBC",
526
+ 'spades;' => "\xE2\x99\xA0",
527
+ 'sub;' => "\xE2\x8A\x82",
528
+ 'sube;' => "\xE2\x8A\x86",
529
+ 'sum;' => "\xE2\x88\x91",
530
+ 'sup;' => "\xE2\x8A\x83",
531
+ 'sup1' => "\xC2\xB9",
532
+ 'sup1;' => "\xC2\xB9",
533
+ 'sup2' => "\xC2\xB2",
534
+ 'sup2;' => "\xC2\xB2",
535
+ 'sup3' => "\xC2\xB3",
536
+ 'sup3;' => "\xC2\xB3",
537
+ 'supe;' => "\xE2\x8A\x87",
538
+ 'szlig' => "\xC3\x9F",
539
+ 'szlig;' => "\xC3\x9F",
540
+ 'Tau;' => "\xCE\xA4",
541
+ 'tau;' => "\xCF\x84",
542
+ 'there4;' => "\xE2\x88\xB4",
543
+ 'Theta;' => "\xCE\x98",
544
+ 'theta;' => "\xCE\xB8",
545
+ 'thetasym;' => "\xCF\x91",
546
+ 'thinsp;' => "\xE2\x80\x89",
547
+ 'THORN' => "\xC3\x9E",
548
+ 'thorn' => "\xC3\xBE",
549
+ 'THORN;' => "\xC3\x9E",
550
+ 'thorn;' => "\xC3\xBE",
551
+ 'tilde;' => "\xCB\x9C",
552
+ 'times' => "\xC3\x97",
553
+ 'times;' => "\xC3\x97",
554
+ 'TRADE;' => "\xE2\x84\xA2",
555
+ 'trade;' => "\xE2\x84\xA2",
556
+ 'Uacute' => "\xC3\x9A",
557
+ 'uacute' => "\xC3\xBA",
558
+ 'Uacute;' => "\xC3\x9A",
559
+ 'uacute;' => "\xC3\xBA",
560
+ 'uArr;' => "\xE2\x87\x91",
561
+ 'uarr;' => "\xE2\x86\x91",
562
+ 'Ucirc' => "\xC3\x9B",
563
+ 'ucirc' => "\xC3\xBB",
564
+ 'Ucirc;' => "\xC3\x9B",
565
+ 'ucirc;' => "\xC3\xBB",
566
+ 'Ugrave' => "\xC3\x99",
567
+ 'ugrave' => "\xC3\xB9",
568
+ 'Ugrave;' => "\xC3\x99",
569
+ 'ugrave;' => "\xC3\xB9",
570
+ 'uml' => "\xC2\xA8",
571
+ 'uml;' => "\xC2\xA8",
572
+ 'upsih;' => "\xCF\x92",
573
+ 'Upsilon;' => "\xCE\xA5",
574
+ 'upsilon;' => "\xCF\x85",
575
+ 'Uuml' => "\xC3\x9C",
576
+ 'uuml' => "\xC3\xBC",
577
+ 'Uuml;' => "\xC3\x9C",
578
+ 'uuml;' => "\xC3\xBC",
579
+ 'weierp;' => "\xE2\x84\x98",
580
+ 'Xi;' => "\xCE\x9E",
581
+ 'xi;' => "\xCE\xBE",
582
+ 'Yacute' => "\xC3\x9D",
583
+ 'yacute' => "\xC3\xBD",
584
+ 'Yacute;' => "\xC3\x9D",
585
+ 'yacute;' => "\xC3\xBD",
586
+ 'yen' => "\xC2\xA5",
587
+ 'yen;' => "\xC2\xA5",
588
+ 'yuml' => "\xC3\xBF",
589
+ 'Yuml;' => "\xC5\xB8",
590
+ 'yuml;' => "\xC3\xBF",
591
+ 'Zeta;' => "\xCE\x96",
592
+ 'zeta;' => "\xCE\xB6",
593
+ 'zwj;' => "\xE2\x80\x8D",
594
+ 'zwnj;' => "\xE2\x80\x8C"
595
+ );
596
+
597
+ for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
598
+ {
599
+ $consumed = substr($this->consumed, 1);
600
+ if (isset($entities[$consumed]))
601
+ {
602
+ $match = $consumed;
603
+ }
604
+ }
605
+
606
+ if ($match !== null)
607
+ {
608
+ $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
609
+ $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
610
+ }
611
+ break;
612
+ }
613
+ }
614
+ }
615
+
libs/SimpleCluvPie/library/SimpleCluvPie/Enclosure.php ADDED
@@ -0,0 +1,1379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles everything related to enclosures (including Media RSS and iTunes RSS)
46
+ *
47
+ * Used by {@see SimpleCluvPie_Item::get_enclosure()} and {@see SimpleCluvPie_Item::get_enclosures()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_enclosure_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Enclosure
55
+ {
56
+ /**
57
+ * @var string
58
+ * @see get_bitrate()
59
+ */
60
+ var $bitrate;
61
+
62
+ /**
63
+ * @var array
64
+ * @see get_captions()
65
+ */
66
+ var $captions;
67
+
68
+ /**
69
+ * @var array
70
+ * @see get_categories()
71
+ */
72
+ var $categories;
73
+
74
+ /**
75
+ * @var int
76
+ * @see get_channels()
77
+ */
78
+ var $channels;
79
+
80
+ /**
81
+ * @var SimpleCluvPie_Copyright
82
+ * @see get_copyright()
83
+ */
84
+ var $copyright;
85
+
86
+ /**
87
+ * @var array
88
+ * @see get_credits()
89
+ */
90
+ var $credits;
91
+
92
+ /**
93
+ * @var string
94
+ * @see get_description()
95
+ */
96
+ var $description;
97
+
98
+ /**
99
+ * @var int
100
+ * @see get_duration()
101
+ */
102
+ var $duration;
103
+
104
+ /**
105
+ * @var string
106
+ * @see get_expression()
107
+ */
108
+ var $expression;
109
+
110
+ /**
111
+ * @var string
112
+ * @see get_framerate()
113
+ */
114
+ var $framerate;
115
+
116
+ /**
117
+ * @var string
118
+ * @see get_handler()
119
+ */
120
+ var $handler;
121
+
122
+ /**
123
+ * @var array
124
+ * @see get_hashes()
125
+ */
126
+ var $hashes;
127
+
128
+ /**
129
+ * @var string
130
+ * @see get_height()
131
+ */
132
+ var $height;
133
+
134
+ /**
135
+ * @deprecated
136
+ * @var null
137
+ */
138
+ var $javascript;
139
+
140
+ /**
141
+ * @var array
142
+ * @see get_keywords()
143
+ */
144
+ var $keywords;
145
+
146
+ /**
147
+ * @var string
148
+ * @see get_language()
149
+ */
150
+ var $lang;
151
+
152
+ /**
153
+ * @var string
154
+ * @see get_length()
155
+ */
156
+ var $length;
157
+
158
+ /**
159
+ * @var string
160
+ * @see get_link()
161
+ */
162
+ var $link;
163
+
164
+ /**
165
+ * @var string
166
+ * @see get_medium()
167
+ */
168
+ var $medium;
169
+
170
+ /**
171
+ * @var string
172
+ * @see get_player()
173
+ */
174
+ var $player;
175
+
176
+ /**
177
+ * @var array
178
+ * @see get_ratings()
179
+ */
180
+ var $ratings;
181
+
182
+ /**
183
+ * @var array
184
+ * @see get_restrictions()
185
+ */
186
+ var $restrictions;
187
+
188
+ /**
189
+ * @var string
190
+ * @see get_sampling_rate()
191
+ */
192
+ var $samplingrate;
193
+
194
+ /**
195
+ * @var array
196
+ * @see get_thumbnails()
197
+ */
198
+ var $thumbnails;
199
+
200
+ /**
201
+ * @var string
202
+ * @see get_title()
203
+ */
204
+ var $title;
205
+
206
+ /**
207
+ * @var string
208
+ * @see get_type()
209
+ */
210
+ var $type;
211
+
212
+ /**
213
+ * @var string
214
+ * @see get_width()
215
+ */
216
+ var $width;
217
+
218
+ /**
219
+ * Constructor, used to input the data
220
+ *
221
+ * For documentation on all the parameters, see the corresponding
222
+ * properties and their accessors
223
+ *
224
+ * @uses idna_convert If available, this will convert an IDN
225
+ */
226
+ public function __construct($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)
227
+ {
228
+ $this->bitrate = $bitrate;
229
+ $this->captions = $captions;
230
+ $this->categories = $categories;
231
+ $this->channels = $channels;
232
+ $this->copyright = $copyright;
233
+ $this->credits = $credits;
234
+ $this->description = $description;
235
+ $this->duration = $duration;
236
+ $this->expression = $expression;
237
+ $this->framerate = $framerate;
238
+ $this->hashes = $hashes;
239
+ $this->height = $height;
240
+ $this->keywords = $keywords;
241
+ $this->lang = $lang;
242
+ $this->length = $length;
243
+ $this->link = $link;
244
+ $this->medium = $medium;
245
+ $this->player = $player;
246
+ $this->ratings = $ratings;
247
+ $this->restrictions = $restrictions;
248
+ $this->samplingrate = $samplingrate;
249
+ $this->thumbnails = $thumbnails;
250
+ $this->title = $title;
251
+ $this->type = $type;
252
+ $this->width = $width;
253
+
254
+ if (class_exists('idna_convert'))
255
+ {
256
+ $idn = new idna_convert();
257
+ $parsed = SimpleCluvPie_Misc::parse_url($link);
258
+ $this->link = SimpleCluvPie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
259
+ }
260
+ $this->handler = $this->get_handler(); // Needs to load last
261
+ }
262
+
263
+ /**
264
+ * String-ified version
265
+ *
266
+ * @return string
267
+ */
268
+ public function __toString()
269
+ {
270
+ // There is no $this->data here
271
+ return md5(serialize($this));
272
+ }
273
+
274
+ /**
275
+ * Get the bitrate
276
+ *
277
+ * @return string|null
278
+ */
279
+ public function get_bitrate()
280
+ {
281
+ if ($this->bitrate !== null)
282
+ {
283
+ return $this->bitrate;
284
+ }
285
+ else
286
+ {
287
+ return null;
288
+ }
289
+ }
290
+
291
+ /**
292
+ * Get a single caption
293
+ *
294
+ * @param int $key
295
+ * @return SimpleCluvPie_Caption|null
296
+ */
297
+ public function get_caption($key = 0)
298
+ {
299
+ $captions = $this->get_captions();
300
+ if (isset($captions[$key]))
301
+ {
302
+ return $captions[$key];
303
+ }
304
+ else
305
+ {
306
+ return null;
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Get all captions
312
+ *
313
+ * @return array|null Array of {@see SimpleCluvPie_Caption} objects
314
+ */
315
+ public function get_captions()
316
+ {
317
+ if ($this->captions !== null)
318
+ {
319
+ return $this->captions;
320
+ }
321
+ else
322
+ {
323
+ return null;
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Get a single category
329
+ *
330
+ * @param int $key
331
+ * @return SimpleCluvPie_Category|null
332
+ */
333
+ public function get_category($key = 0)
334
+ {
335
+ $categories = $this->get_categories();
336
+ if (isset($categories[$key]))
337
+ {
338
+ return $categories[$key];
339
+ }
340
+ else
341
+ {
342
+ return null;
343
+ }
344
+ }
345
+
346
+ /**
347
+ * Get all categories
348
+ *
349
+ * @return array|null Array of {@see SimpleCluvPie_Category} objects
350
+ */
351
+ public function get_categories()
352
+ {
353
+ if ($this->categories !== null)
354
+ {
355
+ return $this->categories;
356
+ }
357
+ else
358
+ {
359
+ return null;
360
+ }
361
+ }
362
+
363
+ /**
364
+ * Get the number of audio channels
365
+ *
366
+ * @return int|null
367
+ */
368
+ public function get_channels()
369
+ {
370
+ if ($this->channels !== null)
371
+ {
372
+ return $this->channels;
373
+ }
374
+ else
375
+ {
376
+ return null;
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Get the copyright information
382
+ *
383
+ * @return SimpleCluvPie_Copyright|null
384
+ */
385
+ public function get_copyright()
386
+ {
387
+ if ($this->copyright !== null)
388
+ {
389
+ return $this->copyright;
390
+ }
391
+ else
392
+ {
393
+ return null;
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Get a single credit
399
+ *
400
+ * @param int $key
401
+ * @return SimpleCluvPie_Credit|null
402
+ */
403
+ public function get_credit($key = 0)
404
+ {
405
+ $credits = $this->get_credits();
406
+ if (isset($credits[$key]))
407
+ {
408
+ return $credits[$key];
409
+ }
410
+ else
411
+ {
412
+ return null;
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Get all credits
418
+ *
419
+ * @return array|null Array of {@see SimpleCluvPie_Credit} objects
420
+ */
421
+ public function get_credits()
422
+ {
423
+ if ($this->credits !== null)
424
+ {
425
+ return $this->credits;
426
+ }
427
+ else
428
+ {
429
+ return null;
430
+ }
431
+ }
432
+
433
+ /**
434
+ * Get the description of the enclosure
435
+ *
436
+ * @return string|null
437
+ */
438
+ public function get_description()
439
+ {
440
+ if ($this->description !== null)
441
+ {
442
+ return $this->description;
443
+ }
444
+ else
445
+ {
446
+ return null;
447
+ }
448
+ }
449
+
450
+ /**
451
+ * Get the duration of the enclosure
452
+ *
453
+ * @param bool $convert Convert seconds into hh:mm:ss
454
+ * @return string|int|null 'hh:mm:ss' string if `$convert` was specified, otherwise integer (or null if none found)
455
+ */
456
+ public function get_duration($convert = false)
457
+ {
458
+ if ($this->duration !== null)
459
+ {
460
+ if ($convert)
461
+ {
462
+ $time = SimpleCluvPie_Misc::time_hms($this->duration);
463
+ return $time;
464
+ }
465
+ else
466
+ {
467
+ return $this->duration;
468
+ }
469
+ }
470
+ else
471
+ {
472
+ return null;
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Get the expression
478
+ *
479
+ * @return string Probably one of 'sample', 'full', 'nonstop', 'clip'. Defaults to 'full'
480
+ */
481
+ public function get_expression()
482
+ {
483
+ if ($this->expression !== null)
484
+ {
485
+ return $this->expression;
486
+ }
487
+ else
488
+ {
489
+ return 'full';
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Get the file extension
495
+ *
496
+ * @return string|null
497
+ */
498
+ public function get_extension()
499
+ {
500
+ if ($this->link !== null)
501
+ {
502
+ $url = SimpleCluvPie_Misc::parse_url($this->link);
503
+ if ($url['path'] !== '')
504
+ {
505
+ return pathinfo($url['path'], PATHINFO_EXTENSION);
506
+ }
507
+ }
508
+ return null;
509
+ }
510
+
511
+ /**
512
+ * Get the framerate (in frames-per-second)
513
+ *
514
+ * @return string|null
515
+ */
516
+ public function get_framerate()
517
+ {
518
+ if ($this->framerate !== null)
519
+ {
520
+ return $this->framerate;
521
+ }
522
+ else
523
+ {
524
+ return null;
525
+ }
526
+ }
527
+
528
+ /**
529
+ * Get the preferred handler
530
+ *
531
+ * @return string|null One of 'flash', 'fmedia', 'quicktime', 'wmedia', 'mp3'
532
+ */
533
+ public function get_handler()
534
+ {
535
+ return $this->get_real_type(true);
536
+ }
537
+
538
+ /**
539
+ * Get a single hash
540
+ *
541
+ * @link http://www.rssboard.org/media-rss#media-hash
542
+ * @param int $key
543
+ * @return string|null Hash as per `media:hash`, prefixed with "$algo:"
544
+ */
545
+ public function get_hash($key = 0)
546
+ {
547
+ $hashes = $this->get_hashes();
548
+ if (isset($hashes[$key]))
549
+ {
550
+ return $hashes[$key];
551
+ }
552
+ else
553
+ {
554
+ return null;
555
+ }
556
+ }
557
+
558
+ /**
559
+ * Get all credits
560
+ *
561
+ * @return array|null Array of strings, see {@see get_hash()}
562
+ */
563
+ public function get_hashes()
564
+ {
565
+ if ($this->hashes !== null)
566
+ {
567
+ return $this->hashes;
568
+ }
569
+ else
570
+ {
571
+ return null;
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Get the height
577
+ *
578
+ * @return string|null
579
+ */
580
+ public function get_height()
581
+ {
582
+ if ($this->height !== null)
583
+ {
584
+ return $this->height;
585
+ }
586
+ else
587
+ {
588
+ return null;
589
+ }
590
+ }
591
+
592
+ /**
593
+ * Get the language
594
+ *
595
+ * @link http://tools.ietf.org/html/rfc3066
596
+ * @return string|null Language code as per RFC 3066
597
+ */
598
+ public function get_language()
599
+ {
600
+ if ($this->lang !== null)
601
+ {
602
+ return $this->lang;
603
+ }
604
+ else
605
+ {
606
+ return null;
607
+ }
608
+ }
609
+
610
+ /**
611
+ * Get a single keyword
612
+ *
613
+ * @param int $key
614
+ * @return string|null
615
+ */
616
+ public function get_keyword($key = 0)
617
+ {
618
+ $keywords = $this->get_keywords();
619
+ if (isset($keywords[$key]))
620
+ {
621
+ return $keywords[$key];
622
+ }
623
+ else
624
+ {
625
+ return null;
626
+ }
627
+ }
628
+
629
+ /**
630
+ * Get all keywords
631
+ *
632
+ * @return array|null Array of strings
633
+ */
634
+ public function get_keywords()
635
+ {
636
+ if ($this->keywords !== null)
637
+ {
638
+ return $this->keywords;
639
+ }
640
+ else
641
+ {
642
+ return null;
643
+ }
644
+ }
645
+
646
+ /**
647
+ * Get length
648
+ *
649
+ * @return float Length in bytes
650
+ */
651
+ public function get_length()
652
+ {
653
+ if ($this->length !== null)
654
+ {
655
+ return $this->length;
656
+ }
657
+ else
658
+ {
659
+ return null;
660
+ }
661
+ }
662
+
663
+ /**
664
+ * Get the URL
665
+ *
666
+ * @return string|null
667
+ */
668
+ public function get_link()
669
+ {
670
+ if ($this->link !== null)
671
+ {
672
+ return urldecode($this->link);
673
+ }
674
+ else
675
+ {
676
+ return null;
677
+ }
678
+ }
679
+
680
+ /**
681
+ * Get the medium
682
+ *
683
+ * @link http://www.rssboard.org/media-rss#media-content
684
+ * @return string|null Should be one of 'image', 'audio', 'video', 'document', 'executable'
685
+ */
686
+ public function get_medium()
687
+ {
688
+ if ($this->medium !== null)
689
+ {
690
+ return $this->medium;
691
+ }
692
+ else
693
+ {
694
+ return null;
695
+ }
696
+ }
697
+
698
+ /**
699
+ * Get the player URL
700
+ *
701
+ * Typically the same as {@see get_permalink()}
702
+ * @return string|null Player URL
703
+ */
704
+ public function get_player()
705
+ {
706
+ if ($this->player !== null)
707
+ {
708
+ return $this->player;
709
+ }
710
+ else
711
+ {
712
+ return null;
713
+ }
714
+ }
715
+
716
+ /**
717
+ * Get a single rating
718
+ *
719
+ * @param int $key
720
+ * @return SimpleCluvPie_Rating|null
721
+ */
722
+ public function get_rating($key = 0)
723
+ {
724
+ $ratings = $this->get_ratings();
725
+ if (isset($ratings[$key]))
726
+ {
727
+ return $ratings[$key];
728
+ }
729
+ else
730
+ {
731
+ return null;
732
+ }
733
+ }
734
+
735
+ /**
736
+ * Get all ratings
737
+ *
738
+ * @return array|null Array of {@see SimpleCluvPie_Rating} objects
739
+ */
740
+ public function get_ratings()
741
+ {
742
+ if ($this->ratings !== null)
743
+ {
744
+ return $this->ratings;
745
+ }
746
+ else
747
+ {
748
+ return null;
749
+ }
750
+ }
751
+
752
+ /**
753
+ * Get a single restriction
754
+ *
755
+ * @param int $key
756
+ * @return SimpleCluvPie_Restriction|null
757
+ */
758
+ public function get_restriction($key = 0)
759
+ {
760
+ $restrictions = $this->get_restrictions();
761
+ if (isset($restrictions[$key]))
762
+ {
763
+ return $restrictions[$key];
764
+ }
765
+ else
766
+ {
767
+ return null;
768
+ }
769
+ }
770
+
771
+ /**
772
+ * Get all restrictions
773
+ *
774
+ * @return array|null Array of {@see SimpleCluvPie_Restriction} objects
775
+ */
776
+ public function get_restrictions()
777
+ {
778
+ if ($this->restrictions !== null)
779
+ {
780
+ return $this->restrictions;
781
+ }
782
+ else
783
+ {
784
+ return null;
785
+ }
786
+ }
787
+
788
+ /**
789
+ * Get the sampling rate (in kHz)
790
+ *
791
+ * @return string|null
792
+ */
793
+ public function get_sampling_rate()
794
+ {
795
+ if ($this->samplingrate !== null)
796
+ {
797
+ return $this->samplingrate;
798
+ }
799
+ else
800
+ {
801
+ return null;
802
+ }
803
+ }
804
+
805
+ /**
806
+ * Get the file size (in MiB)
807
+ *
808
+ * @return float|null File size in mebibytes (1048 bytes)
809
+ */
810
+ public function get_size()
811
+ {
812
+ $length = $this->get_length();
813
+ if ($length !== null)
814
+ {
815
+ return round($length/1048576, 2);
816
+ }
817
+ else
818
+ {
819
+ return null;
820
+ }
821
+ }
822
+
823
+ /**
824
+ * Get a single thumbnail
825
+ *
826
+ * @param int $key
827
+ * @return string|null Thumbnail URL
828
+ */
829
+ public function get_thumbnail($key = 0)
830
+ {
831
+ $thumbnails = $this->get_thumbnails();
832
+ if (isset($thumbnails[$key]))
833
+ {
834
+ return $thumbnails[$key];
835
+ }
836
+ else
837
+ {
838
+ return null;
839
+ }
840
+ }
841
+
842
+ /**
843
+ * Get all thumbnails
844
+ *
845
+ * @return array|null Array of thumbnail URLs
846
+ */
847
+ public function get_thumbnails()
848
+ {
849
+ if ($this->thumbnails !== null)
850
+ {
851
+ return $this->thumbnails;
852
+ }
853
+ else
854
+ {
855
+ return null;
856
+ }
857
+ }
858
+
859
+ /**
860
+ * Get the title
861
+ *
862
+ * @return string|null
863
+ */
864
+ public function get_title()
865
+ {
866
+ if ($this->title !== null)
867
+ {
868
+ return $this->title;
869
+ }
870
+ else
871
+ {
872
+ return null;
873
+ }
874
+ }
875
+
876
+ /**
877
+ * Get mimetype of the enclosure
878
+ *
879
+ * @see get_real_type()
880
+ * @return string|null MIME type
881
+ */
882
+ public function get_type()
883
+ {
884
+ if ($this->type !== null)
885
+ {
886
+ return $this->type;
887
+ }
888
+ else
889
+ {
890
+ return null;
891
+ }
892
+ }
893
+
894
+ /**
895
+ * Get the width
896
+ *
897
+ * @return string|null
898
+ */
899
+ public function get_width()
900
+ {
901
+ if ($this->width !== null)
902
+ {
903
+ return $this->width;
904
+ }
905
+ else
906
+ {
907
+ return null;
908
+ }
909
+ }
910
+
911
+ /**
912
+ * Embed the enclosure using `<embed>`
913
+ *
914
+ * @deprecated Use the second parameter to {@see embed} instead
915
+ *
916
+ * @param array|string $options See first paramter to {@see embed}
917
+ * @return string HTML string to output
918
+ */
919
+ public function native_embed($options='')
920
+ {
921
+ return $this->embed($options, true);
922
+ }
923
+
924
+ /**
925
+ * Embed the enclosure using Javascript
926
+ *
927
+ * `$options` is an array or comma-separated key:value string, with the
928
+ * following properties:
929
+ *
930
+ * - `alt` (string): Alternate content for when an end-user does not have
931
+ * the appropriate handler installed or when a file type is
932
+ * unsupported. Can be any text or HTML. Defaults to blank.
933
+ * - `altclass` (string): If a file type is unsupported, the end-user will
934
+ * see the alt text (above) linked directly to the content. That link
935
+ * will have this value as its class name. Defaults to blank.
936
+ * - `audio` (string): This is an image that should be used as a
937
+ * placeholder for audio files before they're loaded (QuickTime-only).
938
+ * Can be any relative or absolute URL. Defaults to blank.
939
+ * - `bgcolor` (string): The background color for the media, if not
940
+ * already transparent. Defaults to `#ffffff`.
941
+ * - `height` (integer): The height of the embedded media. Accepts any
942
+ * numeric pixel value (such as `360`) or `auto`. Defaults to `auto`,
943
+ * and it is recommended that you use this default.
944
+ * - `loop` (boolean): Do you want the media to loop when it's done?
945
+ * Defaults to `false`.
946
+ * - `mediaplayer` (string): The location of the included
947
+ * `mediaplayer.swf` file. This allows for the playback of Flash Video
948
+ * (`.flv`) files, and is the default handler for non-Odeo MP3's.
949
+ * Defaults to blank.
950
+ * - `video` (string): This is an image that should be used as a
951
+ * placeholder for video files before they're loaded (QuickTime-only).
952
+ * Can be any relative or absolute URL. Defaults to blank.
953
+ * - `width` (integer): The width of the embedded media. Accepts any
954
+ * numeric pixel value (such as `480`) or `auto`. Defaults to `auto`,
955
+ * and it is recommended that you use this default.
956
+ * - `widescreen` (boolean): Is the enclosure widescreen or standard?
957
+ * This applies only to video enclosures, and will automatically resize
958
+ * the content appropriately. Defaults to `false`, implying 4:3 mode.
959
+ *
960
+ * Note: Non-widescreen (4:3) mode with `width` and `height` set to `auto`
961
+ * will default to 480x360 video resolution. Widescreen (16:9) mode with
962
+ * `width` and `height` set to `auto` will default to 480x270 video resolution.
963
+ *
964
+ * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
965
+ * @param array|string $options Comma-separated key:value list, or array
966
+ * @param bool $native Use `<embed>`
967
+ * @return string HTML string to output
968
+ */
969
+ public function embed($options = '', $native = false)
970
+ {
971
+ // Set up defaults
972
+ $audio = '';
973
+ $video = '';
974
+ $alt = '';
975
+ $altclass = '';
976
+ $loop = 'false';
977
+ $width = 'auto';
978
+ $height = 'auto';
979
+ $bgcolor = '#ffffff';
980
+ $mediaplayer = '';
981
+ $widescreen = false;
982
+ $handler = $this->get_handler();
983
+ $type = $this->get_real_type();
984
+
985
+ // Process options and reassign values as necessary
986
+ if (is_array($options))
987
+ {
988
+ extract($options);
989
+ }
990
+ else
991
+ {
992
+ $options = explode(',', $options);
993
+ foreach($options as $option)
994
+ {
995
+ $opt = explode(':', $option, 2);
996
+ if (isset($opt[0], $opt[1]))
997
+ {
998
+ $opt[0] = trim($opt[0]);
999
+ $opt[1] = trim($opt[1]);
1000
+ switch ($opt[0])
1001
+ {
1002
+ case 'audio':
1003
+ $audio = $opt[1];
1004
+ break;
1005
+
1006
+ case 'video':
1007
+ $video = $opt[1];
1008
+ break;
1009
+
1010
+ case 'alt':
1011
+ $alt = $opt[1];
1012
+ break;
1013
+
1014
+ case 'altclass':
1015
+ $altclass = $opt[1];
1016
+ break;
1017
+
1018
+ case 'loop':
1019
+ $loop = $opt[1];
1020
+ break;
1021
+
1022
+ case 'width':
1023
+ $width = $opt[1];
1024
+ break;
1025
+
1026
+ case 'height':
1027
+ $height = $opt[1];
1028
+ break;
1029
+
1030
+ case 'bgcolor':
1031
+ $bgcolor = $opt[1];
1032
+ break;
1033
+
1034
+ case 'mediaplayer':
1035
+ $mediaplayer = $opt[1];
1036
+ break;
1037
+
1038
+ case 'widescreen':
1039
+ $widescreen = $opt[1];
1040
+ break;
1041
+ }
1042
+ }
1043
+ }
1044
+ }
1045
+
1046
+ $mime = explode('/', $type, 2);
1047
+ $mime = $mime[0];
1048
+
1049
+ // Process values for 'auto'
1050
+ if ($width === 'auto')
1051
+ {
1052
+ if ($mime === 'video')
1053
+ {
1054
+ if ($height === 'auto')
1055
+ {
1056
+ $width = 480;
1057
+ }
1058
+ elseif ($widescreen)
1059
+ {
1060
+ $width = round((intval($height)/9)*16);
1061
+ }
1062
+ else
1063
+ {
1064
+ $width = round((intval($height)/3)*4);
1065
+ }
1066
+ }
1067
+ else
1068
+ {
1069
+ $width = '100%';
1070
+ }
1071
+ }
1072
+
1073
+ if ($height === 'auto')
1074
+ {
1075
+ if ($mime === 'audio')
1076
+ {
1077
+ $height = 0;
1078
+ }
1079
+ elseif ($mime === 'video')
1080
+ {
1081
+ if ($width === 'auto')
1082
+ {
1083
+ if ($widescreen)
1084
+ {
1085
+ $height = 270;
1086
+ }
1087
+ else
1088
+ {
1089
+ $height = 360;
1090
+ }
1091
+ }
1092
+ elseif ($widescreen)
1093
+ {
1094
+ $height = round((intval($width)/16)*9);
1095
+ }
1096
+ else
1097
+ {
1098
+ $height = round((intval($width)/4)*3);
1099
+ }
1100
+ }
1101
+ else
1102
+ {
1103
+ $height = 376;
1104
+ }
1105
+ }
1106
+ elseif ($mime === 'audio')
1107
+ {
1108
+ $height = 0;
1109
+ }
1110
+
1111
+ // Set proper placeholder value
1112
+ if ($mime === 'audio')
1113
+ {
1114
+ $placeholder = $audio;
1115
+ }
1116
+ elseif ($mime === 'video')
1117
+ {
1118
+ $placeholder = $video;
1119
+ }
1120
+
1121
+ $embed = '';
1122
+
1123
+ // Flash
1124
+ if ($handler === 'flash')
1125
+ {
1126
+ if ($native)
1127
+ {
1128
+ $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>";
1129
+ }
1130
+ else
1131
+ {
1132
+ $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
1133
+ }
1134
+ }
1135
+
1136
+ // Flash Media Player file types.
1137
+ // Preferred handler for MP3 file types.
1138
+ elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
1139
+ {
1140
+ $height += 20;
1141
+ if ($native)
1142
+ {
1143
+ $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>";
1144
+ }
1145
+ else
1146
+ {
1147
+ $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
1148
+ }
1149
+ }
1150
+
1151
+ // QuickTime 7 file types. Need to test with QuickTime 6.
1152
+ // Only handle MP3's if the Flash Media Player is not present.
1153
+ elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
1154
+ {
1155
+ $height += 16;
1156
+ if ($native)
1157
+ {
1158
+ if ($placeholder !== '')
1159
+ {
1160
+ $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>";
1161
+ }
1162
+ else
1163
+ {
1164
+ $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>";
1165
+ }
1166
+ }
1167
+ else
1168
+ {
1169
+ $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
1170
+ }
1171
+ }
1172
+
1173
+ // Windows Media
1174
+ elseif ($handler === 'wmedia')
1175
+ {
1176
+ $height += 45;
1177
+ if ($native)
1178
+ {
1179
+ $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>";
1180
+ }
1181
+ else
1182
+ {
1183
+ $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
1184
+ }
1185
+ }
1186
+
1187
+ // Everything else
1188
+ else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
1189
+
1190
+ return $embed;
1191
+ }
1192
+
1193
+ /**
1194
+ * Get the real media type
1195
+ *
1196
+ * Often, feeds lie to us, necessitating a bit of deeper inspection. This
1197
+ * converts types to their canonical representations based on the file
1198
+ * extension
1199
+ *
1200
+ * @see get_type()
1201
+ * @param bool $find_handler Internal use only, use {@see get_handler()} instead
1202
+ * @return string MIME type
1203
+ */
1204
+ public function get_real_type($find_handler = false)
1205
+ {
1206
+ // Mime-types by handler.
1207
+ $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
1208
+ $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
1209
+ $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
1210
+ $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
1211
+ $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
1212
+
1213
+ if ($this->get_type() !== null)
1214
+ {
1215
+ $type = strtolower($this->type);
1216
+ }
1217
+ else
1218
+ {
1219
+ $type = null;
1220
+ }
1221
+
1222
+ // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
1223
+ if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
1224
+ {
1225
+ switch (strtolower($this->get_extension()))
1226
+ {
1227
+ // Audio mime-types
1228
+ case 'aac':
1229
+ case 'adts':
1230
+ $type = 'audio/acc';
1231
+ break;
1232
+
1233
+ case 'aif':
1234
+ case 'aifc':
1235
+ case 'aiff':
1236
+ case 'cdda':
1237
+ $type = 'audio/aiff';
1238
+ break;
1239
+
1240
+ case 'bwf':
1241
+ $type = 'audio/wav';
1242
+ break;
1243
+
1244
+ case 'kar':
1245
+ case 'mid':
1246
+ case 'midi':
1247
+ case 'smf':
1248
+ $type = 'audio/midi';
1249
+ break;
1250
+
1251
+ case 'm4a':
1252
+ $type = 'audio/x-m4a';
1253
+ break;
1254
+
1255
+ case 'mp3':
1256
+ case 'swa':
1257
+ $type = 'audio/mp3';
1258
+ break;
1259
+
1260
+ case 'wav':
1261
+ $type = 'audio/wav';
1262
+ break;
1263
+
1264
+ case 'wax':
1265
+ $type = 'audio/x-ms-wax';
1266
+ break;
1267
+
1268
+ case 'wma':
1269
+ $type = 'audio/x-ms-wma';
1270
+ break;
1271
+
1272
+ // Video mime-types
1273
+ case '3gp':
1274
+ case '3gpp':
1275
+ $type = 'video/3gpp';
1276
+ break;
1277
+
1278
+ case '3g2':
1279
+ case '3gp2':
1280
+ $type = 'video/3gpp2';
1281
+ break;
1282
+
1283
+ case 'asf':
1284
+ $type = 'video/x-ms-asf';
1285
+ break;
1286
+
1287
+ case 'flv':
1288
+ $type = 'video/x-flv';
1289
+ break;
1290
+
1291
+ case 'm1a':
1292
+ case 'm1s':
1293
+ case 'm1v':
1294
+ case 'm15':
1295
+ case 'm75':
1296
+ case 'mp2':
1297
+ case 'mpa':
1298
+ case 'mpeg':
1299
+ case 'mpg':
1300
+ case 'mpm':
1301
+ case 'mpv':
1302
+ $type = 'video/mpeg';
1303
+ break;
1304
+
1305
+ case 'm4v':
1306
+ $type = 'video/x-m4v';
1307
+ break;
1308
+
1309
+ case 'mov':
1310
+ case 'qt':
1311
+ $type = 'video/quicktime';
1312
+ break;
1313
+
1314
+ case 'mp4':
1315
+ case 'mpg4':
1316
+ $type = 'video/mp4';
1317
+ break;
1318
+
1319
+ case 'sdv':
1320
+ $type = 'video/sd-video';
1321
+ break;
1322
+
1323
+ case 'wm':
1324
+ $type = 'video/x-ms-wm';
1325
+ break;
1326
+
1327
+ case 'wmv':
1328
+ $type = 'video/x-ms-wmv';
1329
+ break;
1330
+
1331
+ case 'wvx':
1332
+ $type = 'video/x-ms-wvx';
1333
+ break;
1334
+
1335
+ // Flash mime-types
1336
+ case 'spl':
1337
+ $type = 'application/futuresplash';
1338
+ break;
1339
+
1340
+ case 'swf':
1341
+ $type = 'application/x-shockwave-flash';
1342
+ break;
1343
+ }
1344
+ }
1345
+
1346
+ if ($find_handler)
1347
+ {
1348
+ if (in_array($type, $types_flash))
1349
+ {
1350
+ return 'flash';
1351
+ }
1352
+ elseif (in_array($type, $types_fmedia))
1353
+ {
1354
+ return 'fmedia';
1355
+ }
1356
+ elseif (in_array($type, $types_quicktime))
1357
+ {
1358
+ return 'quicktime';
1359
+ }
1360
+ elseif (in_array($type, $types_wmedia))
1361
+ {
1362
+ return 'wmedia';
1363
+ }
1364
+ elseif (in_array($type, $types_mp3))
1365
+ {
1366
+ return 'mp3';
1367
+ }
1368
+ else
1369
+ {
1370
+ return null;
1371
+ }
1372
+ }
1373
+ else
1374
+ {
1375
+ return $type;
1376
+ }
1377
+ }
1378
+ }
1379
+
libs/SimpleCluvPie/library/SimpleCluvPie/Exception.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * General SimpleCluvPie exception class
46
+ *
47
+ * @package SimpleCluvPie
48
+ */
49
+ class SimpleCluvPie_Exception extends Exception
50
+ {
51
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/File.php ADDED
@@ -0,0 +1,306 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Used for fetching remote files and reading local files
46
+ *
47
+ * Supports HTTP 1.0 via cURL or fsockopen, with spotty HTTP 1.1 support
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_file_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage HTTP
53
+ * @todo Move to properly supporting RFC2616 (HTTP/1.1)
54
+ */
55
+ class SimpleCluvPie_File
56
+ {
57
+ var $url;
58
+ var $useragent;
59
+ var $success = true;
60
+ var $headers = array();
61
+ var $body;
62
+ var $status_code;
63
+ var $redirects = 0;
64
+ var $error;
65
+ var $method = SIMPLECLUVPIE_FILE_SOURCE_NONE;
66
+ var $permanent_url;
67
+
68
+ public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false, $curl_options = array())
69
+ {
70
+ if (class_exists('idna_convert'))
71
+ {
72
+ $idn = new idna_convert();
73
+ $parsed = SimpleCluvPie_Misc::parse_url($url);
74
+ $url = SimpleCluvPie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
75
+ }
76
+ $this->url = $url;
77
+ $this->permanent_url = $url;
78
+ $this->useragent = $useragent;
79
+ if (preg_match('/^http(s)?:\/\//i', $url))
80
+ {
81
+ if ($useragent === null)
82
+ {
83
+ $useragent = ini_get('user_agent');
84
+ $this->useragent = $useragent;
85
+ }
86
+ if (!is_array($headers))
87
+ {
88
+ $headers = array();
89
+ }
90
+ if (!$force_fsockopen && function_exists('curl_exec'))
91
+ {
92
+ $this->method = SIMPLECLUVPIE_FILE_SOURCE_REMOTE | SIMPLECLUVPIE_FILE_SOURCE_CURL;
93
+ $fp = curl_init();
94
+ $headers2 = array();
95
+ foreach ($headers as $key => $value)
96
+ {
97
+ $headers2[] = "$key: $value";
98
+ }
99
+ if (version_compare(SimpleCluvPie_Misc::get_curl_version(), '7.10.5', '>='))
100
+ {
101
+ curl_setopt($fp, CURLOPT_ENCODING, '');
102
+ }
103
+ curl_setopt($fp, CURLOPT_URL, $url);
104
+ curl_setopt($fp, CURLOPT_HEADER, 1);
105
+ curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
106
+ curl_setopt($fp, CURLOPT_FAILONERROR, 1);
107
+ curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
108
+ curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
109
+ curl_setopt($fp, CURLOPT_REFERER, $url);
110
+ curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
111
+ curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
112
+ if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimpleCluvPie_Misc::get_curl_version(), '7.15.2', '>='))
113
+ {
114
+ curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
115
+ curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
116
+ }
117
+ foreach ($curl_options as $curl_param => $curl_value) {
118
+ curl_setopt($fp, $curl_param, $curl_value);
119
+ }
120
+
121
+ $this->headers = curl_exec($fp);
122
+ if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
123
+ {
124
+ curl_setopt($fp, CURLOPT_ENCODING, 'none');
125
+ $this->headers = curl_exec($fp);
126
+ }
127
+ if (curl_errno($fp))
128
+ {
129
+ $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
130
+ $this->success = false;
131
+ }
132
+ else
133
+ {
134
+ // Use the updated url provided by curl_getinfo after any redirects.
135
+ if ($info = curl_getinfo($fp)) {
136
+ $this->url = $info['url'];
137
+ }
138
+ curl_close($fp);
139
+ $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
140
+ $this->headers = array_pop($this->headers);
141
+ $parser = new SimpleCluvPie_HTTP_Parser($this->headers);
142
+ if ($parser->parse())
143
+ {
144
+ $this->headers = $parser->headers;
145
+ $this->body = trim($parser->body);
146
+ $this->status_code = $parser->status_code;
147
+ if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
148
+ {
149
+ $this->redirects++;
150
+ $location = SimpleCluvPie_Misc::absolutize_url($this->headers['location'], $url);
151
+ $previousStatusCode = $this->status_code;
152
+ $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
153
+ $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
154
+ return;
155
+ }
156
+ }
157
+ }
158
+ }
159
+ else
160
+ {
161
+ $this->method = SIMPLECLUVPIE_FILE_SOURCE_REMOTE | SIMPLECLUVPIE_FILE_SOURCE_FSOCKOPEN;
162
+ $url_parts = parse_url($url);
163
+ $socket_host = $url_parts['host'];
164
+ if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
165
+ {
166
+ $socket_host = "ssl://$url_parts[host]";
167
+ $url_parts['port'] = 443;
168
+ }
169
+ if (!isset($url_parts['port']))
170
+ {
171
+ $url_parts['port'] = 80;
172
+ }
173
+ $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
174
+ if (!$fp)
175
+ {
176
+ $this->error = 'fsockopen error: ' . $errstr;
177
+ $this->success = false;
178
+ }
179
+ else
180
+ {
181
+ stream_set_timeout($fp, $timeout);
182
+ if (isset($url_parts['path']))
183
+ {
184
+ if (isset($url_parts['query']))
185
+ {
186
+ $get = "$url_parts[path]?$url_parts[query]";
187
+ }
188
+ else
189
+ {
190
+ $get = $url_parts['path'];
191
+ }
192
+ }
193
+ else
194
+ {
195
+ $get = '/';
196
+ }
197
+ $out = "GET $get HTTP/1.1\r\n";
198
+ $out .= "Host: $url_parts[host]\r\n";
199
+ $out .= "User-Agent: $useragent\r\n";
200
+ if (extension_loaded('zlib'))
201
+ {
202
+ $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
203
+ }
204
+
205
+ if (isset($url_parts['user']) && isset($url_parts['pass']))
206
+ {
207
+ $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
208
+ }
209
+ foreach ($headers as $key => $value)
210
+ {
211
+ $out .= "$key: $value\r\n";
212
+ }
213
+ $out .= "Connection: Close\r\n\r\n";
214
+ fwrite($fp, $out);
215
+
216
+ $info = stream_get_meta_data($fp);
217
+
218
+ $this->headers = '';
219
+ while (!$info['eof'] && !$info['timed_out'])
220
+ {
221
+ $this->headers .= fread($fp, 1160);
222
+ $info = stream_get_meta_data($fp);
223
+ }
224
+ if (!$info['timed_out'])
225
+ {
226
+ $parser = new SimpleCluvPie_HTTP_Parser($this->headers);
227
+ if ($parser->parse())
228
+ {
229
+ $this->headers = $parser->headers;
230
+ $this->body = $parser->body; // do not trim this or you get a gzinflate error
231
+ $this->status_code = $parser->status_code;
232
+ if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
233
+ {
234
+ $this->redirects++;
235
+ $location = SimpleCluvPie_Misc::absolutize_url($this->headers['location'], $url);
236
+ $previousStatusCode = $this->status_code;
237
+ $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
238
+ $this->permanent_url = ($previousStatusCode == 301) ? $location : $url;
239
+ return;
240
+ }
241
+ if (isset($this->headers['content-encoding']))
242
+ {
243
+ // Hey, we act dumb elsewhere, so let's do that here too
244
+ switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
245
+ {
246
+ case 'gzip':
247
+ case 'x-gzip':
248
+ $decoder = new SimpleCluvPie_gzdecode($this->body);
249
+ if (!$decoder->parse())
250
+ {
251
+ $this->error = 'Unable to decode HTTP "gzip" stream';
252
+ $this->success = false;
253
+ }
254
+ else
255
+ {
256
+ $this->body = trim($decoder->data);
257
+ }
258
+ break;
259
+
260
+ case 'deflate':
261
+ if (($decompressed = gzinflate($this->body)) !== false)
262
+ {
263
+ $this->body = $decompressed;
264
+ }
265
+ else if (($decompressed = gzuncompress($this->body)) !== false)
266
+ {
267
+ $this->body = $decompressed;
268
+ }
269
+ else if (function_exists('gzdecode') && ($decompressed = gzdecode($this->body)) !== false)
270
+ {
271
+ $this->body = $decompressed;
272
+ }
273
+ else
274
+ {
275
+ $this->error = 'Unable to decode HTTP "deflate" stream';
276
+ $this->success = false;
277
+ }
278
+ break;
279
+
280
+ default:
281
+ $this->error = 'Unknown content coding';
282
+ $this->success = false;
283
+ }
284
+ }
285
+ }
286
+ }
287
+ else
288
+ {
289
+ $this->error = 'fsocket timed out';
290
+ $this->success = false;
291
+ }
292
+ fclose($fp);
293
+ }
294
+ }
295
+ }
296
+ else
297
+ {
298
+ $this->method = SIMPLECLUVPIE_FILE_SOURCE_LOCAL | SIMPLECLUVPIE_FILE_SOURCE_FILE_GET_CONTENTS;
299
+ if (empty($url) || !($this->body = trim(file_get_contents($url))))
300
+ {
301
+ $this->error = 'file_get_contents could not read the file';
302
+ $this->success = false;
303
+ }
304
+ }
305
+ }
306
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/HTTP/Parser.php ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * HTTP Response Parser
47
+ *
48
+ * @package SimpleCluvPie
49
+ * @subpackage HTTP
50
+ */
51
+ class SimpleCluvPie_HTTP_Parser
52
+ {
53
+ /**
54
+ * HTTP Version
55
+ *
56
+ * @var float
57
+ */
58
+ public $http_version = 0.0;
59
+
60
+ /**
61
+ * Status code
62
+ *
63
+ * @var int
64
+ */
65
+ public $status_code = 0;
66
+
67
+ /**
68
+ * Reason phrase
69
+ *
70
+ * @var string
71
+ */
72
+ public $reason = '';
73
+
74
+ /**
75
+ * Key/value pairs of the headers
76
+ *
77
+ * @var array
78
+ */
79
+ public $headers = array();
80
+
81
+ /**
82
+ * Body of the response
83
+ *
84
+ * @var string
85
+ */
86
+ public $body = '';
87
+
88
+ /**
89
+ * Current state of the state machine
90
+ *
91
+ * @var string
92
+ */
93
+ protected $state = 'http_version';
94
+
95
+ /**
96
+ * Input data
97
+ *
98
+ * @var string
99
+ */
100
+ protected $data = '';
101
+
102
+ /**
103
+ * Input data length (to avoid calling strlen() everytime this is needed)
104
+ *
105
+ * @var int
106
+ */
107
+ protected $data_length = 0;
108
+
109
+ /**
110
+ * Current position of the pointer
111
+ *
112
+ * @var int
113
+ */
114
+ protected $position = 0;
115
+
116
+ /**
117
+ * Name of the hedaer currently being parsed
118
+ *
119
+ * @var string
120
+ */
121
+ protected $name = '';
122
+
123
+ /**
124
+ * Value of the hedaer currently being parsed
125
+ *
126
+ * @var string
127
+ */
128
+ protected $value = '';
129
+
130
+ /**
131
+ * Create an instance of the class with the input data
132
+ *
133
+ * @param string $data Input data
134
+ */
135
+ public function __construct($data)
136
+ {
137
+ $this->data = $data;
138
+ $this->data_length = strlen($this->data);
139
+ }
140
+
141
+ /**
142
+ * Parse the input data
143
+ *
144
+ * @return bool true on success, false on failure
145
+ */
146
+ public function parse()
147
+ {
148
+ while ($this->state && $this->state !== 'emit' && $this->has_data())
149
+ {
150
+ $state = $this->state;
151
+ $this->$state();
152
+ }
153
+ $this->data = '';
154
+ if ($this->state === 'emit' || $this->state === 'body')
155
+ {
156
+ return true;
157
+ }
158
+ else
159
+ {
160
+ $this->http_version = '';
161
+ $this->status_code = '';
162
+ $this->reason = '';
163
+ $this->headers = array();
164
+ $this->body = '';
165
+ return false;
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Check whether there is data beyond the pointer
171
+ *
172
+ * @return bool true if there is further data, false if not
173
+ */
174
+ protected function has_data()
175
+ {
176
+ return (bool) ($this->position < $this->data_length);
177
+ }
178
+
179
+ /**
180
+ * See if the next character is LWS
181
+ *
182
+ * @return bool true if the next character is LWS, false if not
183
+ */
184
+ protected function is_linear_whitespace()
185
+ {
186
+ return (bool) ($this->data[$this->position] === "\x09"
187
+ || $this->data[$this->position] === "\x20"
188
+ || ($this->data[$this->position] === "\x0A"
189
+ && isset($this->data[$this->position + 1])
190
+ && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
191
+ }
192
+
193
+ /**
194
+ * Parse the HTTP version
195
+ */
196
+ protected function http_version()
197
+ {
198
+ if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
199
+ {
200
+ $len = strspn($this->data, '0123456789.', 5);
201
+ $this->http_version = substr($this->data, 5, $len);
202
+ $this->position += 5 + $len;
203
+ if (substr_count($this->http_version, '.') <= 1)
204
+ {
205
+ $this->http_version = (float) $this->http_version;
206
+ $this->position += strspn($this->data, "\x09\x20", $this->position);
207
+ $this->state = 'status';
208
+ }
209
+ else
210
+ {
211
+ $this->state = false;
212
+ }
213
+ }
214
+ else
215
+ {
216
+ $this->state = false;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Parse the status code
222
+ */
223
+ protected function status()
224
+ {
225
+ if ($len = strspn($this->data, '0123456789', $this->position))
226
+ {
227
+ $this->status_code = (int) substr($this->data, $this->position, $len);
228
+ $this->position += $len;
229
+ $this->state = 'reason';
230
+ }
231
+ else
232
+ {
233
+ $this->state = false;
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Parse the reason phrase
239
+ */
240
+ protected function reason()
241
+ {
242
+ $len = strcspn($this->data, "\x0A", $this->position);
243
+ $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
244
+ $this->position += $len + 1;
245
+ $this->state = 'new_line';
246
+ }
247
+
248
+ /**
249
+ * Deal with a new line, shifting data around as needed
250
+ */
251
+ protected function new_line()
252
+ {
253
+ $this->value = trim($this->value, "\x0D\x20");
254
+ if ($this->name !== '' && $this->value !== '')
255
+ {
256
+ $this->name = strtolower($this->name);
257
+ // We should only use the last Content-Type header. c.f. issue #1
258
+ if (isset($this->headers[$this->name]) && $this->name !== 'content-type')
259
+ {
260
+ $this->headers[$this->name] .= ', ' . $this->value;
261
+ }
262
+ else
263
+ {
264
+ $this->headers[$this->name] = $this->value;
265
+ }
266
+ }
267
+ $this->name = '';
268
+ $this->value = '';
269
+ if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
270
+ {
271
+ $this->position += 2;
272
+ $this->state = 'body';
273
+ }
274
+ elseif ($this->data[$this->position] === "\x0A")
275
+ {
276
+ $this->position++;
277
+ $this->state = 'body';
278
+ }
279
+ else
280
+ {
281
+ $this->state = 'name';
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Parse a header name
287
+ */
288
+ protected function name()
289
+ {
290
+ $len = strcspn($this->data, "\x0A:", $this->position);
291
+ if (isset($this->data[$this->position + $len]))
292
+ {
293
+ if ($this->data[$this->position + $len] === "\x0A")
294
+ {
295
+ $this->position += $len;
296
+ $this->state = 'new_line';
297
+ }
298
+ else
299
+ {
300
+ $this->name = substr($this->data, $this->position, $len);
301
+ $this->position += $len + 1;
302
+ $this->state = 'value';
303
+ }
304
+ }
305
+ else
306
+ {
307
+ $this->state = false;
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Parse LWS, replacing consecutive LWS characters with a single space
313
+ */
314
+ protected function linear_whitespace()
315
+ {
316
+ do
317
+ {
318
+ if (substr($this->data, $this->position, 2) === "\x0D\x0A")
319
+ {
320
+ $this->position += 2;
321
+ }
322
+ elseif ($this->data[$this->position] === "\x0A")
323
+ {
324
+ $this->position++;
325
+ }
326
+ $this->position += strspn($this->data, "\x09\x20", $this->position);
327
+ } while ($this->has_data() && $this->is_linear_whitespace());
328
+ $this->value .= "\x20";
329
+ }
330
+
331
+ /**
332
+ * See what state to move to while within non-quoted header values
333
+ */
334
+ protected function value()
335
+ {
336
+ if ($this->is_linear_whitespace())
337
+ {
338
+ $this->linear_whitespace();
339
+ }
340
+ else
341
+ {
342
+ switch ($this->data[$this->position])
343
+ {
344
+ case '"':
345
+ // Workaround for ETags: we have to include the quotes as
346
+ // part of the tag.
347
+ if (strtolower($this->name) === 'etag')
348
+ {
349
+ $this->value .= '"';
350
+ $this->position++;
351
+ $this->state = 'value_char';
352
+ break;
353
+ }
354
+ $this->position++;
355
+ $this->state = 'quote';
356
+ break;
357
+
358
+ case "\x0A":
359
+ $this->position++;
360
+ $this->state = 'new_line';
361
+ break;
362
+
363
+ default:
364
+ $this->state = 'value_char';
365
+ break;
366
+ }
367
+ }
368
+ }
369
+
370
+ /**
371
+ * Parse a header value while outside quotes
372
+ */
373
+ protected function value_char()
374
+ {
375
+ $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
376
+ $this->value .= substr($this->data, $this->position, $len);
377
+ $this->position += $len;
378
+ $this->state = 'value';
379
+ }
380
+
381
+ /**
382
+ * See what state to move to while within quoted header values
383
+ */
384
+ protected function quote()
385
+ {
386
+ if ($this->is_linear_whitespace())
387
+ {
388
+ $this->linear_whitespace();
389
+ }
390
+ else
391
+ {
392
+ switch ($this->data[$this->position])
393
+ {
394
+ case '"':
395
+ $this->position++;
396
+ $this->state = 'value';
397
+ break;
398
+
399
+ case "\x0A":
400
+ $this->position++;
401
+ $this->state = 'new_line';
402
+ break;
403
+
404
+ case '\\':
405
+ $this->position++;
406
+ $this->state = 'quote_escaped';
407
+ break;
408
+
409
+ default:
410
+ $this->state = 'quote_char';
411
+ break;
412
+ }
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Parse a header value while within quotes
418
+ */
419
+ protected function quote_char()
420
+ {
421
+ $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
422
+ $this->value .= substr($this->data, $this->position, $len);
423
+ $this->position += $len;
424
+ $this->state = 'value';
425
+ }
426
+
427
+ /**
428
+ * Parse an escaped character within quotes
429
+ */
430
+ protected function quote_escaped()
431
+ {
432
+ $this->value .= $this->data[$this->position];
433
+ $this->position++;
434
+ $this->state = 'quote';
435
+ }
436
+
437
+ /**
438
+ * Parse the body
439
+ */
440
+ protected function body()
441
+ {
442
+ $this->body = substr($this->data, $this->position);
443
+ if (!empty($this->headers['transfer-encoding']))
444
+ {
445
+ unset($this->headers['transfer-encoding']);
446
+ $this->state = 'chunked';
447
+ }
448
+ else
449
+ {
450
+ $this->state = 'emit';
451
+ }
452
+ }
453
+
454
+ /**
455
+ * Parsed a "Transfer-Encoding: chunked" body
456
+ */
457
+ protected function chunked()
458
+ {
459
+ if (!preg_match('/^([0-9a-f]+)[^\r\n]*\r\n/i', trim($this->body)))
460
+ {
461
+ $this->state = 'emit';
462
+ return;
463
+ }
464
+
465
+ $decoded = '';
466
+ $encoded = $this->body;
467
+
468
+ while (true)
469
+ {
470
+ $is_chunked = (bool) preg_match( '/^([0-9a-f]+)[^\r\n]*\r\n/i', $encoded, $matches );
471
+ if (!$is_chunked)
472
+ {
473
+ // Looks like it's not chunked after all
474
+ $this->state = 'emit';
475
+ return;
476
+ }
477
+
478
+ $length = hexdec(trim($matches[1]));
479
+ if ($length === 0)
480
+ {
481
+ // Ignore trailer headers
482
+ $this->state = 'emit';
483
+ $this->body = $decoded;
484
+ return;
485
+ }
486
+
487
+ $chunk_length = strlen($matches[0]);
488
+ $decoded .= $part = substr($encoded, $chunk_length, $length);
489
+ $encoded = substr($encoded, $chunk_length + $length + 2);
490
+
491
+ if (trim($encoded) === '0' || empty($encoded))
492
+ {
493
+ $this->state = 'emit';
494
+ $this->body = $decoded;
495
+ return;
496
+ }
497
+ }
498
+ }
499
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/IRI.php ADDED
@@ -0,0 +1,1257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * IRI parser/serialiser/normaliser
46
+ *
47
+ * @package SimpleCluvPie
48
+ * @subpackage HTTP
49
+ * @author Geoffrey Sneddon
50
+ * @author Steve Minutillo
51
+ * @author Ryan McCue
52
+ * @copyright 2007-2012 Geoffrey Sneddon, Steve Minutillo, Ryan McCue
53
+ * @license http://www.opensource.org/licenses/bsd-license.php
54
+ */
55
+ class SimpleCluvPie_IRI
56
+ {
57
+ /**
58
+ * Scheme
59
+ *
60
+ * @var string
61
+ */
62
+ protected $scheme = null;
63
+
64
+ /**
65
+ * User Information
66
+ *
67
+ * @var string
68
+ */
69
+ protected $iuserinfo = null;
70
+
71
+ /**
72
+ * ihost
73
+ *
74
+ * @var string
75
+ */
76
+ protected $ihost = null;
77
+
78
+ /**
79
+ * Port
80
+ *
81
+ * @var string
82
+ */
83
+ protected $port = null;
84
+
85
+ /**
86
+ * ipath
87
+ *
88
+ * @var string
89
+ */
90
+ protected $ipath = '';
91
+
92
+ /**
93
+ * iquery
94
+ *
95
+ * @var string
96
+ */
97
+ protected $iquery = null;
98
+
99
+ /**
100
+ * ifragment
101
+ *
102
+ * @var string
103
+ */
104
+ protected $ifragment = null;
105
+
106
+ /**
107
+ * Normalization database
108
+ *
109
+ * Each key is the scheme, each value is an array with each key as the IRI
110
+ * part and value as the default value for that part.
111
+ */
112
+ protected $normalization = array(
113
+ 'acap' => array(
114
+ 'port' => 674
115
+ ),
116
+ 'dict' => array(
117
+ 'port' => 2628
118
+ ),
119
+ 'file' => array(
120
+ 'ihost' => 'localhost'
121
+ ),
122
+ 'http' => array(
123
+ 'port' => 80,
124
+ 'ipath' => '/'
125
+ ),
126
+ 'https' => array(
127
+ 'port' => 443,
128
+ 'ipath' => '/'
129
+ ),
130
+ );
131
+
132
+ /**
133
+ * Return the entire IRI when you try and read the object as a string
134
+ *
135
+ * @return string
136
+ */
137
+ public function __toString()
138
+ {
139
+ return $this->get_iri();
140
+ }
141
+
142
+ /**
143
+ * Overload __set() to provide access via properties
144
+ *
145
+ * @param string $name Property name
146
+ * @param mixed $value Property value
147
+ */
148
+ public function __set($name, $value)
149
+ {
150
+ if (method_exists($this, 'set_' . $name))
151
+ {
152
+ call_user_func(array($this, 'set_' . $name), $value);
153
+ }
154
+ elseif (
155
+ $name === 'iauthority'
156
+ || $name === 'iuserinfo'
157
+ || $name === 'ihost'
158
+ || $name === 'ipath'
159
+ || $name === 'iquery'
160
+ || $name === 'ifragment'
161
+ )
162
+ {
163
+ call_user_func(array($this, 'set_' . substr($name, 1)), $value);
164
+ }
165
+ }
166
+
167
+ /**
168
+ * Overload __get() to provide access via properties
169
+ *
170
+ * @param string $name Property name
171
+ * @return mixed
172
+ */
173
+ public function __get($name)
174
+ {
175
+ // isset() returns false for null, we don't want to do that
176
+ // Also why we use array_key_exists below instead of isset()
177
+ $props = get_object_vars($this);
178
+
179
+ if (
180
+ $name === 'iri' ||
181
+ $name === 'uri' ||
182
+ $name === 'iauthority' ||
183
+ $name === 'authority'
184
+ )
185
+ {
186
+ $return = $this->{"get_$name"}();
187
+ }
188
+ elseif (array_key_exists($name, $props))
189
+ {
190
+ $return = $this->$name;
191
+ }
192
+ // host -> ihost
193
+ elseif (($prop = 'i' . $name) && array_key_exists($prop, $props))
194
+ {
195
+ $name = $prop;
196
+ $return = $this->$prop;
197
+ }
198
+ // ischeme -> scheme
199
+ elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props))
200
+ {
201
+ $name = $prop;
202
+ $return = $this->$prop;
203
+ }
204
+ else
205
+ {
206
+ trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
207
+ $return = null;
208
+ }
209
+
210
+ if ($return === null && isset($this->normalization[$this->scheme][$name]))
211
+ {
212
+ return $this->normalization[$this->scheme][$name];
213
+ }
214
+ else
215
+ {
216
+ return $return;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Overload __isset() to provide access via properties
222
+ *
223
+ * @param string $name Property name
224
+ * @return bool
225
+ */
226
+ public function __isset($name)
227
+ {
228
+ if (method_exists($this, 'get_' . $name) || isset($this->$name))
229
+ {
230
+ return true;
231
+ }
232
+ else
233
+ {
234
+ return false;
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Overload __unset() to provide access via properties
240
+ *
241
+ * @param string $name Property name
242
+ */
243
+ public function __unset($name)
244
+ {
245
+ if (method_exists($this, 'set_' . $name))
246
+ {
247
+ call_user_func(array($this, 'set_' . $name), '');
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Create a new IRI object, from a specified string
253
+ *
254
+ * @param string $iri
255
+ */
256
+ public function __construct($iri = null)
257
+ {
258
+ $this->set_iri($iri);
259
+ }
260
+
261
+ /**
262
+ * Clean up
263
+ */
264
+ public function __destruct() {
265
+ $this->set_iri(null, true);
266
+ $this->set_path(null, true);
267
+ $this->set_authority(null, true);
268
+ }
269
+
270
+ /**
271
+ * Create a new IRI object by resolving a relative IRI
272
+ *
273
+ * Returns false if $base is not absolute, otherwise an IRI.
274
+ *
275
+ * @param IRI|string $base (Absolute) Base IRI
276
+ * @param IRI|string $relative Relative IRI
277
+ * @return IRI|false
278
+ */
279
+ public static function absolutize($base, $relative)
280
+ {
281
+ if (!($relative instanceof SimpleCluvPie_IRI))
282
+ {
283
+ $relative = new SimpleCluvPie_IRI($relative);
284
+ }
285
+ if (!$relative->is_valid())
286
+ {
287
+ return false;
288
+ }
289
+ elseif ($relative->scheme !== null)
290
+ {
291
+ return clone $relative;
292
+ }
293
+ else
294
+ {
295
+ if (!($base instanceof SimpleCluvPie_IRI))
296
+ {
297
+ $base = new SimpleCluvPie_IRI($base);
298
+ }
299
+ if ($base->scheme !== null && $base->is_valid())
300
+ {
301
+ if ($relative->get_iri() !== '')
302
+ {
303
+ if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null)
304
+ {
305
+ $target = clone $relative;
306
+ $target->scheme = $base->scheme;
307
+ }
308
+ else
309
+ {
310
+ $target = new SimpleCluvPie_IRI;
311
+ $target->scheme = $base->scheme;
312
+ $target->iuserinfo = $base->iuserinfo;
313
+ $target->ihost = $base->ihost;
314
+ $target->port = $base->port;
315
+ if ($relative->ipath !== '')
316
+ {
317
+ if ($relative->ipath[0] === '/')
318
+ {
319
+ $target->ipath = $relative->ipath;
320
+ }
321
+ elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '')
322
+ {
323
+ $target->ipath = '/' . $relative->ipath;
324
+ }
325
+ elseif (($last_segment = strrpos($base->ipath, '/')) !== false)
326
+ {
327
+ $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
328
+ }
329
+ else
330
+ {
331
+ $target->ipath = $relative->ipath;
332
+ }
333
+ $target->ipath = $target->remove_dot_segments($target->ipath);
334
+ $target->iquery = $relative->iquery;
335
+ }
336
+ else
337
+ {
338
+ $target->ipath = $base->ipath;
339
+ if ($relative->iquery !== null)
340
+ {
341
+ $target->iquery = $relative->iquery;
342
+ }
343
+ elseif ($base->iquery !== null)
344
+ {
345
+ $target->iquery = $base->iquery;
346
+ }
347
+ }
348
+ $target->ifragment = $relative->ifragment;
349
+ }
350
+ }
351
+ else
352
+ {
353
+ $target = clone $base;
354
+ $target->ifragment = null;
355
+ }
356
+ $target->scheme_normalization();
357
+ return $target;
358
+ }
359
+ else
360
+ {
361
+ return false;
362
+ }
363
+ }
364
+ }
365
+
366
+ /**
367
+ * Parse an IRI into scheme/authority/path/query/fragment segments
368
+ *
369
+ * @param string $iri
370
+ * @return array
371
+ */
372
+ protected function parse_iri($iri)
373
+ {
374
+ $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
375
+ if (preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match))
376
+ {
377
+ if ($match[1] === '')
378
+ {
379
+ $match['scheme'] = null;
380
+ }
381
+ if (!isset($match[3]) || $match[3] === '')
382
+ {
383
+ $match['authority'] = null;
384
+ }
385
+ if (!isset($match[5]))
386
+ {
387
+ $match['path'] = '';
388
+ }
389
+ if (!isset($match[6]) || $match[6] === '')
390
+ {
391
+ $match['query'] = null;
392
+ }
393
+ if (!isset($match[8]) || $match[8] === '')
394
+ {
395
+ $match['fragment'] = null;
396
+ }
397
+ return $match;
398
+ }
399
+ else
400
+ {
401
+ // This can occur when a paragraph is accidentally parsed as a URI
402
+ return false;
403
+ }
404
+ }
405
+
406
+ /**
407
+ * Remove dot segments from a path
408
+ *
409
+ * @param string $input
410
+ * @return string
411
+ */
412
+ protected function remove_dot_segments($input)
413
+ {
414
+ $output = '';
415
+ while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
416
+ {
417
+ // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
418
+ if (strpos($input, '../') === 0)
419
+ {
420
+ $input = substr($input, 3);
421
+ }
422
+ elseif (strpos($input, './') === 0)
423
+ {
424
+ $input = substr($input, 2);
425
+ }
426
+ // 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,
427
+ elseif (strpos($input, '/./') === 0)
428
+ {
429
+ $input = substr($input, 2);
430
+ }
431
+ elseif ($input === '/.')
432
+ {
433
+ $input = '/';
434
+ }
435
+ // 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,
436
+ elseif (strpos($input, '/../') === 0)
437
+ {
438
+ $input = substr($input, 3);
439
+ $output = substr_replace($output, '', strrpos($output, '/'));
440
+ }
441
+ elseif ($input === '/..')
442
+ {
443
+ $input = '/';
444
+ $output = substr_replace($output, '', strrpos($output, '/'));
445
+ }
446
+ // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
447
+ elseif ($input === '.' || $input === '..')
448
+ {
449
+ $input = '';
450
+ }
451
+ // 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
452
+ elseif (($pos = strpos($input, '/', 1)) !== false)
453
+ {
454
+ $output .= substr($input, 0, $pos);
455
+ $input = substr_replace($input, '', 0, $pos);
456
+ }
457
+ else
458
+ {
459
+ $output .= $input;
460
+ $input = '';
461
+ }
462
+ }
463
+ return $output . $input;
464
+ }
465
+
466
+ /**
467
+ * Replace invalid character with percent encoding
468
+ *
469
+ * @param string $string Input string
470
+ * @param string $extra_chars Valid characters not in iunreserved or
471
+ * iprivate (this is ASCII-only)
472
+ * @param bool $iprivate Allow iprivate
473
+ * @return string
474
+ */
475
+ protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false)
476
+ {
477
+ // Normalize as many pct-encoded sections as possible
478
+ $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $string);
479
+
480
+ // Replace invalid percent characters
481
+ $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
482
+
483
+ // Add unreserved and % to $extra_chars (the latter is safe because all
484
+ // pct-encoded sections are now valid).
485
+ $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
486
+
487
+ // Now replace any bytes that aren't allowed with their pct-encoded versions
488
+ $position = 0;
489
+ $strlen = strlen($string);
490
+ while (($position += strspn($string, $extra_chars, $position)) < $strlen)
491
+ {
492
+ $value = ord($string[$position]);
493
+
494
+ // Start position
495
+ $start = $position;
496
+
497
+ // By default we are valid
498
+ $valid = true;
499
+
500
+ // No one byte sequences are valid due to the while.
501
+ // Two byte sequence:
502
+ if (($value & 0xE0) === 0xC0)
503
+ {
504
+ $character = ($value & 0x1F) << 6;
505
+ $length = 2;
506
+ $remaining = 1;
507
+ }
508
+ // Three byte sequence:
509
+ elseif (($value & 0xF0) === 0xE0)
510
+ {
511
+ $character = ($value & 0x0F) << 12;
512
+ $length = 3;
513
+ $remaining = 2;
514
+ }
515
+ // Four byte sequence:
516
+ elseif (($value & 0xF8) === 0xF0)
517
+ {
518
+ $character = ($value & 0x07) << 18;
519
+ $length = 4;
520
+ $remaining = 3;
521
+ }
522
+ // Invalid byte:
523
+ else
524
+ {
525
+ $valid = false;
526
+ $length = 1;
527
+ $remaining = 0;
528
+ }
529
+
530
+ if ($remaining)
531
+ {
532
+ if ($position + $length <= $strlen)
533
+ {
534
+ for ($position++; $remaining; $position++)
535
+ {
536
+ $value = ord($string[$position]);
537
+
538
+ // Check that the byte is valid, then add it to the character:
539
+ if (($value & 0xC0) === 0x80)
540
+ {
541
+ $character |= ($value & 0x3F) << (--$remaining * 6);
542
+ }
543
+ // If it is invalid, count the sequence as invalid and reprocess the current byte:
544
+ else
545
+ {
546
+ $valid = false;
547
+ $position--;
548
+ break;
549
+ }
550
+ }
551
+ }
552
+ else
553
+ {
554
+ $position = $strlen - 1;
555
+ $valid = false;
556
+ }
557
+ }
558
+
559
+ // Percent encode anything invalid or not in ucschar
560
+ if (
561
+ // Invalid sequences
562
+ !$valid
563
+ // Non-shortest form sequences are invalid
564
+ || $length > 1 && $character <= 0x7F
565
+ || $length > 2 && $character <= 0x7FF
566
+ || $length > 3 && $character <= 0xFFFF
567
+ // Outside of range of ucschar codepoints
568
+ // Noncharacters
569
+ || ($character & 0xFFFE) === 0xFFFE
570
+ || $character >= 0xFDD0 && $character <= 0xFDEF
571
+ || (
572
+ // Everything else not in ucschar
573
+ $character > 0xD7FF && $character < 0xF900
574
+ || $character < 0xA0
575
+ || $character > 0xEFFFD
576
+ )
577
+ && (
578
+ // Everything not in iprivate, if it applies
579
+ !$iprivate
580
+ || $character < 0xE000
581
+ || $character > 0x10FFFD
582
+ )
583
+ )
584
+ {
585
+ // If we were a character, pretend we weren't, but rather an error.
586
+ if ($valid)
587
+ $position--;
588
+
589
+ for ($j = $start; $j <= $position; $j++)
590
+ {
591
+ $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
592
+ $j += 2;
593
+ $position += 2;
594
+ $strlen += 2;
595
+ }
596
+ }
597
+ }
598
+
599
+ return $string;
600
+ }
601
+
602
+ /**
603
+ * Callback function for preg_replace_callback.
604
+ *
605
+ * Removes sequences of percent encoded bytes that represent UTF-8
606
+ * encoded characters in iunreserved
607
+ *
608
+ * @param array $match PCRE match
609
+ * @return string Replacement
610
+ */
611
+ protected function remove_iunreserved_percent_encoded($match)
612
+ {
613
+ // As we just have valid percent encoded sequences we can just explode
614
+ // and ignore the first member of the returned array (an empty string).
615
+ $bytes = explode('%', $match[0]);
616
+
617
+ // Initialize the new string (this is what will be returned) and that
618
+ // there are no bytes remaining in the current sequence (unsurprising
619
+ // at the first byte!).
620
+ $string = '';
621
+ $remaining = 0;
622
+
623
+ // Loop over each and every byte, and set $value to its value
624
+ for ($i = 1, $len = count($bytes); $i < $len; $i++)
625
+ {
626
+ $value = hexdec($bytes[$i]);
627
+
628
+ // If we're the first byte of sequence:
629
+ if (!$remaining)
630
+ {
631
+ // Start position
632
+ $start = $i;
633
+
634
+ // By default we are valid
635
+ $valid = true;
636
+
637
+ // One byte sequence:
638
+ if ($value <= 0x7F)
639
+ {
640
+ $character = $value;
641
+ $length = 1;
642
+ }
643
+ // Two byte sequence:
644
+ elseif (($value & 0xE0) === 0xC0)
645
+ {
646
+ $character = ($value & 0x1F) << 6;
647
+ $length = 2;
648
+ $remaining = 1;
649
+ }
650
+ // Three byte sequence:
651
+ elseif (($value & 0xF0) === 0xE0)
652
+ {
653
+ $character = ($value & 0x0F) << 12;
654
+ $length = 3;
655
+ $remaining = 2;
656
+ }
657
+ // Four byte sequence:
658
+ elseif (($value & 0xF8) === 0xF0)
659
+ {
660
+ $character = ($value & 0x07) << 18;
661
+ $length = 4;
662
+ $remaining = 3;
663
+ }
664
+ // Invalid byte:
665
+ else
666
+ {
667
+ $valid = false;
668
+ $remaining = 0;
669
+ }
670
+ }
671
+ // Continuation byte:
672
+ else
673
+ {
674
+ // Check that the byte is valid, then add it to the character:
675
+ if (($value & 0xC0) === 0x80)
676
+ {
677
+ $remaining--;
678
+ $character |= ($value & 0x3F) << ($remaining * 6);
679
+ }
680
+ // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
681
+ else
682
+ {
683
+ $valid = false;
684
+ $remaining = 0;
685
+ $i--;
686
+ }
687
+ }
688
+
689
+ // If we've reached the end of the current byte sequence, append it to Unicode::$data
690
+ if (!$remaining)
691
+ {
692
+ // Percent encode anything invalid or not in iunreserved
693
+ if (
694
+ // Invalid sequences
695
+ !$valid
696
+ // Non-shortest form sequences are invalid
697
+ || $length > 1 && $character <= 0x7F
698
+ || $length > 2 && $character <= 0x7FF
699
+ || $length > 3 && $character <= 0xFFFF
700
+ // Outside of range of iunreserved codepoints
701
+ || $character < 0x2D
702
+ || $character > 0xEFFFD
703
+ // Noncharacters
704
+ || ($character & 0xFFFE) === 0xFFFE
705
+ || $character >= 0xFDD0 && $character <= 0xFDEF
706
+ // Everything else not in iunreserved (this is all BMP)
707
+ || $character === 0x2F
708
+ || $character > 0x39 && $character < 0x41
709
+ || $character > 0x5A && $character < 0x61
710
+ || $character > 0x7A && $character < 0x7E
711
+ || $character > 0x7E && $character < 0xA0
712
+ || $character > 0xD7FF && $character < 0xF900
713
+ )
714
+ {
715
+ for ($j = $start; $j <= $i; $j++)
716
+ {
717
+ $string .= '%' . strtoupper($bytes[$j]);
718
+ }
719
+ }
720
+ else
721
+ {
722
+ for ($j = $start; $j <= $i; $j++)
723
+ {
724
+ $string .= chr(hexdec($bytes[$j]));
725
+ }
726
+ }
727
+ }
728
+ }
729
+
730
+ // If we have any bytes left over they are invalid (i.e., we are
731
+ // mid-way through a multi-byte sequence)
732
+ if ($remaining)
733
+ {
734
+ for ($j = $start; $j < $len; $j++)
735
+ {
736
+ $string .= '%' . strtoupper($bytes[$j]);
737
+ }
738
+ }
739
+
740
+ return $string;
741
+ }
742
+
743
+ protected function scheme_normalization()
744
+ {
745
+ if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo'])
746
+ {
747
+ $this->iuserinfo = null;
748
+ }
749
+ if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost'])
750
+ {
751
+ $this->ihost = null;
752
+ }
753
+ if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port'])
754
+ {
755
+ $this->port = null;
756
+ }
757
+ if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath'])
758
+ {
759
+ $this->ipath = '';
760
+ }
761
+ if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery'])
762
+ {
763
+ $this->iquery = null;
764
+ }
765
+ if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment'])
766
+ {
767
+ $this->ifragment = null;
768
+ }
769
+ }
770
+
771
+ /**
772
+ * Check if the object represents a valid IRI. This needs to be done on each
773
+ * call as some things change depending on another part of the IRI.
774
+ *
775
+ * @return bool
776
+ */
777
+ public function is_valid()
778
+ {
779
+ if ($this->ipath === '') return true;
780
+
781
+ $isauthority = $this->iuserinfo !== null || $this->ihost !== null ||
782
+ $this->port !== null;
783
+ if ($isauthority && $this->ipath[0] === '/') return true;
784
+
785
+ if (!$isauthority && (substr($this->ipath, 0, 2) === '//')) return false;
786
+
787
+ // Relative urls cannot have a colon in the first path segment (and the
788
+ // slashes themselves are not included so skip the first character).
789
+ if (!$this->scheme && !$isauthority &&
790
+ strpos($this->ipath, ':') !== false &&
791
+ strpos($this->ipath, '/', 1) !== false &&
792
+ strpos($this->ipath, ':') < strpos($this->ipath, '/', 1)) return false;
793
+
794
+ return true;
795
+ }
796
+
797
+ /**
798
+ * Set the entire IRI. Returns true on success, false on failure (if there
799
+ * are any invalid characters).
800
+ *
801
+ * @param string $iri
802
+ * @return bool
803
+ */
804
+ public function set_iri($iri, $clear_cache = false)
805
+ {
806
+ static $cache;
807
+ if ($clear_cache)
808
+ {
809
+ $cache = null;
810
+ return;
811
+ }
812
+ if (!$cache)
813
+ {
814
+ $cache = array();
815
+ }
816
+
817
+ if ($iri === null)
818
+ {
819
+ return true;
820
+ }
821
+ elseif (isset($cache[$iri]))
822
+ {
823
+ list($this->scheme,
824
+ $this->iuserinfo,
825
+ $this->ihost,
826
+ $this->port,
827
+ $this->ipath,
828
+ $this->iquery,
829
+ $this->ifragment,
830
+ $return) = $cache[$iri];
831
+ return $return;
832
+ }
833
+ else
834
+ {
835
+ $parsed = $this->parse_iri((string) $iri);
836
+ if (!$parsed)
837
+ {
838
+ return false;
839
+ }
840
+
841
+ $return = $this->set_scheme($parsed['scheme'])
842
+ && $this->set_authority($parsed['authority'])
843
+ && $this->set_path($parsed['path'])
844
+ && $this->set_query($parsed['query'])
845
+ && $this->set_fragment($parsed['fragment']);
846
+
847
+ $cache[$iri] = array($this->scheme,
848
+ $this->iuserinfo,
849
+ $this->ihost,
850
+ $this->port,
851
+ $this->ipath,
852
+ $this->iquery,
853
+ $this->ifragment,
854
+ $return);
855
+ return $return;
856
+ }
857
+ }
858
+
859
+ /**
860
+ * Set the scheme. Returns true on success, false on failure (if there are
861
+ * any invalid characters).
862
+ *
863
+ * @param string $scheme
864
+ * @return bool
865
+ */
866
+ public function set_scheme($scheme)
867
+ {
868
+ if ($scheme === null)
869
+ {
870
+ $this->scheme = null;
871
+ }
872
+ elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme))
873
+ {
874
+ $this->scheme = null;
875
+ return false;
876
+ }
877
+ else
878
+ {
879
+ $this->scheme = strtolower($scheme);
880
+ }
881
+ return true;
882
+ }
883
+
884
+ /**
885
+ * Set the authority. Returns true on success, false on failure (if there are
886
+ * any invalid characters).
887
+ *
888
+ * @param string $authority
889
+ * @return bool
890
+ */
891
+ public function set_authority($authority, $clear_cache = false)
892
+ {
893
+ static $cache;
894
+ if ($clear_cache)
895
+ {
896
+ $cache = null;
897
+ return;
898
+ }
899
+ if (!$cache)
900
+ $cache = array();
901
+
902
+ if ($authority === null)
903
+ {
904
+ $this->iuserinfo = null;
905
+ $this->ihost = null;
906
+ $this->port = null;
907
+ return true;
908
+ }
909
+ elseif (isset($cache[$authority]))
910
+ {
911
+ list($this->iuserinfo,
912
+ $this->ihost,
913
+ $this->port,
914
+ $return) = $cache[$authority];
915
+
916
+ return $return;
917
+ }
918
+ else
919
+ {
920
+ $remaining = $authority;
921
+ if (($iuserinfo_end = strrpos($remaining, '@')) !== false)
922
+ {
923
+ $iuserinfo = substr($remaining, 0, $iuserinfo_end);
924
+ $remaining = substr($remaining, $iuserinfo_end + 1);
925
+ }
926
+ else
927
+ {
928
+ $iuserinfo = null;
929
+ }
930
+ if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false)
931
+ {
932
+ if (($port = substr($remaining, $port_start + 1)) === false)
933
+ {
934
+ $port = null;
935
+ }
936
+ $remaining = substr($remaining, 0, $port_start);
937
+ }
938
+ else
939
+ {
940
+ $port = null;
941
+ }
942
+
943
+ $return = $this->set_userinfo($iuserinfo) &&
944
+ $this->set_host($remaining) &&
945
+ $this->set_port($port);
946
+
947
+ $cache[$authority] = array($this->iuserinfo,
948
+ $this->ihost,
949
+ $this->port,
950
+ $return);
951
+
952
+ return $return;
953
+ }
954
+ }
955
+
956
+ /**
957
+ * Set the iuserinfo.
958
+ *
959
+ * @param string $iuserinfo
960
+ * @return bool
961
+ */
962
+ public function set_userinfo($iuserinfo)
963
+ {
964
+ if ($iuserinfo === null)
965
+ {
966
+ $this->iuserinfo = null;
967
+ }
968
+ else
969
+ {
970
+ $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
971
+ $this->scheme_normalization();
972
+ }
973
+
974
+ return true;
975
+ }
976
+
977
+ /**
978
+ * Set the ihost. Returns true on success, false on failure (if there are
979
+ * any invalid characters).
980
+ *
981
+ * @param string $ihost
982
+ * @return bool
983
+ */
984
+ public function set_host($ihost)
985
+ {
986
+ if ($ihost === null)
987
+ {
988
+ $this->ihost = null;
989
+ return true;
990
+ }
991
+ elseif (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']')
992
+ {
993
+ if (SimpleCluvPie_Net_IPv6::check_ipv6(substr($ihost, 1, -1)))
994
+ {
995
+ $this->ihost = '[' . SimpleCluvPie_Net_IPv6::compress(substr($ihost, 1, -1)) . ']';
996
+ }
997
+ else
998
+ {
999
+ $this->ihost = null;
1000
+ return false;
1001
+ }
1002
+ }
1003
+ else
1004
+ {
1005
+ $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
1006
+
1007
+ // Lowercase, but ignore pct-encoded sections (as they should
1008
+ // remain uppercase). This must be done after the previous step
1009
+ // as that can add unescaped characters.
1010
+ $position = 0;
1011
+ $strlen = strlen($ihost);
1012
+ while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen)
1013
+ {
1014
+ if ($ihost[$position] === '%')
1015
+ {
1016
+ $position += 3;
1017
+ }
1018
+ else
1019
+ {
1020
+ $ihost[$position] = strtolower($ihost[$position]);
1021
+ $position++;
1022
+ }
1023
+ }
1024
+
1025
+ $this->ihost = $ihost;
1026
+ }
1027
+
1028
+ $this->scheme_normalization();
1029
+
1030
+ return true;
1031
+ }
1032
+
1033
+ /**
1034
+ * Set the port. Returns true on success, false on failure (if there are
1035
+ * any invalid characters).
1036
+ *
1037
+ * @param string $port
1038
+ * @return bool
1039
+ */
1040
+ public function set_port($port)
1041
+ {
1042
+ if ($port === null)
1043
+ {
1044
+ $this->port = null;
1045
+ return true;
1046
+ }
1047
+ elseif (strspn($port, '0123456789') === strlen($port))
1048
+ {
1049
+ $this->port = (int) $port;
1050
+ $this->scheme_normalization();
1051
+ return true;
1052
+ }
1053
+ else
1054
+ {
1055
+ $this->port = null;
1056
+ return false;
1057
+ }
1058
+ }
1059
+
1060
+ /**
1061
+ * Set the ipath.
1062
+ *
1063
+ * @param string $ipath
1064
+ * @return bool
1065
+ */
1066
+ public function set_path($ipath, $clear_cache = false)
1067
+ {
1068
+ static $cache;
1069
+ if ($clear_cache)
1070
+ {
1071
+ $cache = null;
1072
+ return;
1073
+ }
1074
+ if (!$cache)
1075
+ {
1076
+ $cache = array();
1077
+ }
1078
+
1079
+ $ipath = (string) $ipath;
1080
+
1081
+ if (isset($cache[$ipath]))
1082
+ {
1083
+ $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
1084
+ }
1085
+ else
1086
+ {
1087
+ $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
1088
+ $removed = $this->remove_dot_segments($valid);
1089
+
1090
+ $cache[$ipath] = array($valid, $removed);
1091
+ $this->ipath = ($this->scheme !== null) ? $removed : $valid;
1092
+ }
1093
+
1094
+ $this->scheme_normalization();
1095
+ return true;
1096
+ }
1097
+
1098
+ /**
1099
+ * Set the iquery.
1100
+ *
1101
+ * @param string $iquery
1102
+ * @return bool
1103
+ */
1104
+ public function set_query($iquery)
1105
+ {
1106
+ if ($iquery === null)
1107
+ {
1108
+ $this->iquery = null;
1109
+ }
1110
+ else
1111
+ {
1112
+ $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
1113
+ $this->scheme_normalization();
1114
+ }
1115
+ return true;
1116
+ }
1117
+
1118
+ /**
1119
+ * Set the ifragment.
1120
+ *
1121
+ * @param string $ifragment
1122
+ * @return bool
1123
+ */
1124
+ public function set_fragment($ifragment)
1125
+ {
1126
+ if ($ifragment === null)
1127
+ {
1128
+ $this->ifragment = null;
1129
+ }
1130
+ else
1131
+ {
1132
+ $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
1133
+ $this->scheme_normalization();
1134
+ }
1135
+ return true;
1136
+ }
1137
+
1138
+ /**
1139
+ * Convert an IRI to a URI (or parts thereof)
1140
+ *
1141
+ * @return string
1142
+ */
1143
+ public function to_uri($string)
1144
+ {
1145
+ static $non_ascii;
1146
+ if (!$non_ascii)
1147
+ {
1148
+ $non_ascii = implode('', range("\x80", "\xFF"));
1149
+ }
1150
+
1151
+ $position = 0;
1152
+ $strlen = strlen($string);
1153
+ while (($position += strcspn($string, $non_ascii, $position)) < $strlen)
1154
+ {
1155
+ $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
1156
+ $position += 3;
1157
+ $strlen += 2;
1158
+ }
1159
+
1160
+ return $string;
1161
+ }
1162
+
1163
+ /**
1164
+ * Get the complete IRI
1165
+ *
1166
+ * @return string
1167
+ */
1168
+ public function get_iri()
1169
+ {
1170
+ if (!$this->is_valid())
1171
+ {
1172
+ return false;
1173
+ }
1174
+
1175
+ $iri = '';
1176
+ if ($this->scheme !== null)
1177
+ {
1178
+ $iri .= $this->scheme . ':';
1179
+ }
1180
+ if (($iauthority = $this->get_iauthority()) !== null)
1181
+ {
1182
+ $iri .= '//' . $iauthority;
1183
+ }
1184
+ if ($this->ipath !== '')
1185
+ {
1186
+ $iri .= $this->ipath;
1187
+ }
1188
+ elseif (!empty($this->normalization[$this->scheme]['ipath']) && $iauthority !== null && $iauthority !== '')
1189
+ {
1190
+ $iri .= $this->normalization[$this->scheme]['ipath'];
1191
+ }
1192
+ if ($this->iquery !== null)
1193
+ {
1194
+ $iri .= '?' . $this->iquery;
1195
+ }
1196
+ if ($this->ifragment !== null)
1197
+ {
1198
+ $iri .= '#' . $this->ifragment;
1199
+ }
1200
+
1201
+ return $iri;
1202
+ }
1203
+
1204
+ /**
1205
+ * Get the complete URI
1206
+ *
1207
+ * @return string
1208
+ */
1209
+ public function get_uri()
1210
+ {
1211
+ return $this->to_uri($this->get_iri());
1212
+ }
1213
+
1214
+ /**
1215
+ * Get the complete iauthority
1216
+ *
1217
+ * @return string
1218
+ */
1219
+ protected function get_iauthority()
1220
+ {
1221
+ if ($this->iuserinfo !== null || $this->ihost !== null || $this->port !== null)
1222
+ {
1223
+ $iauthority = '';
1224
+ if ($this->iuserinfo !== null)
1225
+ {
1226
+ $iauthority .= $this->iuserinfo . '@';
1227
+ }
1228
+ if ($this->ihost !== null)
1229
+ {
1230
+ $iauthority .= $this->ihost;
1231
+ }
1232
+ if ($this->port !== null)
1233
+ {
1234
+ $iauthority .= ':' . $this->port;
1235
+ }
1236
+ return $iauthority;
1237
+ }
1238
+ else
1239
+ {
1240
+ return null;
1241
+ }
1242
+ }
1243
+
1244
+ /**
1245
+ * Get the complete authority
1246
+ *
1247
+ * @return string
1248
+ */
1249
+ protected function get_authority()
1250
+ {
1251
+ $iauthority = $this->get_iauthority();
1252
+ if (is_string($iauthority))
1253
+ return $this->to_uri($iauthority);
1254
+ else
1255
+ return $iauthority;
1256
+ }
1257
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Item.php ADDED
@@ -0,0 +1,2977 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Manages all item-related data
47
+ *
48
+ * Used by {@see SimpleCluvPie::get_item()} and {@see SimpleCluvPie::get_items()}
49
+ *
50
+ * This class can be overloaded with {@see SimpleCluvPie::set_item_class()}
51
+ *
52
+ * @package SimpleCluvPie
53
+ * @subpackage API
54
+ */
55
+ class SimpleCluvPie_Item
56
+ {
57
+ /**
58
+ * Parent feed
59
+ *
60
+ * @access private
61
+ * @var SimpleCluvPie
62
+ */
63
+ var $feed;
64
+
65
+ /**
66
+ * Raw data
67
+ *
68
+ * @access private
69
+ * @var array
70
+ */
71
+ var $data = array();
72
+
73
+ /**
74
+ * Registry object
75
+ *
76
+ * @see set_registry
77
+ * @var SimpleCluvPie_Registry
78
+ */
79
+ protected $registry;
80
+
81
+ /**
82
+ * Create a new item object
83
+ *
84
+ * This is usually used by {@see SimpleCluvPie::get_items} and
85
+ * {@see SimpleCluvPie::get_item}. Avoid creating this manually.
86
+ *
87
+ * @param SimpleCluvPie $feed Parent feed
88
+ * @param array $data Raw data
89
+ */
90
+ public function __construct($feed, $data)
91
+ {
92
+ $this->feed = $feed;
93
+ $this->data = $data;
94
+ }
95
+
96
+ /**
97
+ * Set the registry handler
98
+ *
99
+ * This is usually used by {@see SimpleCluvPie_Registry::create}
100
+ *
101
+ * @since 1.3
102
+ * @param SimpleCluvPie_Registry $registry
103
+ */
104
+ public function set_registry(SimpleCluvPie_Registry $registry)
105
+ {
106
+ $this->registry = $registry;
107
+ }
108
+
109
+ /**
110
+ * Get a string representation of the item
111
+ *
112
+ * @return string
113
+ */
114
+ public function __toString()
115
+ {
116
+ return md5(serialize($this->data));
117
+ }
118
+
119
+ /**
120
+ * Remove items that link back to this before destroying this object
121
+ */
122
+ public function __destruct()
123
+ {
124
+ if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
125
+ {
126
+ unset($this->feed);
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Get data for an item-level element
132
+ *
133
+ * This method allows you to get access to ANY element/attribute that is a
134
+ * sub-element of the item/entry tag.
135
+ *
136
+ * See {@see SimpleCluvPie::get_feed_tags()} for a description of the return value
137
+ *
138
+ * @since 1.0
139
+ * @see http://simplecluvpie.org/wiki/faq/supported_xml_namespaces
140
+ * @param string $namespace The URL of the XML namespace of the elements you're trying to access
141
+ * @param string $tag Tag name
142
+ * @return array
143
+ */
144
+ public function get_item_tags($namespace, $tag)
145
+ {
146
+ if (isset($this->data['child'][$namespace][$tag]))
147
+ {
148
+ return $this->data['child'][$namespace][$tag];
149
+ }
150
+ else
151
+ {
152
+ return null;
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Get the base URL value from the parent feed
158
+ *
159
+ * Uses `<xml:base>`
160
+ *
161
+ * @param array $element
162
+ * @return string
163
+ */
164
+ public function get_base($element = array())
165
+ {
166
+ return $this->feed->get_base($element);
167
+ }
168
+
169
+ /**
170
+ * Sanitize feed data
171
+ *
172
+ * @access private
173
+ * @see SimpleCluvPie::sanitize()
174
+ * @param string $data Data to sanitize
175
+ * @param int $type One of the SIMPLECLUVPIE_CONSTRUCT_* constants
176
+ * @param string $base Base URL to resolve URLs against
177
+ * @return string Sanitized data
178
+ */
179
+ public function sanitize($data, $type, $base = '')
180
+ {
181
+ return $this->feed->sanitize($data, $type, $base);
182
+ }
183
+
184
+ /**
185
+ * Get the parent feed
186
+ *
187
+ * Note: this may not work as you think for multifeeds!
188
+ *
189
+ * @link http://simplecluvpie.org/faq/typical_multifeed_gotchas#missing_data_from_feed
190
+ * @since 1.0
191
+ * @return SimpleCluvPie
192
+ */
193
+ public function get_feed()
194
+ {
195
+ return $this->feed;
196
+ }
197
+
198
+ /**
199
+ * Get the unique identifier for the item
200
+ *
201
+ * This is usually used when writing code to check for new items in a feed.
202
+ *
203
+ * Uses `<atom:id>`, `<guid>`, `<dc:identifier>` or the `about` attribute
204
+ * for RDF. If none of these are supplied (or `$hash` is true), creates an
205
+ * MD5 hash based on the permalink, title and content.
206
+ *
207
+ * @since Beta 2
208
+ * @param boolean $hash Should we force using a hash instead of the supplied ID?
209
+ * @return string
210
+ */
211
+ public function get_id($hash = false, $fn = '')
212
+ {
213
+ if (!$hash)
214
+ {
215
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'id'))
216
+ {
217
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
218
+ }
219
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'id'))
220
+ {
221
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
222
+ }
223
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'guid'))
224
+ {
225
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
226
+ }
227
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'identifier'))
228
+ {
229
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
230
+ }
231
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'identifier'))
232
+ {
233
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
234
+ }
235
+ elseif (isset($this->data['attribs'][SIMPLECLUVPIE_NAMESPACE_RDF]['about']))
236
+ {
237
+ return $this->sanitize($this->data['attribs'][SIMPLECLUVPIE_NAMESPACE_RDF]['about'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
238
+ }
239
+ }
240
+ if ($fn === '' || !is_callable($fn)) $fn = 'md5';
241
+ return call_user_func($fn,
242
+ $this->get_permalink().$this->get_title().$this->get_content());
243
+ }
244
+
245
+ /**
246
+ * Get the title of the item
247
+ *
248
+ * Uses `<atom:title>`, `<title>` or `<dc:title>`
249
+ *
250
+ * @since Beta 2 (previously called `get_item_title` since 0.8)
251
+ * @return string|null
252
+ */
253
+ public function get_title()
254
+ {
255
+ if (!isset($this->data['title']))
256
+ {
257
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'title'))
258
+ {
259
+ $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
260
+ }
261
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'title'))
262
+ {
263
+ $this->data['title'] = $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
264
+ }
265
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'title'))
266
+ {
267
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
268
+ }
269
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'title'))
270
+ {
271
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
272
+ }
273
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'title'))
274
+ {
275
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
276
+ }
277
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'title'))
278
+ {
279
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
280
+ }
281
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'title'))
282
+ {
283
+ $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
284
+ }
285
+ else
286
+ {
287
+ $this->data['title'] = null;
288
+ }
289
+ }
290
+ return $this->data['title'];
291
+ }
292
+
293
+ /**
294
+ * Get the content for the item
295
+ *
296
+ * Prefers summaries over full content , but will return full content if a
297
+ * summary does not exist.
298
+ *
299
+ * To prefer full content instead, use {@see get_content}
300
+ *
301
+ * Uses `<atom:summary>`, `<description>`, `<dc:description>` or
302
+ * `<itunes:subtitle>`
303
+ *
304
+ * @since 0.8
305
+ * @param boolean $description_only Should we avoid falling back to the content?
306
+ * @return string|null
307
+ */
308
+ public function get_description($description_only = false)
309
+ {
310
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'summary'))
311
+ {
312
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
313
+ }
314
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'summary'))
315
+ {
316
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
317
+ }
318
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'description'))
319
+ {
320
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
321
+ }
322
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'description'))
323
+ {
324
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
325
+ }
326
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'description'))
327
+ {
328
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
329
+ }
330
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'description'))
331
+ {
332
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
333
+ }
334
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'summary'))
335
+ {
336
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
337
+ }
338
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'subtitle'))
339
+ {
340
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
341
+ }
342
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'description'))
343
+ {
344
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
345
+ }
346
+
347
+ elseif (!$description_only)
348
+ {
349
+ return $this->get_content(true);
350
+ }
351
+ else
352
+ {
353
+ return null;
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Get the content for the item
359
+ *
360
+ * Prefers full content over summaries, but will return a summary if full
361
+ * content does not exist.
362
+ *
363
+ * To prefer summaries instead, use {@see get_description}
364
+ *
365
+ * Uses `<atom:content>` or `<content:encoded>` (RSS 1.0 Content Module)
366
+ *
367
+ * @since 1.0
368
+ * @param boolean $content_only Should we avoid falling back to the description?
369
+ * @return string|null
370
+ */
371
+ public function get_content($content_only = false)
372
+ {
373
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'content'))
374
+ {
375
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_content_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
376
+ }
377
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'content'))
378
+ {
379
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
380
+ }
381
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
382
+ {
383
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
384
+ }
385
+ elseif (!$content_only)
386
+ {
387
+ return $this->get_description(true);
388
+ }
389
+ else
390
+ {
391
+ return null;
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Get the media:thumbnail of the item
397
+ *
398
+ * Uses `<media:thumbnail>`
399
+ *
400
+ *
401
+ * @return array|null
402
+ */
403
+ public function get_thumbnail()
404
+ {
405
+ if (!isset($this->data['thumbnail']))
406
+ {
407
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
408
+ {
409
+ $this->data['thumbnail'] = $return[0]['attribs'][''];
410
+ }
411
+ else
412
+ {
413
+ $this->data['thumbnail'] = null;
414
+ }
415
+ }
416
+ return $this->data['thumbnail'];
417
+ }
418
+
419
+ /**
420
+ * Get a category for the item
421
+ *
422
+ * @since Beta 3 (previously called `get_categories()` since Beta 2)
423
+ * @param int $key The category that you want to return. Remember that arrays begin with 0, not 1
424
+ * @return SimpleCluvPie_Category|null
425
+ */
426
+ public function get_category($key = 0)
427
+ {
428
+ $categories = $this->get_categories();
429
+ if (isset($categories[$key]))
430
+ {
431
+ return $categories[$key];
432
+ }
433
+ else
434
+ {
435
+ return null;
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Get all categories for the item
441
+ *
442
+ * Uses `<atom:category>`, `<category>` or `<dc:subject>`
443
+ *
444
+ * @since Beta 3
445
+ * @return SimpleCluvPie_Category[]|null List of {@see SimpleCluvPie_Category} objects
446
+ */
447
+ public function get_categories()
448
+ {
449
+ $categories = array();
450
+
451
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'category') as $category)
452
+ {
453
+ $term = null;
454
+ $scheme = null;
455
+ $label = null;
456
+ if (isset($category['attribs']['']['term']))
457
+ {
458
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLECLUVPIE_CONSTRUCT_HTML);
459
+ }
460
+ if (isset($category['attribs']['']['scheme']))
461
+ {
462
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_HTML);
463
+ }
464
+ if (isset($category['attribs']['']['label']))
465
+ {
466
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_HTML);
467
+ }
468
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
469
+ }
470
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'category') as $category)
471
+ {
472
+ // This is really the label, but keep this as the term also for BC.
473
+ // Label will also work on retrieving because that falls back to term.
474
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
475
+ if (isset($category['attribs']['']['domain']))
476
+ {
477
+ $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLECLUVPIE_CONSTRUCT_HTML);
478
+ }
479
+ else
480
+ {
481
+ $scheme = null;
482
+ }
483
+ $categories[] = $this->registry->create('Category', array($term, $scheme, null));
484
+ }
485
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'subject') as $category)
486
+ {
487
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_HTML), null, null));
488
+ }
489
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'subject') as $category)
490
+ {
491
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_HTML), null, null));
492
+ }
493
+
494
+ if (!empty($categories))
495
+ {
496
+ return array_unique($categories);
497
+ }
498
+ else
499
+ {
500
+ return null;
501
+ }
502
+ }
503
+
504
+ /**
505
+ * Get an author for the item
506
+ *
507
+ * @since Beta 2
508
+ * @param int $key The author that you want to return. Remember that arrays begin with 0, not 1
509
+ * @return SimpleCluvPie_Author|null
510
+ */
511
+ public function get_author($key = 0)
512
+ {
513
+ $authors = $this->get_authors();
514
+ if (isset($authors[$key]))
515
+ {
516
+ return $authors[$key];
517
+ }
518
+ else
519
+ {
520
+ return null;
521
+ }
522
+ }
523
+
524
+ /**
525
+ * Get a contributor for the item
526
+ *
527
+ * @since 1.1
528
+ * @param int $key The contrbutor that you want to return. Remember that arrays begin with 0, not 1
529
+ * @return SimpleCluvPie_Author|null
530
+ */
531
+ public function get_contributor($key = 0)
532
+ {
533
+ $contributors = $this->get_contributors();
534
+ if (isset($contributors[$key]))
535
+ {
536
+ return $contributors[$key];
537
+ }
538
+ else
539
+ {
540
+ return null;
541
+ }
542
+ }
543
+
544
+ /**
545
+ * Get all contributors for the item
546
+ *
547
+ * Uses `<atom:contributor>`
548
+ *
549
+ * @since 1.1
550
+ * @return array|null List of {@see SimpleCluvPie_Author} objects
551
+ */
552
+ public function get_contributors()
553
+ {
554
+ $contributors = array();
555
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
556
+ {
557
+ $name = null;
558
+ $uri = null;
559
+ $email = null;
560
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
561
+ {
562
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
563
+ }
564
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
565
+ {
566
+ $uri = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
567
+ }
568
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
569
+ {
570
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
571
+ }
572
+ if ($name !== null || $email !== null || $uri !== null)
573
+ {
574
+ $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
575
+ }
576
+ }
577
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
578
+ {
579
+ $name = null;
580
+ $url = null;
581
+ $email = null;
582
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
583
+ {
584
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
585
+ }
586
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
587
+ {
588
+ $url = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
589
+ }
590
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
591
+ {
592
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
593
+ }
594
+ if ($name !== null || $email !== null || $url !== null)
595
+ {
596
+ $contributors[] = $this->registry->create('Author', array($name, $url, $email));
597
+ }
598
+ }
599
+
600
+ if (!empty($contributors))
601
+ {
602
+ return array_unique($contributors);
603
+ }
604
+ else
605
+ {
606
+ return null;
607
+ }
608
+ }
609
+
610
+ /**
611
+ * Get all authors for the item
612
+ *
613
+ * Uses `<atom:author>`, `<author>`, `<dc:creator>` or `<itunes:author>`
614
+ *
615
+ * @since Beta 2
616
+ * @return array|null List of {@see SimpleCluvPie_Author} objects
617
+ */
618
+ public function get_authors()
619
+ {
620
+ $authors = array();
621
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'author') as $author)
622
+ {
623
+ $name = null;
624
+ $uri = null;
625
+ $email = null;
626
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
627
+ {
628
+ $name = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
629
+ }
630
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
631
+ {
632
+ $uri = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
633
+ }
634
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
635
+ {
636
+ $email = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
637
+ }
638
+ if ($name !== null || $email !== null || $uri !== null)
639
+ {
640
+ $authors[] = $this->registry->create('Author', array($name, $uri, $email));
641
+ }
642
+ }
643
+ if ($author = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'author'))
644
+ {
645
+ $name = null;
646
+ $url = null;
647
+ $email = null;
648
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
649
+ {
650
+ $name = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
651
+ }
652
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
653
+ {
654
+ $url = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
655
+ }
656
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
657
+ {
658
+ $email = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML);
659
+ }
660
+ if ($name !== null || $email !== null || $url !== null)
661
+ {
662
+ $authors[] = $this->registry->create('Author', array($name, $url, $email));
663
+ }
664
+ }
665
+ if ($author = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'author'))
666
+ {
667
+ $authors[] = $this->registry->create('Author', array(null, null, $this->sanitize($author[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML)));
668
+ }
669
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'creator') as $author)
670
+ {
671
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_HTML), null, null));
672
+ }
673
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'creator') as $author)
674
+ {
675
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_HTML), null, null));
676
+ }
677
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'author') as $author)
678
+ {
679
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_HTML), null, null));
680
+ }
681
+
682
+ if (!empty($authors))
683
+ {
684
+ return array_unique($authors);
685
+ }
686
+ elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
687
+ {
688
+ return $authors;
689
+ }
690
+ elseif ($authors = $this->feed->get_authors())
691
+ {
692
+ return $authors;
693
+ }
694
+ else
695
+ {
696
+ return null;
697
+ }
698
+ }
699
+
700
+ /**
701
+ * Get the copyright info for the item
702
+ *
703
+ * Uses `<atom:rights>` or `<dc:rights>`
704
+ *
705
+ * @since 1.1
706
+ * @return string
707
+ */
708
+ public function get_copyright()
709
+ {
710
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'rights'))
711
+ {
712
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
713
+ }
714
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'rights'))
715
+ {
716
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
717
+ }
718
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'rights'))
719
+ {
720
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
721
+ }
722
+ else
723
+ {
724
+ return null;
725
+ }
726
+ }
727
+
728
+ /**
729
+ * Get the posting date/time for the item
730
+ *
731
+ * Uses `<atom:published>`, `<atom:updated>`, `<atom:issued>`,
732
+ * `<atom:modified>`, `<pubDate>` or `<dc:date>`
733
+ *
734
+ * Note: obeys PHP's timezone setting. To get a UTC date/time, use
735
+ * {@see get_gmdate}
736
+ *
737
+ * @since Beta 2 (previously called `get_item_date` since 0.8)
738
+ *
739
+ * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
740
+ * @return int|string|null
741
+ */
742
+ public function get_date($date_format = 'j F Y, g:i a')
743
+ {
744
+ if (!isset($this->data['date']))
745
+ {
746
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'published'))
747
+ {
748
+ $this->data['date']['raw'] = $return[0]['data'];
749
+ }
750
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'pubDate'))
751
+ {
752
+ $this->data['date']['raw'] = $return[0]['data'];
753
+ }
754
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'date'))
755
+ {
756
+ $this->data['date']['raw'] = $return[0]['data'];
757
+ }
758
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'date'))
759
+ {
760
+ $this->data['date']['raw'] = $return[0]['data'];
761
+ }
762
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'updated'))
763
+ {
764
+ $this->data['date']['raw'] = $return[0]['data'];
765
+ }
766
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'issued'))
767
+ {
768
+ $this->data['date']['raw'] = $return[0]['data'];
769
+ }
770
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'created'))
771
+ {
772
+ $this->data['date']['raw'] = $return[0]['data'];
773
+ }
774
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'modified'))
775
+ {
776
+ $this->data['date']['raw'] = $return[0]['data'];
777
+ }
778
+
779
+ if (!empty($this->data['date']['raw']))
780
+ {
781
+ $parser = $this->registry->call('Parse_Date', 'get');
782
+ $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
783
+ }
784
+ else
785
+ {
786
+ $this->data['date'] = null;
787
+ }
788
+ }
789
+ if ($this->data['date'])
790
+ {
791
+ $date_format = (string) $date_format;
792
+ switch ($date_format)
793
+ {
794
+ case '':
795
+ return $this->sanitize($this->data['date']['raw'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
796
+
797
+ case 'U':
798
+ return $this->data['date']['parsed'];
799
+
800
+ default:
801
+ return date($date_format, $this->data['date']['parsed']);
802
+ }
803
+ }
804
+ else
805
+ {
806
+ return null;
807
+ }
808
+ }
809
+
810
+ /**
811
+ * Get the update date/time for the item
812
+ *
813
+ * Uses `<atom:updated>`
814
+ *
815
+ * Note: obeys PHP's timezone setting. To get a UTC date/time, use
816
+ * {@see get_gmdate}
817
+ *
818
+ * @param string $date_format Supports any PHP date format from {@see http://php.net/date} (empty for the raw data)
819
+ * @return int|string|null
820
+ */
821
+ public function get_updated_date($date_format = 'j F Y, g:i a')
822
+ {
823
+ if (!isset($this->data['updated']))
824
+ {
825
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'updated'))
826
+ {
827
+ $this->data['updated']['raw'] = $return[0]['data'];
828
+ }
829
+
830
+ if (!empty($this->data['updated']['raw']))
831
+ {
832
+ $parser = $this->registry->call('Parse_Date', 'get');
833
+ $this->data['updated']['parsed'] = $parser->parse($this->data['updated']['raw']);
834
+ }
835
+ else
836
+ {
837
+ $this->data['updated'] = null;
838
+ }
839
+ }
840
+ if ($this->data['updated'])
841
+ {
842
+ $date_format = (string) $date_format;
843
+ switch ($date_format)
844
+ {
845
+ case '':
846
+ return $this->sanitize($this->data['updated']['raw'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
847
+
848
+ case 'U':
849
+ return $this->data['updated']['parsed'];
850
+
851
+ default:
852
+ return date($date_format, $this->data['updated']['parsed']);
853
+ }
854
+ }
855
+ else
856
+ {
857
+ return null;
858
+ }
859
+ }
860
+
861
+ /**
862
+ * Get the localized posting date/time for the item
863
+ *
864
+ * Returns the date formatted in the localized language. To display in
865
+ * languages other than the server's default, you need to change the locale
866
+ * with {@link http://php.net/setlocale setlocale()}. The available
867
+ * localizations depend on which ones are installed on your web server.
868
+ *
869
+ * @since 1.0
870
+ *
871
+ * @param string $date_format Supports any PHP date format from {@see http://php.net/strftime} (empty for the raw data)
872
+ * @return int|string|null
873
+ */
874
+ public function get_local_date($date_format = '%c')
875
+ {
876
+ if (!$date_format)
877
+ {
878
+ return $this->sanitize($this->get_date(''), SIMPLECLUVPIE_CONSTRUCT_TEXT);
879
+ }
880
+ elseif (($date = $this->get_date('U')) !== null && $date !== false)
881
+ {
882
+ return strftime($date_format, $date);
883
+ }
884
+ else
885
+ {
886
+ return null;
887
+ }
888
+ }
889
+
890
+ /**
891
+ * Get the posting date/time for the item (UTC time)
892
+ *
893
+ * @see get_date
894
+ * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
895
+ * @return int|string|null
896
+ */
897
+ public function get_gmdate($date_format = 'j F Y, g:i a')
898
+ {
899
+ $date = $this->get_date('U');
900
+ if ($date === null)
901
+ {
902
+ return null;
903
+ }
904
+
905
+ return gmdate($date_format, $date);
906
+ }
907
+
908
+ /**
909
+ * Get the update date/time for the item (UTC time)
910
+ *
911
+ * @see get_updated_date
912
+ * @param string $date_format Supports any PHP date format from {@see http://php.net/date}
913
+ * @return int|string|null
914
+ */
915
+ public function get_updated_gmdate($date_format = 'j F Y, g:i a')
916
+ {
917
+ $date = $this->get_updated_date('U');
918
+ if ($date === null)
919
+ {
920
+ return null;
921
+ }
922
+
923
+ return gmdate($date_format, $date);
924
+ }
925
+
926
+ /**
927
+ * Get the permalink for the item
928
+ *
929
+ * Returns the first link available with a relationship of "alternate".
930
+ * Identical to {@see get_link()} with key 0
931
+ *
932
+ * @see get_link
933
+ * @since 0.8
934
+ * @return string|null Permalink URL
935
+ */
936
+ public function get_permalink()
937
+ {
938
+ $link = $this->get_link();
939
+ $enclosure = $this->get_enclosure(0);
940
+ if ($link !== null)
941
+ {
942
+ return $link;
943
+ }
944
+ elseif ($enclosure !== null)
945
+ {
946
+ return $enclosure->get_link();
947
+ }
948
+ else
949
+ {
950
+ return null;
951
+ }
952
+ }
953
+
954
+ /**
955
+ * Get a single link for the item
956
+ *
957
+ * @since Beta 3
958
+ * @param int $key The link that you want to return. Remember that arrays begin with 0, not 1
959
+ * @param string $rel The relationship of the link to return
960
+ * @return string|null Link URL
961
+ */
962
+ public function get_link($key = 0, $rel = 'alternate')
963
+ {
964
+ $links = $this->get_links($rel);
965
+ if ($links[$key] !== null)
966
+ {
967
+ return $links[$key];
968
+ }
969
+ else
970
+ {
971
+ return null;
972
+ }
973
+ }
974
+
975
+ /**
976
+ * Get all links for the item
977
+ *
978
+ * Uses `<atom:link>`, `<link>` or `<guid>`
979
+ *
980
+ * @since Beta 2
981
+ * @param string $rel The relationship of links to return
982
+ * @return array|null Links found for the item (strings)
983
+ */
984
+ public function get_links($rel = 'alternate')
985
+ {
986
+ if (!isset($this->data['links']))
987
+ {
988
+ $this->data['links'] = array();
989
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'link') as $link)
990
+ {
991
+ if (isset($link['attribs']['']['href']))
992
+ {
993
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
994
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
995
+
996
+ }
997
+ }
998
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'link') as $link)
999
+ {
1000
+ if (isset($link['attribs']['']['href']))
1001
+ {
1002
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
1003
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
1004
+ }
1005
+ }
1006
+ if ($links = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'link'))
1007
+ {
1008
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
1009
+ }
1010
+ if ($links = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'link'))
1011
+ {
1012
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
1013
+ }
1014
+ if ($links = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'link'))
1015
+ {
1016
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
1017
+ }
1018
+ if ($links = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'guid'))
1019
+ {
1020
+ if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
1021
+ {
1022
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
1023
+ }
1024
+ }
1025
+
1026
+ $keys = array_keys($this->data['links']);
1027
+ foreach ($keys as $key)
1028
+ {
1029
+ if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
1030
+ {
1031
+ if (isset($this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
1032
+ {
1033
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
1034
+ $this->data['links'][$key] =& $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
1035
+ }
1036
+ else
1037
+ {
1038
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
1039
+ }
1040
+ }
1041
+ elseif (substr($key, 0, 41) === SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY)
1042
+ {
1043
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
1044
+ }
1045
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
1046
+ }
1047
+ }
1048
+ if (isset($this->data['links'][$rel]))
1049
+ {
1050
+ return $this->data['links'][$rel];
1051
+ }
1052
+ else
1053
+ {
1054
+ return null;
1055
+ }
1056
+ }
1057
+
1058
+ /**
1059
+ * Get an enclosure from the item
1060
+ *
1061
+ * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
1062
+ *
1063
+ * @since Beta 2
1064
+ * @todo Add ability to prefer one type of content over another (in a media group).
1065
+ * @param int $key The enclosure that you want to return. Remember that arrays begin with 0, not 1
1066
+ * @return SimpleCluvPie_Enclosure|null
1067
+ */
1068
+ public function get_enclosure($key = 0, $prefer = null)
1069
+ {
1070
+ $enclosures = $this->get_enclosures();
1071
+ if (isset($enclosures[$key]))
1072
+ {
1073
+ return $enclosures[$key];
1074
+ }
1075
+ else
1076
+ {
1077
+ return null;
1078
+ }
1079
+ }
1080
+
1081
+ /**
1082
+ * Get all available enclosures (podcasts, etc.)
1083
+ *
1084
+ * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
1085
+ *
1086
+ * At this point, we're pretty much assuming that all enclosures for an item
1087
+ * are the same content. Anything else is too complicated to
1088
+ * properly support.
1089
+ *
1090
+ * @since Beta 2
1091
+ * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
1092
+ * @todo If an element exists at a level, but its value is empty, we should fall back to the value from the parent (if it exists).
1093
+ * @return SimpleCluvPie_Enclosure[]|null List of SimpleCluvPie_Enclosure items
1094
+ */
1095
+ public function get_enclosures()
1096
+ {
1097
+ if (!isset($this->data['enclosures']))
1098
+ {
1099
+ $this->data['enclosures'] = array();
1100
+
1101
+ // Elements
1102
+ $captions_parent = null;
1103
+ $categories_parent = null;
1104
+ $copyrights_parent = null;
1105
+ $credits_parent = null;
1106
+ $description_parent = null;
1107
+ $duration_parent = null;
1108
+ $hashes_parent = null;
1109
+ $keywords_parent = null;
1110
+ $player_parent = null;
1111
+ $ratings_parent = null;
1112
+ $restrictions_parent = null;
1113
+ $thumbnails_parent = null;
1114
+ $title_parent = null;
1115
+
1116
+ // Let's do the channel and item-level ones first, and just re-use them if we need to.
1117
+ $parent = $this->get_feed();
1118
+
1119
+ // CAPTIONS
1120
+ if ($captions = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'text'))
1121
+ {
1122
+ foreach ($captions as $caption)
1123
+ {
1124
+ $caption_type = null;
1125
+ $caption_lang = null;
1126
+ $caption_startTime = null;
1127
+ $caption_endTime = null;
1128
+ $caption_text = null;
1129
+ if (isset($caption['attribs']['']['type']))
1130
+ {
1131
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1132
+ }
1133
+ if (isset($caption['attribs']['']['lang']))
1134
+ {
1135
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1136
+ }
1137
+ if (isset($caption['attribs']['']['start']))
1138
+ {
1139
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1140
+ }
1141
+ if (isset($caption['attribs']['']['end']))
1142
+ {
1143
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1144
+ }
1145
+ if (isset($caption['data']))
1146
+ {
1147
+ $caption_text = $this->sanitize($caption['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1148
+ }
1149
+ $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
1150
+ }
1151
+ }
1152
+ elseif ($captions = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'text'))
1153
+ {
1154
+ foreach ($captions as $caption)
1155
+ {
1156
+ $caption_type = null;
1157
+ $caption_lang = null;
1158
+ $caption_startTime = null;
1159
+ $caption_endTime = null;
1160
+ $caption_text = null;
1161
+ if (isset($caption['attribs']['']['type']))
1162
+ {
1163
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1164
+ }
1165
+ if (isset($caption['attribs']['']['lang']))
1166
+ {
1167
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1168
+ }
1169
+ if (isset($caption['attribs']['']['start']))
1170
+ {
1171
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1172
+ }
1173
+ if (isset($caption['attribs']['']['end']))
1174
+ {
1175
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1176
+ }
1177
+ if (isset($caption['data']))
1178
+ {
1179
+ $caption_text = $this->sanitize($caption['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1180
+ }
1181
+ $captions_parent[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
1182
+ }
1183
+ }
1184
+ if (is_array($captions_parent))
1185
+ {
1186
+ $captions_parent = array_values(array_unique($captions_parent));
1187
+ }
1188
+
1189
+ // CATEGORIES
1190
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'category') as $category)
1191
+ {
1192
+ $term = null;
1193
+ $scheme = null;
1194
+ $label = null;
1195
+ if (isset($category['data']))
1196
+ {
1197
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1198
+ }
1199
+ if (isset($category['attribs']['']['scheme']))
1200
+ {
1201
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1202
+ }
1203
+ else
1204
+ {
1205
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
1206
+ }
1207
+ if (isset($category['attribs']['']['label']))
1208
+ {
1209
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1210
+ }
1211
+ $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
1212
+ }
1213
+ foreach ((array) $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'category') as $category)
1214
+ {
1215
+ $term = null;
1216
+ $scheme = null;
1217
+ $label = null;
1218
+ if (isset($category['data']))
1219
+ {
1220
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1221
+ }
1222
+ if (isset($category['attribs']['']['scheme']))
1223
+ {
1224
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1225
+ }
1226
+ else
1227
+ {
1228
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
1229
+ }
1230
+ if (isset($category['attribs']['']['label']))
1231
+ {
1232
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1233
+ }
1234
+ $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
1235
+ }
1236
+ foreach ((array) $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'category') as $category)
1237
+ {
1238
+ $term = null;
1239
+ $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
1240
+ $label = null;
1241
+ if (isset($category['attribs']['']['text']))
1242
+ {
1243
+ $label = $this->sanitize($category['attribs']['']['text'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1244
+ }
1245
+ $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
1246
+
1247
+ if (isset($category['child'][SIMPLECLUVPIE_NAMESPACE_ITUNES]['category']))
1248
+ {
1249
+ foreach ((array) $category['child'][SIMPLECLUVPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
1250
+ {
1251
+ if (isset($subcategory['attribs']['']['text']))
1252
+ {
1253
+ $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1254
+ }
1255
+ $categories_parent[] = $this->registry->create('Category', array($term, $scheme, $label));
1256
+ }
1257
+ }
1258
+ }
1259
+ if (is_array($categories_parent))
1260
+ {
1261
+ $categories_parent = array_values(array_unique($categories_parent));
1262
+ }
1263
+
1264
+ // COPYRIGHT
1265
+ if ($copyright = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'copyright'))
1266
+ {
1267
+ $copyright_url = null;
1268
+ $copyright_label = null;
1269
+ if (isset($copyright[0]['attribs']['']['url']))
1270
+ {
1271
+ $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1272
+ }
1273
+ if (isset($copyright[0]['data']))
1274
+ {
1275
+ $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1276
+ }
1277
+ $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
1278
+ }
1279
+ elseif ($copyright = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'copyright'))
1280
+ {
1281
+ $copyright_url = null;
1282
+ $copyright_label = null;
1283
+ if (isset($copyright[0]['attribs']['']['url']))
1284
+ {
1285
+ $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1286
+ }
1287
+ if (isset($copyright[0]['data']))
1288
+ {
1289
+ $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1290
+ }
1291
+ $copyrights_parent = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
1292
+ }
1293
+
1294
+ // CREDITS
1295
+ if ($credits = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'credit'))
1296
+ {
1297
+ foreach ($credits as $credit)
1298
+ {
1299
+ $credit_role = null;
1300
+ $credit_scheme = null;
1301
+ $credit_name = null;
1302
+ if (isset($credit['attribs']['']['role']))
1303
+ {
1304
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1305
+ }
1306
+ if (isset($credit['attribs']['']['scheme']))
1307
+ {
1308
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1309
+ }
1310
+ else
1311
+ {
1312
+ $credit_scheme = 'urn:ebu';
1313
+ }
1314
+ if (isset($credit['data']))
1315
+ {
1316
+ $credit_name = $this->sanitize($credit['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1317
+ }
1318
+ $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
1319
+ }
1320
+ }
1321
+ elseif ($credits = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'credit'))
1322
+ {
1323
+ foreach ($credits as $credit)
1324
+ {
1325
+ $credit_role = null;
1326
+ $credit_scheme = null;
1327
+ $credit_name = null;
1328
+ if (isset($credit['attribs']['']['role']))
1329
+ {
1330
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1331
+ }
1332
+ if (isset($credit['attribs']['']['scheme']))
1333
+ {
1334
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1335
+ }
1336
+ else
1337
+ {
1338
+ $credit_scheme = 'urn:ebu';
1339
+ }
1340
+ if (isset($credit['data']))
1341
+ {
1342
+ $credit_name = $this->sanitize($credit['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1343
+ }
1344
+ $credits_parent[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
1345
+ }
1346
+ }
1347
+ if (is_array($credits_parent))
1348
+ {
1349
+ $credits_parent = array_values(array_unique($credits_parent));
1350
+ }
1351
+
1352
+ // DESCRIPTION
1353
+ if ($description_parent = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'description'))
1354
+ {
1355
+ if (isset($description_parent[0]['data']))
1356
+ {
1357
+ $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1358
+ }
1359
+ }
1360
+ elseif ($description_parent = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'description'))
1361
+ {
1362
+ if (isset($description_parent[0]['data']))
1363
+ {
1364
+ $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1365
+ }
1366
+ }
1367
+
1368
+ // DURATION
1369
+ if ($duration_parent = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'duration'))
1370
+ {
1371
+ $seconds = null;
1372
+ $minutes = null;
1373
+ $hours = null;
1374
+ if (isset($duration_parent[0]['data']))
1375
+ {
1376
+ $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
1377
+ if (sizeof($temp) > 0)
1378
+ {
1379
+ $seconds = (int) array_pop($temp);
1380
+ }
1381
+ if (sizeof($temp) > 0)
1382
+ {
1383
+ $minutes = (int) array_pop($temp);
1384
+ $seconds += $minutes * 60;
1385
+ }
1386
+ if (sizeof($temp) > 0)
1387
+ {
1388
+ $hours = (int) array_pop($temp);
1389
+ $seconds += $hours * 3600;
1390
+ }
1391
+ unset($temp);
1392
+ $duration_parent = $seconds;
1393
+ }
1394
+ }
1395
+
1396
+ // HASHES
1397
+ if ($hashes_iterator = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'hash'))
1398
+ {
1399
+ foreach ($hashes_iterator as $hash)
1400
+ {
1401
+ $value = null;
1402
+ $algo = null;
1403
+ if (isset($hash['data']))
1404
+ {
1405
+ $value = $this->sanitize($hash['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1406
+ }
1407
+ if (isset($hash['attribs']['']['algo']))
1408
+ {
1409
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1410
+ }
1411
+ else
1412
+ {
1413
+ $algo = 'md5';
1414
+ }
1415
+ $hashes_parent[] = $algo.':'.$value;
1416
+ }
1417
+ }
1418
+ elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'hash'))
1419
+ {
1420
+ foreach ($hashes_iterator as $hash)
1421
+ {
1422
+ $value = null;
1423
+ $algo = null;
1424
+ if (isset($hash['data']))
1425
+ {
1426
+ $value = $this->sanitize($hash['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1427
+ }
1428
+ if (isset($hash['attribs']['']['algo']))
1429
+ {
1430
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1431
+ }
1432
+ else
1433
+ {
1434
+ $algo = 'md5';
1435
+ }
1436
+ $hashes_parent[] = $algo.':'.$value;
1437
+ }
1438
+ }
1439
+ if (is_array($hashes_parent))
1440
+ {
1441
+ $hashes_parent = array_values(array_unique($hashes_parent));
1442
+ }
1443
+
1444
+ // KEYWORDS
1445
+ if ($keywords = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'keywords'))
1446
+ {
1447
+ if (isset($keywords[0]['data']))
1448
+ {
1449
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
1450
+ foreach ($temp as $word)
1451
+ {
1452
+ $keywords_parent[] = trim($word);
1453
+ }
1454
+ }
1455
+ unset($temp);
1456
+ }
1457
+ elseif ($keywords = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'keywords'))
1458
+ {
1459
+ if (isset($keywords[0]['data']))
1460
+ {
1461
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
1462
+ foreach ($temp as $word)
1463
+ {
1464
+ $keywords_parent[] = trim($word);
1465
+ }
1466
+ }
1467
+ unset($temp);
1468
+ }
1469
+ elseif ($keywords = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'keywords'))
1470
+ {
1471
+ if (isset($keywords[0]['data']))
1472
+ {
1473
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
1474
+ foreach ($temp as $word)
1475
+ {
1476
+ $keywords_parent[] = trim($word);
1477
+ }
1478
+ }
1479
+ unset($temp);
1480
+ }
1481
+ elseif ($keywords = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'keywords'))
1482
+ {
1483
+ if (isset($keywords[0]['data']))
1484
+ {
1485
+ $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
1486
+ foreach ($temp as $word)
1487
+ {
1488
+ $keywords_parent[] = trim($word);
1489
+ }
1490
+ }
1491
+ unset($temp);
1492
+ }
1493
+ if (is_array($keywords_parent))
1494
+ {
1495
+ $keywords_parent = array_values(array_unique($keywords_parent));
1496
+ }
1497
+
1498
+ // PLAYER
1499
+ if ($player_parent = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'player'))
1500
+ {
1501
+ if (isset($player_parent[0]['attribs']['']['url']))
1502
+ {
1503
+ $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
1504
+ }
1505
+ }
1506
+ elseif ($player_parent = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'player'))
1507
+ {
1508
+ if (isset($player_parent[0]['attribs']['']['url']))
1509
+ {
1510
+ $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
1511
+ }
1512
+ }
1513
+
1514
+ // RATINGS
1515
+ if ($ratings = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'rating'))
1516
+ {
1517
+ foreach ($ratings as $rating)
1518
+ {
1519
+ $rating_scheme = null;
1520
+ $rating_value = null;
1521
+ if (isset($rating['attribs']['']['scheme']))
1522
+ {
1523
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1524
+ }
1525
+ else
1526
+ {
1527
+ $rating_scheme = 'urn:simple';
1528
+ }
1529
+ if (isset($rating['data']))
1530
+ {
1531
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1532
+ }
1533
+ $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
1534
+ }
1535
+ }
1536
+ elseif ($ratings = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'explicit'))
1537
+ {
1538
+ foreach ($ratings as $rating)
1539
+ {
1540
+ $rating_scheme = 'urn:itunes';
1541
+ $rating_value = null;
1542
+ if (isset($rating['data']))
1543
+ {
1544
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1545
+ }
1546
+ $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
1547
+ }
1548
+ }
1549
+ elseif ($ratings = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'rating'))
1550
+ {
1551
+ foreach ($ratings as $rating)
1552
+ {
1553
+ $rating_scheme = null;
1554
+ $rating_value = null;
1555
+ if (isset($rating['attribs']['']['scheme']))
1556
+ {
1557
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1558
+ }
1559
+ else
1560
+ {
1561
+ $rating_scheme = 'urn:simple';
1562
+ }
1563
+ if (isset($rating['data']))
1564
+ {
1565
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1566
+ }
1567
+ $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
1568
+ }
1569
+ }
1570
+ elseif ($ratings = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'explicit'))
1571
+ {
1572
+ foreach ($ratings as $rating)
1573
+ {
1574
+ $rating_scheme = 'urn:itunes';
1575
+ $rating_value = null;
1576
+ if (isset($rating['data']))
1577
+ {
1578
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1579
+ }
1580
+ $ratings_parent[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
1581
+ }
1582
+ }
1583
+ if (is_array($ratings_parent))
1584
+ {
1585
+ $ratings_parent = array_values(array_unique($ratings_parent));
1586
+ }
1587
+
1588
+ // RESTRICTIONS
1589
+ if ($restrictions = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'restriction'))
1590
+ {
1591
+ foreach ($restrictions as $restriction)
1592
+ {
1593
+ $restriction_relationship = null;
1594
+ $restriction_type = null;
1595
+ $restriction_value = null;
1596
+ if (isset($restriction['attribs']['']['relationship']))
1597
+ {
1598
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1599
+ }
1600
+ if (isset($restriction['attribs']['']['type']))
1601
+ {
1602
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1603
+ }
1604
+ if (isset($restriction['data']))
1605
+ {
1606
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1607
+ }
1608
+ $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
1609
+ }
1610
+ }
1611
+ elseif ($restrictions = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'block'))
1612
+ {
1613
+ foreach ($restrictions as $restriction)
1614
+ {
1615
+ $restriction_relationship = 'allow';
1616
+ $restriction_type = null;
1617
+ $restriction_value = 'itunes';
1618
+ if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
1619
+ {
1620
+ $restriction_relationship = 'deny';
1621
+ }
1622
+ $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
1623
+ }
1624
+ }
1625
+ elseif ($restrictions = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'restriction'))
1626
+ {
1627
+ foreach ($restrictions as $restriction)
1628
+ {
1629
+ $restriction_relationship = null;
1630
+ $restriction_type = null;
1631
+ $restriction_value = null;
1632
+ if (isset($restriction['attribs']['']['relationship']))
1633
+ {
1634
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1635
+ }
1636
+ if (isset($restriction['attribs']['']['type']))
1637
+ {
1638
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1639
+ }
1640
+ if (isset($restriction['data']))
1641
+ {
1642
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1643
+ }
1644
+ $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
1645
+ }
1646
+ }
1647
+ elseif ($restrictions = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'block'))
1648
+ {
1649
+ foreach ($restrictions as $restriction)
1650
+ {
1651
+ $restriction_relationship = 'allow';
1652
+ $restriction_type = null;
1653
+ $restriction_value = 'itunes';
1654
+ if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
1655
+ {
1656
+ $restriction_relationship = 'deny';
1657
+ }
1658
+ $restrictions_parent[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
1659
+ }
1660
+ }
1661
+ if (is_array($restrictions_parent))
1662
+ {
1663
+ $restrictions_parent = array_values(array_unique($restrictions_parent));
1664
+ }
1665
+ else
1666
+ {
1667
+ $restrictions_parent = array(new SimpleCluvPie_Restriction('allow', null, 'default'));
1668
+ }
1669
+
1670
+ // THUMBNAILS
1671
+ if ($thumbnails = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
1672
+ {
1673
+ foreach ($thumbnails as $thumbnail)
1674
+ {
1675
+ if (isset($thumbnail['attribs']['']['url']))
1676
+ {
1677
+ $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
1678
+ }
1679
+ }
1680
+ }
1681
+ elseif ($thumbnails = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
1682
+ {
1683
+ foreach ($thumbnails as $thumbnail)
1684
+ {
1685
+ if (isset($thumbnail['attribs']['']['url']))
1686
+ {
1687
+ $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
1688
+ }
1689
+ }
1690
+ }
1691
+
1692
+ // TITLES
1693
+ if ($title_parent = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'title'))
1694
+ {
1695
+ if (isset($title_parent[0]['data']))
1696
+ {
1697
+ $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1698
+ }
1699
+ }
1700
+ elseif ($title_parent = $parent->get_channel_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'title'))
1701
+ {
1702
+ if (isset($title_parent[0]['data']))
1703
+ {
1704
+ $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1705
+ }
1706
+ }
1707
+
1708
+ // Clear the memory
1709
+ unset($parent);
1710
+
1711
+ // Attributes
1712
+ $bitrate = null;
1713
+ $channels = null;
1714
+ $duration = null;
1715
+ $expression = null;
1716
+ $framerate = null;
1717
+ $height = null;
1718
+ $javascript = null;
1719
+ $lang = null;
1720
+ $length = null;
1721
+ $medium = null;
1722
+ $samplingrate = null;
1723
+ $type = null;
1724
+ $url = null;
1725
+ $width = null;
1726
+
1727
+ // Elements
1728
+ $captions = null;
1729
+ $categories = null;
1730
+ $copyrights = null;
1731
+ $credits = null;
1732
+ $description = null;
1733
+ $hashes = null;
1734
+ $keywords = null;
1735
+ $player = null;
1736
+ $ratings = null;
1737
+ $restrictions = null;
1738
+ $thumbnails = null;
1739
+ $title = null;
1740
+
1741
+ // If we have media:group tags, loop through them.
1742
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_MEDIARSS, 'group') as $group)
1743
+ {
1744
+ if(isset($group['child']) && isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['content']))
1745
+ {
1746
+ // If we have media:content tags, loop through them.
1747
+ foreach ((array) $group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['content'] as $content)
1748
+ {
1749
+ if (isset($content['attribs']['']['url']))
1750
+ {
1751
+ // Attributes
1752
+ $bitrate = null;
1753
+ $channels = null;
1754
+ $duration = null;
1755
+ $expression = null;
1756
+ $framerate = null;
1757
+ $height = null;
1758
+ $javascript = null;
1759
+ $lang = null;
1760
+ $length = null;
1761
+ $medium = null;
1762
+ $samplingrate = null;
1763
+ $type = null;
1764
+ $url = null;
1765
+ $width = null;
1766
+
1767
+ // Elements
1768
+ $captions = null;
1769
+ $categories = null;
1770
+ $copyrights = null;
1771
+ $credits = null;
1772
+ $description = null;
1773
+ $hashes = null;
1774
+ $keywords = null;
1775
+ $player = null;
1776
+ $ratings = null;
1777
+ $restrictions = null;
1778
+ $thumbnails = null;
1779
+ $title = null;
1780
+
1781
+ // Start checking the attributes of media:content
1782
+ if (isset($content['attribs']['']['bitrate']))
1783
+ {
1784
+ $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1785
+ }
1786
+ if (isset($content['attribs']['']['channels']))
1787
+ {
1788
+ $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1789
+ }
1790
+ if (isset($content['attribs']['']['duration']))
1791
+ {
1792
+ $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1793
+ }
1794
+ else
1795
+ {
1796
+ $duration = $duration_parent;
1797
+ }
1798
+ if (isset($content['attribs']['']['expression']))
1799
+ {
1800
+ $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1801
+ }
1802
+ if (isset($content['attribs']['']['framerate']))
1803
+ {
1804
+ $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1805
+ }
1806
+ if (isset($content['attribs']['']['height']))
1807
+ {
1808
+ $height = $this->sanitize($content['attribs']['']['height'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1809
+ }
1810
+ if (isset($content['attribs']['']['lang']))
1811
+ {
1812
+ $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1813
+ }
1814
+ if (isset($content['attribs']['']['fileSize']))
1815
+ {
1816
+ $length = ceil($content['attribs']['']['fileSize']);
1817
+ }
1818
+ if (isset($content['attribs']['']['medium']))
1819
+ {
1820
+ $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1821
+ }
1822
+ if (isset($content['attribs']['']['samplingrate']))
1823
+ {
1824
+ $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1825
+ }
1826
+ if (isset($content['attribs']['']['type']))
1827
+ {
1828
+ $type = $this->sanitize($content['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1829
+ }
1830
+ if (isset($content['attribs']['']['width']))
1831
+ {
1832
+ $width = $this->sanitize($content['attribs']['']['width'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1833
+ }
1834
+ $url = $this->sanitize($content['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
1835
+
1836
+ // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
1837
+
1838
+ // CAPTIONS
1839
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text']))
1840
+ {
1841
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
1842
+ {
1843
+ $caption_type = null;
1844
+ $caption_lang = null;
1845
+ $caption_startTime = null;
1846
+ $caption_endTime = null;
1847
+ $caption_text = null;
1848
+ if (isset($caption['attribs']['']['type']))
1849
+ {
1850
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1851
+ }
1852
+ if (isset($caption['attribs']['']['lang']))
1853
+ {
1854
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1855
+ }
1856
+ if (isset($caption['attribs']['']['start']))
1857
+ {
1858
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1859
+ }
1860
+ if (isset($caption['attribs']['']['end']))
1861
+ {
1862
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1863
+ }
1864
+ if (isset($caption['data']))
1865
+ {
1866
+ $caption_text = $this->sanitize($caption['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1867
+ }
1868
+ $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
1869
+ }
1870
+ if (is_array($captions))
1871
+ {
1872
+ $captions = array_values(array_unique($captions));
1873
+ }
1874
+ }
1875
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text']))
1876
+ {
1877
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
1878
+ {
1879
+ $caption_type = null;
1880
+ $caption_lang = null;
1881
+ $caption_startTime = null;
1882
+ $caption_endTime = null;
1883
+ $caption_text = null;
1884
+ if (isset($caption['attribs']['']['type']))
1885
+ {
1886
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1887
+ }
1888
+ if (isset($caption['attribs']['']['lang']))
1889
+ {
1890
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1891
+ }
1892
+ if (isset($caption['attribs']['']['start']))
1893
+ {
1894
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1895
+ }
1896
+ if (isset($caption['attribs']['']['end']))
1897
+ {
1898
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1899
+ }
1900
+ if (isset($caption['data']))
1901
+ {
1902
+ $caption_text = $this->sanitize($caption['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1903
+ }
1904
+ $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
1905
+ }
1906
+ if (is_array($captions))
1907
+ {
1908
+ $captions = array_values(array_unique($captions));
1909
+ }
1910
+ }
1911
+ else
1912
+ {
1913
+ $captions = $captions_parent;
1914
+ }
1915
+
1916
+ // CATEGORIES
1917
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category']))
1918
+ {
1919
+ foreach ((array) $content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category'] as $category)
1920
+ {
1921
+ $term = null;
1922
+ $scheme = null;
1923
+ $label = null;
1924
+ if (isset($category['data']))
1925
+ {
1926
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1927
+ }
1928
+ if (isset($category['attribs']['']['scheme']))
1929
+ {
1930
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1931
+ }
1932
+ else
1933
+ {
1934
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
1935
+ }
1936
+ if (isset($category['attribs']['']['label']))
1937
+ {
1938
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1939
+ }
1940
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
1941
+ }
1942
+ }
1943
+ if (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category']))
1944
+ {
1945
+ foreach ((array) $group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category'] as $category)
1946
+ {
1947
+ $term = null;
1948
+ $scheme = null;
1949
+ $label = null;
1950
+ if (isset($category['data']))
1951
+ {
1952
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1953
+ }
1954
+ if (isset($category['attribs']['']['scheme']))
1955
+ {
1956
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1957
+ }
1958
+ else
1959
+ {
1960
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
1961
+ }
1962
+ if (isset($category['attribs']['']['label']))
1963
+ {
1964
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1965
+ }
1966
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
1967
+ }
1968
+ }
1969
+ if (is_array($categories) && is_array($categories_parent))
1970
+ {
1971
+ $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
1972
+ }
1973
+ elseif (is_array($categories))
1974
+ {
1975
+ $categories = array_values(array_unique($categories));
1976
+ }
1977
+ elseif (is_array($categories_parent))
1978
+ {
1979
+ $categories = array_values(array_unique($categories_parent));
1980
+ }
1981
+
1982
+ // COPYRIGHTS
1983
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright']))
1984
+ {
1985
+ $copyright_url = null;
1986
+ $copyright_label = null;
1987
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
1988
+ {
1989
+ $copyright_url = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1990
+ }
1991
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
1992
+ {
1993
+ $copyright_label = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
1994
+ }
1995
+ $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
1996
+ }
1997
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright']))
1998
+ {
1999
+ $copyright_url = null;
2000
+ $copyright_label = null;
2001
+ if (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
2002
+ {
2003
+ $copyright_url = $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2004
+ }
2005
+ if (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
2006
+ {
2007
+ $copyright_label = $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2008
+ }
2009
+ $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
2010
+ }
2011
+ else
2012
+ {
2013
+ $copyrights = $copyrights_parent;
2014
+ }
2015
+
2016
+ // CREDITS
2017
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit']))
2018
+ {
2019
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
2020
+ {
2021
+ $credit_role = null;
2022
+ $credit_scheme = null;
2023
+ $credit_name = null;
2024
+ if (isset($credit['attribs']['']['role']))
2025
+ {
2026
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2027
+ }
2028
+ if (isset($credit['attribs']['']['scheme']))
2029
+ {
2030
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2031
+ }
2032
+ else
2033
+ {
2034
+ $credit_scheme = 'urn:ebu';
2035
+ }
2036
+ if (isset($credit['data']))
2037
+ {
2038
+ $credit_name = $this->sanitize($credit['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2039
+ }
2040
+ $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
2041
+ }
2042
+ if (is_array($credits))
2043
+ {
2044
+ $credits = array_values(array_unique($credits));
2045
+ }
2046
+ }
2047
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit']))
2048
+ {
2049
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
2050
+ {
2051
+ $credit_role = null;
2052
+ $credit_scheme = null;
2053
+ $credit_name = null;
2054
+ if (isset($credit['attribs']['']['role']))
2055
+ {
2056
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2057
+ }
2058
+ if (isset($credit['attribs']['']['scheme']))
2059
+ {
2060
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2061
+ }
2062
+ else
2063
+ {
2064
+ $credit_scheme = 'urn:ebu';
2065
+ }
2066
+ if (isset($credit['data']))
2067
+ {
2068
+ $credit_name = $this->sanitize($credit['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2069
+ }
2070
+ $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
2071
+ }
2072
+ if (is_array($credits))
2073
+ {
2074
+ $credits = array_values(array_unique($credits));
2075
+ }
2076
+ }
2077
+ else
2078
+ {
2079
+ $credits = $credits_parent;
2080
+ }
2081
+
2082
+ // DESCRIPTION
2083
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description']))
2084
+ {
2085
+ $description = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2086
+ }
2087
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description']))
2088
+ {
2089
+ $description = $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2090
+ }
2091
+ else
2092
+ {
2093
+ $description = $description_parent;
2094
+ }
2095
+
2096
+ // HASHES
2097
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash']))
2098
+ {
2099
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
2100
+ {
2101
+ $value = null;
2102
+ $algo = null;
2103
+ if (isset($hash['data']))
2104
+ {
2105
+ $value = $this->sanitize($hash['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2106
+ }
2107
+ if (isset($hash['attribs']['']['algo']))
2108
+ {
2109
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2110
+ }
2111
+ else
2112
+ {
2113
+ $algo = 'md5';
2114
+ }
2115
+ $hashes[] = $algo.':'.$value;
2116
+ }
2117
+ if (is_array($hashes))
2118
+ {
2119
+ $hashes = array_values(array_unique($hashes));
2120
+ }
2121
+ }
2122
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash']))
2123
+ {
2124
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
2125
+ {
2126
+ $value = null;
2127
+ $algo = null;
2128
+ if (isset($hash['data']))
2129
+ {
2130
+ $value = $this->sanitize($hash['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2131
+ }
2132
+ if (isset($hash['attribs']['']['algo']))
2133
+ {
2134
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2135
+ }
2136
+ else
2137
+ {
2138
+ $algo = 'md5';
2139
+ }
2140
+ $hashes[] = $algo.':'.$value;
2141
+ }
2142
+ if (is_array($hashes))
2143
+ {
2144
+ $hashes = array_values(array_unique($hashes));
2145
+ }
2146
+ }
2147
+ else
2148
+ {
2149
+ $hashes = $hashes_parent;
2150
+ }
2151
+
2152
+ // KEYWORDS
2153
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords']))
2154
+ {
2155
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
2156
+ {
2157
+ $temp = explode(',', $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
2158
+ foreach ($temp as $word)
2159
+ {
2160
+ $keywords[] = trim($word);
2161
+ }
2162
+ unset($temp);
2163
+ }
2164
+ if (is_array($keywords))
2165
+ {
2166
+ $keywords = array_values(array_unique($keywords));
2167
+ }
2168
+ }
2169
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords']))
2170
+ {
2171
+ if (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
2172
+ {
2173
+ $temp = explode(',', $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
2174
+ foreach ($temp as $word)
2175
+ {
2176
+ $keywords[] = trim($word);
2177
+ }
2178
+ unset($temp);
2179
+ }
2180
+ if (is_array($keywords))
2181
+ {
2182
+ $keywords = array_values(array_unique($keywords));
2183
+ }
2184
+ }
2185
+ else
2186
+ {
2187
+ $keywords = $keywords_parent;
2188
+ }
2189
+
2190
+ // PLAYER
2191
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player']))
2192
+ {
2193
+ $player = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2194
+ }
2195
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player']))
2196
+ {
2197
+ $player = $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2198
+ }
2199
+ else
2200
+ {
2201
+ $player = $player_parent;
2202
+ }
2203
+
2204
+ // RATINGS
2205
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating']))
2206
+ {
2207
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
2208
+ {
2209
+ $rating_scheme = null;
2210
+ $rating_value = null;
2211
+ if (isset($rating['attribs']['']['scheme']))
2212
+ {
2213
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2214
+ }
2215
+ else
2216
+ {
2217
+ $rating_scheme = 'urn:simple';
2218
+ }
2219
+ if (isset($rating['data']))
2220
+ {
2221
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2222
+ }
2223
+ $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
2224
+ }
2225
+ if (is_array($ratings))
2226
+ {
2227
+ $ratings = array_values(array_unique($ratings));
2228
+ }
2229
+ }
2230
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating']))
2231
+ {
2232
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
2233
+ {
2234
+ $rating_scheme = null;
2235
+ $rating_value = null;
2236
+ if (isset($rating['attribs']['']['scheme']))
2237
+ {
2238
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2239
+ }
2240
+ else
2241
+ {
2242
+ $rating_scheme = 'urn:simple';
2243
+ }
2244
+ if (isset($rating['data']))
2245
+ {
2246
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2247
+ }
2248
+ $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
2249
+ }
2250
+ if (is_array($ratings))
2251
+ {
2252
+ $ratings = array_values(array_unique($ratings));
2253
+ }
2254
+ }
2255
+ else
2256
+ {
2257
+ $ratings = $ratings_parent;
2258
+ }
2259
+
2260
+ // RESTRICTIONS
2261
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction']))
2262
+ {
2263
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
2264
+ {
2265
+ $restriction_relationship = null;
2266
+ $restriction_type = null;
2267
+ $restriction_value = null;
2268
+ if (isset($restriction['attribs']['']['relationship']))
2269
+ {
2270
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2271
+ }
2272
+ if (isset($restriction['attribs']['']['type']))
2273
+ {
2274
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2275
+ }
2276
+ if (isset($restriction['data']))
2277
+ {
2278
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2279
+ }
2280
+ $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
2281
+ }
2282
+ if (is_array($restrictions))
2283
+ {
2284
+ $restrictions = array_values(array_unique($restrictions));
2285
+ }
2286
+ }
2287
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction']))
2288
+ {
2289
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
2290
+ {
2291
+ $restriction_relationship = null;
2292
+ $restriction_type = null;
2293
+ $restriction_value = null;
2294
+ if (isset($restriction['attribs']['']['relationship']))
2295
+ {
2296
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2297
+ }
2298
+ if (isset($restriction['attribs']['']['type']))
2299
+ {
2300
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2301
+ }
2302
+ if (isset($restriction['data']))
2303
+ {
2304
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2305
+ }
2306
+ $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
2307
+ }
2308
+ if (is_array($restrictions))
2309
+ {
2310
+ $restrictions = array_values(array_unique($restrictions));
2311
+ }
2312
+ }
2313
+ else
2314
+ {
2315
+ $restrictions = $restrictions_parent;
2316
+ }
2317
+
2318
+ // THUMBNAILS
2319
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail']))
2320
+ {
2321
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
2322
+ {
2323
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2324
+ }
2325
+ if (is_array($thumbnails))
2326
+ {
2327
+ $thumbnails = array_values(array_unique($thumbnails));
2328
+ }
2329
+ }
2330
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail']))
2331
+ {
2332
+ foreach ($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
2333
+ {
2334
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2335
+ }
2336
+ if (is_array($thumbnails))
2337
+ {
2338
+ $thumbnails = array_values(array_unique($thumbnails));
2339
+ }
2340
+ }
2341
+ else
2342
+ {
2343
+ $thumbnails = $thumbnails_parent;
2344
+ }
2345
+
2346
+ // TITLES
2347
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title']))
2348
+ {
2349
+ $title = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2350
+ }
2351
+ elseif (isset($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title']))
2352
+ {
2353
+ $title = $this->sanitize($group['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2354
+ }
2355
+ else
2356
+ {
2357
+ $title = $title_parent;
2358
+ }
2359
+
2360
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
2361
+ }
2362
+ }
2363
+ }
2364
+ }
2365
+
2366
+ // If we have standalone media:content tags, loop through them.
2367
+ if (isset($this->data['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['content']))
2368
+ {
2369
+ foreach ((array) $this->data['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['content'] as $content)
2370
+ {
2371
+ if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player']))
2372
+ {
2373
+ // Attributes
2374
+ $bitrate = null;
2375
+ $channels = null;
2376
+ $duration = null;
2377
+ $expression = null;
2378
+ $framerate = null;
2379
+ $height = null;
2380
+ $javascript = null;
2381
+ $lang = null;
2382
+ $length = null;
2383
+ $medium = null;
2384
+ $samplingrate = null;
2385
+ $type = null;
2386
+ $url = null;
2387
+ $width = null;
2388
+
2389
+ // Elements
2390
+ $captions = null;
2391
+ $categories = null;
2392
+ $copyrights = null;
2393
+ $credits = null;
2394
+ $description = null;
2395
+ $hashes = null;
2396
+ $keywords = null;
2397
+ $player = null;
2398
+ $ratings = null;
2399
+ $restrictions = null;
2400
+ $thumbnails = null;
2401
+ $title = null;
2402
+
2403
+ // Start checking the attributes of media:content
2404
+ if (isset($content['attribs']['']['bitrate']))
2405
+ {
2406
+ $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2407
+ }
2408
+ if (isset($content['attribs']['']['channels']))
2409
+ {
2410
+ $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2411
+ }
2412
+ if (isset($content['attribs']['']['duration']))
2413
+ {
2414
+ $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2415
+ }
2416
+ else
2417
+ {
2418
+ $duration = $duration_parent;
2419
+ }
2420
+ if (isset($content['attribs']['']['expression']))
2421
+ {
2422
+ $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2423
+ }
2424
+ if (isset($content['attribs']['']['framerate']))
2425
+ {
2426
+ $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2427
+ }
2428
+ if (isset($content['attribs']['']['height']))
2429
+ {
2430
+ $height = $this->sanitize($content['attribs']['']['height'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2431
+ }
2432
+ if (isset($content['attribs']['']['lang']))
2433
+ {
2434
+ $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2435
+ }
2436
+ if (isset($content['attribs']['']['fileSize']))
2437
+ {
2438
+ $length = ceil($content['attribs']['']['fileSize']);
2439
+ }
2440
+ if (isset($content['attribs']['']['medium']))
2441
+ {
2442
+ $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2443
+ }
2444
+ if (isset($content['attribs']['']['samplingrate']))
2445
+ {
2446
+ $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2447
+ }
2448
+ if (isset($content['attribs']['']['type']))
2449
+ {
2450
+ $type = $this->sanitize($content['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2451
+ }
2452
+ if (isset($content['attribs']['']['width']))
2453
+ {
2454
+ $width = $this->sanitize($content['attribs']['']['width'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2455
+ }
2456
+ if (isset($content['attribs']['']['url']))
2457
+ {
2458
+ $url = $this->sanitize($content['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2459
+ }
2460
+ // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
2461
+
2462
+ // CAPTIONS
2463
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text']))
2464
+ {
2465
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
2466
+ {
2467
+ $caption_type = null;
2468
+ $caption_lang = null;
2469
+ $caption_startTime = null;
2470
+ $caption_endTime = null;
2471
+ $caption_text = null;
2472
+ if (isset($caption['attribs']['']['type']))
2473
+ {
2474
+ $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2475
+ }
2476
+ if (isset($caption['attribs']['']['lang']))
2477
+ {
2478
+ $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2479
+ }
2480
+ if (isset($caption['attribs']['']['start']))
2481
+ {
2482
+ $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2483
+ }
2484
+ if (isset($caption['attribs']['']['end']))
2485
+ {
2486
+ $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2487
+ }
2488
+ if (isset($caption['data']))
2489
+ {
2490
+ $caption_text = $this->sanitize($caption['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2491
+ }
2492
+ $captions[] = $this->registry->create('Caption', array($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text));
2493
+ }
2494
+ if (is_array($captions))
2495
+ {
2496
+ $captions = array_values(array_unique($captions));
2497
+ }
2498
+ }
2499
+ else
2500
+ {
2501
+ $captions = $captions_parent;
2502
+ }
2503
+
2504
+ // CATEGORIES
2505
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category']))
2506
+ {
2507
+ foreach ((array) $content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['category'] as $category)
2508
+ {
2509
+ $term = null;
2510
+ $scheme = null;
2511
+ $label = null;
2512
+ if (isset($category['data']))
2513
+ {
2514
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2515
+ }
2516
+ if (isset($category['attribs']['']['scheme']))
2517
+ {
2518
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2519
+ }
2520
+ else
2521
+ {
2522
+ $scheme = 'http://search.yahoo.com/mrss/category_schema';
2523
+ }
2524
+ if (isset($category['attribs']['']['label']))
2525
+ {
2526
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2527
+ }
2528
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
2529
+ }
2530
+ }
2531
+ if (is_array($categories) && is_array($categories_parent))
2532
+ {
2533
+ $categories = array_values(array_unique(array_merge($categories, $categories_parent)));
2534
+ }
2535
+ elseif (is_array($categories))
2536
+ {
2537
+ $categories = array_values(array_unique($categories));
2538
+ }
2539
+ elseif (is_array($categories_parent))
2540
+ {
2541
+ $categories = array_values(array_unique($categories_parent));
2542
+ }
2543
+ else
2544
+ {
2545
+ $categories = null;
2546
+ }
2547
+
2548
+ // COPYRIGHTS
2549
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright']))
2550
+ {
2551
+ $copyright_url = null;
2552
+ $copyright_label = null;
2553
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
2554
+ {
2555
+ $copyright_url = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2556
+ }
2557
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
2558
+ {
2559
+ $copyright_label = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2560
+ }
2561
+ $copyrights = $this->registry->create('Copyright', array($copyright_url, $copyright_label));
2562
+ }
2563
+ else
2564
+ {
2565
+ $copyrights = $copyrights_parent;
2566
+ }
2567
+
2568
+ // CREDITS
2569
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit']))
2570
+ {
2571
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
2572
+ {
2573
+ $credit_role = null;
2574
+ $credit_scheme = null;
2575
+ $credit_name = null;
2576
+ if (isset($credit['attribs']['']['role']))
2577
+ {
2578
+ $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2579
+ }
2580
+ if (isset($credit['attribs']['']['scheme']))
2581
+ {
2582
+ $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2583
+ }
2584
+ else
2585
+ {
2586
+ $credit_scheme = 'urn:ebu';
2587
+ }
2588
+ if (isset($credit['data']))
2589
+ {
2590
+ $credit_name = $this->sanitize($credit['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2591
+ }
2592
+ $credits[] = $this->registry->create('Credit', array($credit_role, $credit_scheme, $credit_name));
2593
+ }
2594
+ if (is_array($credits))
2595
+ {
2596
+ $credits = array_values(array_unique($credits));
2597
+ }
2598
+ }
2599
+ else
2600
+ {
2601
+ $credits = $credits_parent;
2602
+ }
2603
+
2604
+ // DESCRIPTION
2605
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description']))
2606
+ {
2607
+ $description = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2608
+ }
2609
+ else
2610
+ {
2611
+ $description = $description_parent;
2612
+ }
2613
+
2614
+ // HASHES
2615
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash']))
2616
+ {
2617
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
2618
+ {
2619
+ $value = null;
2620
+ $algo = null;
2621
+ if (isset($hash['data']))
2622
+ {
2623
+ $value = $this->sanitize($hash['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2624
+ }
2625
+ if (isset($hash['attribs']['']['algo']))
2626
+ {
2627
+ $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2628
+ }
2629
+ else
2630
+ {
2631
+ $algo = 'md5';
2632
+ }
2633
+ $hashes[] = $algo.':'.$value;
2634
+ }
2635
+ if (is_array($hashes))
2636
+ {
2637
+ $hashes = array_values(array_unique($hashes));
2638
+ }
2639
+ }
2640
+ else
2641
+ {
2642
+ $hashes = $hashes_parent;
2643
+ }
2644
+
2645
+ // KEYWORDS
2646
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords']))
2647
+ {
2648
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
2649
+ {
2650
+ $temp = explode(',', $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT));
2651
+ foreach ($temp as $word)
2652
+ {
2653
+ $keywords[] = trim($word);
2654
+ }
2655
+ unset($temp);
2656
+ }
2657
+ if (is_array($keywords))
2658
+ {
2659
+ $keywords = array_values(array_unique($keywords));
2660
+ }
2661
+ }
2662
+ else
2663
+ {
2664
+ $keywords = $keywords_parent;
2665
+ }
2666
+
2667
+ // PLAYER
2668
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player']))
2669
+ {
2670
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'])) {
2671
+ $player = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2672
+ }
2673
+ }
2674
+ else
2675
+ {
2676
+ $player = $player_parent;
2677
+ }
2678
+
2679
+ // RATINGS
2680
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating']))
2681
+ {
2682
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
2683
+ {
2684
+ $rating_scheme = null;
2685
+ $rating_value = null;
2686
+ if (isset($rating['attribs']['']['scheme']))
2687
+ {
2688
+ $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2689
+ }
2690
+ else
2691
+ {
2692
+ $rating_scheme = 'urn:simple';
2693
+ }
2694
+ if (isset($rating['data']))
2695
+ {
2696
+ $rating_value = $this->sanitize($rating['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2697
+ }
2698
+ $ratings[] = $this->registry->create('Rating', array($rating_scheme, $rating_value));
2699
+ }
2700
+ if (is_array($ratings))
2701
+ {
2702
+ $ratings = array_values(array_unique($ratings));
2703
+ }
2704
+ }
2705
+ else
2706
+ {
2707
+ $ratings = $ratings_parent;
2708
+ }
2709
+
2710
+ // RESTRICTIONS
2711
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction']))
2712
+ {
2713
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
2714
+ {
2715
+ $restriction_relationship = null;
2716
+ $restriction_type = null;
2717
+ $restriction_value = null;
2718
+ if (isset($restriction['attribs']['']['relationship']))
2719
+ {
2720
+ $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2721
+ }
2722
+ if (isset($restriction['attribs']['']['type']))
2723
+ {
2724
+ $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2725
+ }
2726
+ if (isset($restriction['data']))
2727
+ {
2728
+ $restriction_value = $this->sanitize($restriction['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2729
+ }
2730
+ $restrictions[] = $this->registry->create('Restriction', array($restriction_relationship, $restriction_type, $restriction_value));
2731
+ }
2732
+ if (is_array($restrictions))
2733
+ {
2734
+ $restrictions = array_values(array_unique($restrictions));
2735
+ }
2736
+ }
2737
+ else
2738
+ {
2739
+ $restrictions = $restrictions_parent;
2740
+ }
2741
+
2742
+ // THUMBNAILS
2743
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail']))
2744
+ {
2745
+ foreach ($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
2746
+ {
2747
+ if (isset($thumbnail['attribs']['']['url'])) {
2748
+ $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI);
2749
+ }
2750
+ }
2751
+ if (is_array($thumbnails))
2752
+ {
2753
+ $thumbnails = array_values(array_unique($thumbnails));
2754
+ }
2755
+ }
2756
+ else
2757
+ {
2758
+ $thumbnails = $thumbnails_parent;
2759
+ }
2760
+
2761
+ // TITLES
2762
+ if (isset($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title']))
2763
+ {
2764
+ $title = $this->sanitize($content['child'][SIMPLECLUVPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2765
+ }
2766
+ else
2767
+ {
2768
+ $title = $title_parent;
2769
+ }
2770
+
2771
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width));
2772
+ }
2773
+ }
2774
+ }
2775
+
2776
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'link') as $link)
2777
+ {
2778
+ if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
2779
+ {
2780
+ // Attributes
2781
+ $bitrate = null;
2782
+ $channels = null;
2783
+ $duration = null;
2784
+ $expression = null;
2785
+ $framerate = null;
2786
+ $height = null;
2787
+ $javascript = null;
2788
+ $lang = null;
2789
+ $length = null;
2790
+ $medium = null;
2791
+ $samplingrate = null;
2792
+ $type = null;
2793
+ $url = null;
2794
+ $width = null;
2795
+
2796
+ $url = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
2797
+ if (isset($link['attribs']['']['type']))
2798
+ {
2799
+ $type = $this->sanitize($link['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2800
+ }
2801
+ if (isset($link['attribs']['']['length']))
2802
+ {
2803
+ $length = ceil($link['attribs']['']['length']);
2804
+ }
2805
+
2806
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2807
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $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));
2808
+ }
2809
+ }
2810
+
2811
+ foreach ((array) $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'link') as $link)
2812
+ {
2813
+ if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
2814
+ {
2815
+ // Attributes
2816
+ $bitrate = null;
2817
+ $channels = null;
2818
+ $duration = null;
2819
+ $expression = null;
2820
+ $framerate = null;
2821
+ $height = null;
2822
+ $javascript = null;
2823
+ $lang = null;
2824
+ $length = null;
2825
+ $medium = null;
2826
+ $samplingrate = null;
2827
+ $type = null;
2828
+ $url = null;
2829
+ $width = null;
2830
+
2831
+ $url = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
2832
+ if (isset($link['attribs']['']['type']))
2833
+ {
2834
+ $type = $this->sanitize($link['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2835
+ }
2836
+ if (isset($link['attribs']['']['length']))
2837
+ {
2838
+ $length = ceil($link['attribs']['']['length']);
2839
+ }
2840
+
2841
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2842
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $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));
2843
+ }
2844
+ }
2845
+
2846
+ if ($enclosure = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'enclosure'))
2847
+ {
2848
+ if (isset($enclosure[0]['attribs']['']['url']))
2849
+ {
2850
+ // Attributes
2851
+ $bitrate = null;
2852
+ $channels = null;
2853
+ $duration = null;
2854
+ $expression = null;
2855
+ $framerate = null;
2856
+ $height = null;
2857
+ $javascript = null;
2858
+ $lang = null;
2859
+ $length = null;
2860
+ $medium = null;
2861
+ $samplingrate = null;
2862
+ $type = null;
2863
+ $url = null;
2864
+ $width = null;
2865
+
2866
+ $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
2867
+ if (isset($enclosure[0]['attribs']['']['type']))
2868
+ {
2869
+ $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
2870
+ }
2871
+ if (isset($enclosure[0]['attribs']['']['length']))
2872
+ {
2873
+ $length = ceil($enclosure[0]['attribs']['']['length']);
2874
+ }
2875
+
2876
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2877
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $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));
2878
+ }
2879
+ }
2880
+
2881
+ 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))
2882
+ {
2883
+ // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
2884
+ $this->data['enclosures'][] = $this->registry->create('Enclosure', array($url, $type, $length, null, $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));
2885
+ }
2886
+
2887
+ $this->data['enclosures'] = array_values(array_unique($this->data['enclosures']));
2888
+ }
2889
+ if (!empty($this->data['enclosures']))
2890
+ {
2891
+ return $this->data['enclosures'];
2892
+ }
2893
+ else
2894
+ {
2895
+ return null;
2896
+ }
2897
+ }
2898
+
2899
+ /**
2900
+ * Get the latitude coordinates for the item
2901
+ *
2902
+ * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2903
+ *
2904
+ * Uses `<geo:lat>` or `<georss:point>`
2905
+ *
2906
+ * @since 1.0
2907
+ * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2908
+ * @link http://www.georss.org/ GeoRSS
2909
+ * @return string|null
2910
+ */
2911
+ public function get_latitude()
2912
+ {
2913
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
2914
+ {
2915
+ return (float) $return[0]['data'];
2916
+ }
2917
+ elseif (($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2918
+ {
2919
+ return (float) $match[1];
2920
+ }
2921
+ else
2922
+ {
2923
+ return null;
2924
+ }
2925
+ }
2926
+
2927
+ /**
2928
+ * Get the longitude coordinates for the item
2929
+ *
2930
+ * Compatible with the W3C WGS84 Basic Geo and GeoRSS specifications
2931
+ *
2932
+ * Uses `<geo:long>`, `<geo:lon>` or `<georss:point>`
2933
+ *
2934
+ * @since 1.0
2935
+ * @link http://www.w3.org/2003/01/geo/ W3C WGS84 Basic Geo
2936
+ * @link http://www.georss.org/ GeoRSS
2937
+ * @return string|null
2938
+ */
2939
+ public function get_longitude()
2940
+ {
2941
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
2942
+ {
2943
+ return (float) $return[0]['data'];
2944
+ }
2945
+ elseif ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
2946
+ {
2947
+ return (float) $return[0]['data'];
2948
+ }
2949
+ elseif (($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
2950
+ {
2951
+ return (float) $match[2];
2952
+ }
2953
+ else
2954
+ {
2955
+ return null;
2956
+ }
2957
+ }
2958
+
2959
+ /**
2960
+ * Get the `<atom:source>` for the item
2961
+ *
2962
+ * @since 1.1
2963
+ * @return SimpleCluvPie_Source|null
2964
+ */
2965
+ public function get_source()
2966
+ {
2967
+ if ($return = $this->get_item_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'source'))
2968
+ {
2969
+ return $this->registry->create('Source', array($this, $return[0]));
2970
+ }
2971
+ else
2972
+ {
2973
+ return null;
2974
+ }
2975
+ }
2976
+ }
2977
+
libs/SimpleCluvPie/library/SimpleCluvPie/Locator.php ADDED
@@ -0,0 +1,429 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Used for feed auto-discovery
46
+ *
47
+ *
48
+ * This class can be overloaded with {@see SimpleCluvPie::set_locator_class()}
49
+ *
50
+ * @package SimpleCluvPie
51
+ */
52
+ class SimpleCluvPie_Locator
53
+ {
54
+ var $useragent;
55
+ var $timeout;
56
+ var $file;
57
+ var $local = array();
58
+ var $elsewhere = array();
59
+ var $cached_entities = array();
60
+ var $http_base;
61
+ var $base;
62
+ var $base_location = 0;
63
+ var $checked_feeds = 0;
64
+ var $max_checked_feeds = 10;
65
+ protected $registry;
66
+
67
+ public function __construct(SimpleCluvPie_File $file, $timeout = 10, $useragent = null, $max_checked_feeds = 10)
68
+ {
69
+ $this->file = $file;
70
+ $this->useragent = $useragent;
71
+ $this->timeout = $timeout;
72
+ $this->max_checked_feeds = $max_checked_feeds;
73
+
74
+ if (class_exists('DOMDocument'))
75
+ {
76
+ $this->dom = new DOMDocument();
77
+
78
+ set_error_handler(array('SimpleCluvPie_Misc', 'silence_errors'));
79
+ $this->dom->loadHTML($this->file->body);
80
+ restore_error_handler();
81
+ }
82
+ else
83
+ {
84
+ $this->dom = null;
85
+ }
86
+ }
87
+
88
+ public function set_registry(SimpleCluvPie_Registry $registry)
89
+ {
90
+ $this->registry = $registry;
91
+ }
92
+
93
+ public function find($type = SIMPLECLUVPIE_LOCATOR_ALL, &$working)
94
+ {
95
+ if ($this->is_feed($this->file))
96
+ {
97
+ return $this->file;
98
+ }
99
+
100
+ if ($this->file->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE)
101
+ {
102
+ $sniffer = $this->registry->create('Content_Type_Sniffer', array($this->file));
103
+ if ($sniffer->get_type() !== 'text/html')
104
+ {
105
+ return null;
106
+ }
107
+ }
108
+
109
+ if ($type & ~SIMPLECLUVPIE_LOCATOR_NONE)
110
+ {
111
+ $this->get_base();
112
+ }
113
+
114
+ if ($type & SIMPLECLUVPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
115
+ {
116
+ return $working[0];
117
+ }
118
+
119
+ if ($type & (SIMPLECLUVPIE_LOCATOR_LOCAL_EXTENSION | SIMPLECLUVPIE_LOCATOR_LOCAL_BODY | SIMPLECLUVPIE_LOCATOR_REMOTE_EXTENSION | SIMPLECLUVPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
120
+ {
121
+ if ($type & SIMPLECLUVPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
122
+ {
123
+ return $working[0];
124
+ }
125
+
126
+ if ($type & SIMPLECLUVPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
127
+ {
128
+ return $working[0];
129
+ }
130
+
131
+ if ($type & SIMPLECLUVPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
132
+ {
133
+ return $working[0];
134
+ }
135
+
136
+ if ($type & SIMPLECLUVPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
137
+ {
138
+ return $working[0];
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+
144
+ public function is_feed($file, $check_html = false)
145
+ {
146
+ if ($file->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE)
147
+ {
148
+ $sniffer = $this->registry->create('Content_Type_Sniffer', array($file));
149
+ $sniffed = $sniffer->get_type();
150
+ $mime_types = array('application/rss+xml', 'application/rdf+xml',
151
+ 'text/rdf', 'application/atom+xml', 'text/xml',
152
+ 'application/xml', 'application/x-rss+xml');
153
+ if ($check_html)
154
+ {
155
+ $mime_types[] = 'text/html';
156
+ }
157
+ if (in_array($sniffed, $mime_types))
158
+ {
159
+ return true;
160
+ }
161
+ else
162
+ {
163
+ return false;
164
+ }
165
+ }
166
+ elseif ($file->method & SIMPLECLUVPIE_FILE_SOURCE_LOCAL)
167
+ {
168
+ return true;
169
+ }
170
+ else
171
+ {
172
+ return false;
173
+ }
174
+ }
175
+
176
+ public function get_base()
177
+ {
178
+ if ($this->dom === null)
179
+ {
180
+ throw new SimpleCluvPie_Exception('DOMDocument not found, unable to use locator');
181
+ }
182
+ $this->http_base = $this->file->url;
183
+ $this->base = $this->http_base;
184
+ $elements = $this->dom->getElementsByTagName('base');
185
+ foreach ($elements as $element)
186
+ {
187
+ if ($element->hasAttribute('href'))
188
+ {
189
+ $base = $this->registry->call('Misc', 'absolutize_url', array(trim($element->getAttribute('href')), $this->http_base));
190
+ if ($base === false)
191
+ {
192
+ continue;
193
+ }
194
+ $this->base = $base;
195
+ $this->base_location = method_exists($element, 'getLineNo') ? $element->getLineNo() : 0;
196
+ break;
197
+ }
198
+ }
199
+ }
200
+
201
+ public function autodiscovery()
202
+ {
203
+ $done = array();
204
+ $feeds = array();
205
+ $feeds = array_merge($feeds, $this->search_elements_by_tag('link', $done, $feeds));
206
+ $feeds = array_merge($feeds, $this->search_elements_by_tag('a', $done, $feeds));
207
+ $feeds = array_merge($feeds, $this->search_elements_by_tag('area', $done, $feeds));
208
+
209
+ if (!empty($feeds))
210
+ {
211
+ return array_values($feeds);
212
+ }
213
+ else
214
+ {
215
+ return null;
216
+ }
217
+ }
218
+
219
+ protected function search_elements_by_tag($name, &$done, $feeds)
220
+ {
221
+ if ($this->dom === null)
222
+ {
223
+ throw new SimpleCluvPie_Exception('DOMDocument not found, unable to use locator');
224
+ }
225
+
226
+ $links = $this->dom->getElementsByTagName($name);
227
+ foreach ($links as $link)
228
+ {
229
+ if ($this->checked_feeds === $this->max_checked_feeds)
230
+ {
231
+ break;
232
+ }
233
+ if ($link->hasAttribute('href') && $link->hasAttribute('rel'))
234
+ {
235
+ $rel = array_unique($this->registry->call('Misc', 'space_seperated_tokens', array(strtolower($link->getAttribute('rel')))));
236
+ $line = method_exists($link, 'getLineNo') ? $link->getLineNo() : 1;
237
+
238
+ if ($this->base_location < $line)
239
+ {
240
+ $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
241
+ }
242
+ else
243
+ {
244
+ $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
245
+ }
246
+ if ($href === false)
247
+ {
248
+ continue;
249
+ }
250
+
251
+ if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && $link->hasAttribute('type') && in_array(strtolower($this->registry->call('Misc', 'parse_mime', array($link->getAttribute('type')))), array('text/html', 'application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
252
+ {
253
+ $this->checked_feeds++;
254
+ $headers = array(
255
+ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
256
+ );
257
+ $feed = $this->registry->create('File', array($href, $this->timeout, 5, $headers, $this->useragent));
258
+ if ($feed->success && ($feed->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed, true))
259
+ {
260
+ $feeds[$href] = $feed;
261
+ }
262
+ }
263
+ $done[] = $href;
264
+ }
265
+ }
266
+
267
+ return $feeds;
268
+ }
269
+
270
+ public function get_links()
271
+ {
272
+ if ($this->dom === null)
273
+ {
274
+ throw new SimpleCluvPie_Exception('DOMDocument not found, unable to use locator');
275
+ }
276
+
277
+ $links = $this->dom->getElementsByTagName('a');
278
+ foreach ($links as $link)
279
+ {
280
+ if ($link->hasAttribute('href'))
281
+ {
282
+ $href = trim($link->getAttribute('href'));
283
+ $parsed = $this->registry->call('Misc', 'parse_url', array($href));
284
+ if ($parsed['scheme'] === '' || preg_match('/^(https?|feed)?$/i', $parsed['scheme']))
285
+ {
286
+ if (method_exists($link, 'getLineNo') && $this->base_location < $link->getLineNo())
287
+ {
288
+ $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->base));
289
+ }
290
+ else
291
+ {
292
+ $href = $this->registry->call('Misc', 'absolutize_url', array(trim($link->getAttribute('href')), $this->http_base));
293
+ }
294
+ if ($href === false)
295
+ {
296
+ continue;
297
+ }
298
+
299
+ $current = $this->registry->call('Misc', 'parse_url', array($this->file->url));
300
+
301
+ if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
302
+ {
303
+ $this->local[] = $href;
304
+ }
305
+ else
306
+ {
307
+ $this->elsewhere[] = $href;
308
+ }
309
+ }
310
+ }
311
+ }
312
+ $this->local = array_unique($this->local);
313
+ $this->elsewhere = array_unique($this->elsewhere);
314
+ if (!empty($this->local) || !empty($this->elsewhere))
315
+ {
316
+ return true;
317
+ }
318
+ return null;
319
+ }
320
+
321
+ public function get_rel_link($rel)
322
+ {
323
+ if ($this->dom === null)
324
+ {
325
+ throw new SimpleCluvPie_Exception('DOMDocument not found, unable to use '.
326
+ 'locator');
327
+ }
328
+ if (!class_exists('DOMXpath'))
329
+ {
330
+ throw new SimpleCluvPie_Exception('DOMXpath not found, unable to use '.
331
+ 'get_rel_link');
332
+ }
333
+
334
+ $xpath = new DOMXpath($this->dom);
335
+ $query = '//a[@rel and @href] | //link[@rel and @href]';
336
+ foreach ($xpath->query($query) as $link)
337
+ {
338
+ $href = trim($link->getAttribute('href'));
339
+ $parsed = $this->registry->call('Misc', 'parse_url', array($href));
340
+ if ($parsed['scheme'] === '' ||
341
+ preg_match('/^https?$/i', $parsed['scheme']))
342
+ {
343
+ if (method_exists($link, 'getLineNo') &&
344
+ $this->base_location < $link->getLineNo())
345
+ {
346
+ $href =
347
+ $this->registry->call('Misc', 'absolutize_url',
348
+ array(trim($link->getAttribute('href')),
349
+ $this->base));
350
+ }
351
+ else
352
+ {
353
+ $href =
354
+ $this->registry->call('Misc', 'absolutize_url',
355
+ array(trim($link->getAttribute('href')),
356
+ $this->http_base));
357
+ }
358
+ if ($href === false)
359
+ {
360
+ return null;
361
+ }
362
+ $rel_values = explode(' ', strtolower($link->getAttribute('rel')));
363
+ if (in_array($rel, $rel_values))
364
+ {
365
+ return $href;
366
+ }
367
+ }
368
+ }
369
+ return null;
370
+ }
371
+
372
+ public function extension(&$array)
373
+ {
374
+ foreach ($array as $key => $value)
375
+ {
376
+ if ($this->checked_feeds === $this->max_checked_feeds)
377
+ {
378
+ break;
379
+ }
380
+ if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
381
+ {
382
+ $this->checked_feeds++;
383
+
384
+ $headers = array(
385
+ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
386
+ );
387
+ $feed = $this->registry->create('File', array($value, $this->timeout, 5, $headers, $this->useragent));
388
+ if ($feed->success && ($feed->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
389
+ {
390
+ return array($feed);
391
+ }
392
+ else
393
+ {
394
+ unset($array[$key]);
395
+ }
396
+ }
397
+ }
398
+ return null;
399
+ }
400
+
401
+ public function body(&$array)
402
+ {
403
+ foreach ($array as $key => $value)
404
+ {
405
+ if ($this->checked_feeds === $this->max_checked_feeds)
406
+ {
407
+ break;
408
+ }
409
+ if (preg_match('/(rss|rdf|atom|xml)/i', $value))
410
+ {
411
+ $this->checked_feeds++;
412
+ $headers = array(
413
+ 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
414
+ );
415
+ $feed = $this->registry->create('File', array($value, $this->timeout, 5, null, $this->useragent));
416
+ if ($feed->success && ($feed->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
417
+ {
418
+ return array($feed);
419
+ }
420
+ else
421
+ {
422
+ unset($array[$key]);
423
+ }
424
+ }
425
+ }
426
+ return null;
427
+ }
428
+ }
429
+
libs/SimpleCluvPie/library/SimpleCluvPie/Misc.php ADDED
@@ -0,0 +1,2263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Miscellanous utilities
46
+ *
47
+ * @package SimpleCluvPie
48
+ */
49
+ class SimpleCluvPie_Misc
50
+ {
51
+ public static function time_hms($seconds)
52
+ {
53
+ $time = '';
54
+
55
+ $hours = floor($seconds / 3600);
56
+ $remainder = $seconds % 3600;
57
+ if ($hours > 0)
58
+ {
59
+ $time .= $hours.':';
60
+ }
61
+
62
+ $minutes = floor($remainder / 60);
63
+ $seconds = $remainder % 60;
64
+ if ($minutes < 10 && $hours > 0)
65
+ {
66
+ $minutes = '0' . $minutes;
67
+ }
68
+ if ($seconds < 10)
69
+ {
70
+ $seconds = '0' . $seconds;
71
+ }
72
+
73
+ $time .= $minutes.':';
74
+ $time .= $seconds;
75
+
76
+ return $time;
77
+ }
78
+
79
+ public static function absolutize_url($relative, $base)
80
+ {
81
+ $iri = SimpleCluvPie_IRI::absolutize(new SimpleCluvPie_IRI($base), $relative);
82
+ if ($iri === false)
83
+ {
84
+ return false;
85
+ }
86
+ return $iri->get_uri();
87
+ }
88
+
89
+ /**
90
+ * Get a HTML/XML element from a HTML string
91
+ *
92
+ * @deprecated Use DOMDocument instead (parsing HTML with regex is bad!)
93
+ * @param string $realname Element name (including namespace prefix if applicable)
94
+ * @param string $string HTML document
95
+ * @return array
96
+ */
97
+ public static function get_element($realname, $string)
98
+ {
99
+ $return = array();
100
+ $name = preg_quote($realname, '/');
101
+ if (preg_match_all("/<($name)" . SIMPLECLUVPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
102
+ {
103
+ for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
104
+ {
105
+ $return[$i]['tag'] = $realname;
106
+ $return[$i]['full'] = $matches[$i][0][0];
107
+ $return[$i]['offset'] = $matches[$i][0][1];
108
+ if (strlen($matches[$i][3][0]) <= 2)
109
+ {
110
+ $return[$i]['self_closing'] = true;
111
+ }
112
+ else
113
+ {
114
+ $return[$i]['self_closing'] = false;
115
+ $return[$i]['content'] = $matches[$i][4][0];
116
+ }
117
+ $return[$i]['attribs'] = array();
118
+ 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))
119
+ {
120
+ for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
121
+ {
122
+ if (count($attribs[$j]) === 2)
123
+ {
124
+ $attribs[$j][2] = $attribs[$j][1];
125
+ }
126
+ $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimpleCluvPie_Misc::entities_decode(end($attribs[$j]));
127
+ }
128
+ }
129
+ }
130
+ }
131
+ return $return;
132
+ }
133
+
134
+ public static function element_implode($element)
135
+ {
136
+ $full = "<$element[tag]";
137
+ foreach ($element['attribs'] as $key => $value)
138
+ {
139
+ $key = strtolower($key);
140
+ $full .= " $key=\"" . htmlspecialchars($value['data'], ENT_COMPAT, 'UTF-8') . '"';
141
+ }
142
+ if ($element['self_closing'])
143
+ {
144
+ $full .= ' />';
145
+ }
146
+ else
147
+ {
148
+ $full .= ">$element[content]</$element[tag]>";
149
+ }
150
+ return $full;
151
+ }
152
+
153
+ public static function error($message, $level, $file, $line)
154
+ {
155
+ if ((ini_get('error_reporting') & $level) > 0)
156
+ {
157
+ switch ($level)
158
+ {
159
+ case E_USER_ERROR:
160
+ $note = 'PHP Error';
161
+ break;
162
+ case E_USER_WARNING:
163
+ $note = 'PHP Warning';
164
+ break;
165
+ case E_USER_NOTICE:
166
+ $note = 'PHP Notice';
167
+ break;
168
+ default:
169
+ $note = 'Unknown Error';
170
+ break;
171
+ }
172
+
173
+ $log_error = true;
174
+ if (!function_exists('error_log'))
175
+ {
176
+ $log_error = false;
177
+ }
178
+
179
+ $log_file = @ini_get('error_log');
180
+ if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file))
181
+ {
182
+ $log_error = false;
183
+ }
184
+
185
+ if ($log_error)
186
+ {
187
+ @error_log("$note: $message in $file on line $line", 0);
188
+ }
189
+ }
190
+
191
+ return $message;
192
+ }
193
+
194
+ public static function fix_protocol($url, $http = 1)
195
+ {
196
+ $url = SimpleCluvPie_Misc::normalize_url($url);
197
+ $parsed = SimpleCluvPie_Misc::parse_url($url);
198
+ if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
199
+ {
200
+ return SimpleCluvPie_Misc::fix_protocol(SimpleCluvPie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
201
+ }
202
+
203
+ if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
204
+ {
205
+ return SimpleCluvPie_Misc::fix_protocol(SimpleCluvPie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
206
+ }
207
+
208
+ if ($http === 2 && $parsed['scheme'] !== '')
209
+ {
210
+ return "feed:$url";
211
+ }
212
+ elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
213
+ {
214
+ return substr_replace($url, 'podcast', 0, 4);
215
+ }
216
+ elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
217
+ {
218
+ return substr_replace($url, 'itpc', 0, 4);
219
+ }
220
+ else
221
+ {
222
+ return $url;
223
+ }
224
+ }
225
+
226
+ public static function array_merge_recursive($array1, $array2)
227
+ {
228
+ foreach ($array2 as $key => $value)
229
+ {
230
+ if (is_array($value))
231
+ {
232
+ $array1[$key] = SimpleCluvPie_Misc::array_merge_recursive($array1[$key], $value);
233
+ }
234
+ else
235
+ {
236
+ $array1[$key] = $value;
237
+ }
238
+ }
239
+
240
+ return $array1;
241
+ }
242
+
243
+ public static function parse_url($url)
244
+ {
245
+ $iri = new SimpleCluvPie_IRI($url);
246
+ return array(
247
+ 'scheme' => (string) $iri->scheme,
248
+ 'authority' => (string) $iri->authority,
249
+ 'path' => (string) $iri->path,
250
+ 'query' => (string) $iri->query,
251
+ 'fragment' => (string) $iri->fragment
252
+ );
253
+ }
254
+
255
+ public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
256
+ {
257
+ $iri = new SimpleCluvPie_IRI('');
258
+ $iri->scheme = $scheme;
259
+ $iri->authority = $authority;
260
+ $iri->path = $path;
261
+ $iri->query = $query;
262
+ $iri->fragment = $fragment;
263
+ return $iri->get_uri();
264
+ }
265
+
266
+ public static function normalize_url($url)
267
+ {
268
+ $iri = new SimpleCluvPie_IRI($url);
269
+ return $iri->get_uri();
270
+ }
271
+
272
+ public static function percent_encoding_normalization($match)
273
+ {
274
+ $integer = hexdec($match[1]);
275
+ if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
276
+ {
277
+ return chr($integer);
278
+ }
279
+ else
280
+ {
281
+ return strtoupper($match[0]);
282
+ }
283
+ }
284
+
285
+ /**
286
+ * Converts a Windows-1252 encoded string to a UTF-8 encoded string
287
+ *
288
+ * @static
289
+ * @param string $string Windows-1252 encoded string
290
+ * @return string UTF-8 encoded string
291
+ */
292
+ public static function windows_1252_to_utf8($string)
293
+ {
294
+ 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");
295
+
296
+ return strtr($string, $convert_table);
297
+ }
298
+
299
+ /**
300
+ * Change a string from one encoding to another
301
+ *
302
+ * @param string $data Raw data in $input encoding
303
+ * @param string $input Encoding of $data
304
+ * @param string $output Encoding you want
305
+ * @return string|boolean False if we can't convert it
306
+ */
307
+ public static function change_encoding($data, $input, $output)
308
+ {
309
+ $input = SimpleCluvPie_Misc::encoding($input);
310
+ $output = SimpleCluvPie_Misc::encoding($output);
311
+
312
+ // We fail to fail on non US-ASCII bytes
313
+ if ($input === 'US-ASCII')
314
+ {
315
+ static $non_ascii_octects = '';
316
+ if (!$non_ascii_octects)
317
+ {
318
+ for ($i = 0x80; $i <= 0xFF; $i++)
319
+ {
320
+ $non_ascii_octects .= chr($i);
321
+ }
322
+ }
323
+ $data = substr($data, 0, strcspn($data, $non_ascii_octects));
324
+ }
325
+
326
+ // This is first, as behaviour of this is completely predictable
327
+ if ($input === 'windows-1252' && $output === 'UTF-8')
328
+ {
329
+ return SimpleCluvPie_Misc::windows_1252_to_utf8($data);
330
+ }
331
+ // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
332
+ elseif (function_exists('mb_convert_encoding') && ($return = SimpleCluvPie_Misc::change_encoding_mbstring($data, $input, $output)))
333
+ {
334
+ return $return;
335
+ }
336
+ // This is last, as behaviour of this varies with OS userland and PHP version
337
+ elseif (function_exists('iconv') && ($return = SimpleCluvPie_Misc::change_encoding_iconv($data, $input, $output)))
338
+ {
339
+ return $return;
340
+ }
341
+ // If we can't do anything, just fail
342
+ else
343
+ {
344
+ return false;
345
+ }
346
+ }
347
+
348
+ protected static function change_encoding_mbstring($data, $input, $output)
349
+ {
350
+ if ($input === 'windows-949')
351
+ {
352
+ $input = 'EUC-KR';
353
+ }
354
+ if ($output === 'windows-949')
355
+ {
356
+ $output = 'EUC-KR';
357
+ }
358
+ if ($input === 'Windows-31J')
359
+ {
360
+ $input = 'SJIS';
361
+ }
362
+ if ($output === 'Windows-31J')
363
+ {
364
+ $output = 'SJIS';
365
+ }
366
+
367
+ // Check that the encoding is supported
368
+ if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80")
369
+ {
370
+ return false;
371
+ }
372
+ if (!in_array($input, mb_list_encodings()))
373
+ {
374
+ return false;
375
+ }
376
+
377
+ // Let's do some conversion
378
+ if ($return = @mb_convert_encoding($data, $output, $input))
379
+ {
380
+ return $return;
381
+ }
382
+
383
+ return false;
384
+ }
385
+
386
+ protected static function change_encoding_iconv($data, $input, $output)
387
+ {
388
+ return @iconv($input, $output, $data);
389
+ }
390
+
391
+ /**
392
+ * Normalize an encoding name
393
+ *
394
+ * This is automatically generated by create.php
395
+ *
396
+ * To generate it, run `php create.php` on the command line, and copy the
397
+ * output to replace this function.
398
+ *
399
+ * @param string $charset Character set to standardise
400
+ * @return string Standardised name
401
+ */
402
+ public static function encoding($charset)
403
+ {
404
+ // Normalization from UTS #22
405
+ switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
406
+ {
407
+ case 'adobestandardencoding':
408
+ case 'csadobestandardencoding':
409
+ return 'Adobe-Standard-Encoding';
410
+
411
+ case 'adobesymbolencoding':
412
+ case 'cshppsmath':
413
+ return 'Adobe-Symbol-Encoding';
414
+
415
+ case 'ami1251':
416
+ case 'amiga1251':
417
+ return 'Amiga-1251';
418
+
419
+ case 'ansix31101983':
420
+ case 'csat5001983':
421
+ case 'csiso99naplps':
422
+ case 'isoir99':
423
+ case 'naplps':
424
+ return 'ANSI_X3.110-1983';
425
+
426
+ case 'arabic7':
427
+ case 'asmo449':
428
+ case 'csiso89asmo449':
429
+ case 'iso9036':
430
+ case 'isoir89':
431
+ return 'ASMO_449';
432
+
433
+ case 'big5':
434
+ case 'csbig5':
435
+ return 'Big5';
436
+
437
+ case 'big5hkscs':
438
+ return 'Big5-HKSCS';
439
+
440
+ case 'bocu1':
441
+ case 'csbocu1':
442
+ return 'BOCU-1';
443
+
444
+ case 'brf':
445
+ case 'csbrf':
446
+ return 'BRF';
447
+
448
+ case 'bs4730':
449
+ case 'csiso4unitedkingdom':
450
+ case 'gb':
451
+ case 'iso646gb':
452
+ case 'isoir4':
453
+ case 'uk':
454
+ return 'BS_4730';
455
+
456
+ case 'bsviewdata':
457
+ case 'csiso47bsviewdata':
458
+ case 'isoir47':
459
+ return 'BS_viewdata';
460
+
461
+ case 'cesu8':
462
+ case 'cscesu8':
463
+ return 'CESU-8';
464
+
465
+ case 'ca':
466
+ case 'csa71':
467
+ case 'csaz243419851':
468
+ case 'csiso121canadian1':
469
+ case 'iso646ca':
470
+ case 'isoir121':
471
+ return 'CSA_Z243.4-1985-1';
472
+
473
+ case 'csa72':
474
+ case 'csaz243419852':
475
+ case 'csiso122canadian2':
476
+ case 'iso646ca2':
477
+ case 'isoir122':
478
+ return 'CSA_Z243.4-1985-2';
479
+
480
+ case 'csaz24341985gr':
481
+ case 'csiso123csaz24341985gr':
482
+ case 'isoir123':
483
+ return 'CSA_Z243.4-1985-gr';
484
+
485
+ case 'csiso139csn369103':
486
+ case 'csn369103':
487
+ case 'isoir139':
488
+ return 'CSN_369103';
489
+
490
+ case 'csdecmcs':
491
+ case 'dec':
492
+ case 'decmcs':
493
+ return 'DEC-MCS';
494
+
495
+ case 'csiso21german':
496
+ case 'de':
497
+ case 'din66003':
498
+ case 'iso646de':
499
+ case 'isoir21':
500
+ return 'DIN_66003';
501
+
502
+ case 'csdkus':
503
+ case 'dkus':
504
+ return 'dk-us';
505
+
506
+ case 'csiso646danish':
507
+ case 'dk':
508
+ case 'ds2089':
509
+ case 'iso646dk':
510
+ return 'DS_2089';
511
+
512
+ case 'csibmebcdicatde':
513
+ case 'ebcdicatde':
514
+ return 'EBCDIC-AT-DE';
515
+
516
+ case 'csebcdicatdea':
517
+ case 'ebcdicatdea':
518
+ return 'EBCDIC-AT-DE-A';
519
+
520
+ case 'csebcdiccafr':
521
+ case 'ebcdiccafr':
522
+ return 'EBCDIC-CA-FR';
523
+
524
+ case 'csebcdicdkno':
525
+ case 'ebcdicdkno':
526
+ return 'EBCDIC-DK-NO';
527
+
528
+ case 'csebcdicdknoa':
529
+ case 'ebcdicdknoa':
530
+ return 'EBCDIC-DK-NO-A';
531
+
532
+ case 'csebcdices':
533
+ case 'ebcdices':
534
+ return 'EBCDIC-ES';
535
+
536
+ case 'csebcdicesa':
537
+ case 'ebcdicesa':
538
+ return 'EBCDIC-ES-A';
539
+
540
+ case 'csebcdicess':
541
+ case 'ebcdicess':
542
+ return 'EBCDIC-ES-S';
543
+
544
+ case 'csebcdicfise':
545
+ case 'ebcdicfise':
546
+ return 'EBCDIC-FI-SE';
547
+
548
+ case 'csebcdicfisea':
549
+ case 'ebcdicfisea':
550
+ return 'EBCDIC-FI-SE-A';
551
+
552
+ case 'csebcdicfr':
553
+ case 'ebcdicfr':
554
+ return 'EBCDIC-FR';
555
+
556
+ case 'csebcdicit':
557
+ case 'ebcdicit':
558
+ return 'EBCDIC-IT';
559
+
560
+ case 'csebcdicpt':
561
+ case 'ebcdicpt':
562
+ return 'EBCDIC-PT';
563
+
564
+ case 'csebcdicuk':
565
+ case 'ebcdicuk':
566
+ return 'EBCDIC-UK';
567
+
568
+ case 'csebcdicus':
569
+ case 'ebcdicus':
570
+ return 'EBCDIC-US';
571
+
572
+ case 'csiso111ecmacyrillic':
573
+ case 'ecmacyrillic':
574
+ case 'isoir111':
575
+ case 'koi8e':
576
+ return 'ECMA-cyrillic';
577
+
578
+ case 'csiso17spanish':
579
+ case 'es':
580
+ case 'iso646es':
581
+ case 'isoir17':
582
+ return 'ES';
583
+
584
+ case 'csiso85spanish2':
585
+ case 'es2':
586
+ case 'iso646es2':
587
+ case 'isoir85':
588
+ return 'ES2';
589
+
590
+ case 'cseucpkdfmtjapanese':
591
+ case 'eucjp':
592
+ case 'extendedunixcodepackedformatforjapanese':
593
+ return 'EUC-JP';
594
+
595
+ case 'cseucfixwidjapanese':
596
+ case 'extendedunixcodefixedwidthforjapanese':
597
+ return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
598
+
599
+ case 'gb18030':
600
+ return 'GB18030';
601
+
602
+ case 'chinese':
603
+ case 'cp936':
604
+ case 'csgb2312':
605
+ case 'csiso58gb231280':
606
+ case 'gb2312':
607
+ case 'gb231280':
608
+ case 'gbk':
609
+ case 'isoir58':
610
+ case 'ms936':
611
+ case 'windows936':
612
+ return 'GBK';
613
+
614
+ case 'cn':
615
+ case 'csiso57gb1988':
616
+ case 'gb198880':
617
+ case 'iso646cn':
618
+ case 'isoir57':
619
+ return 'GB_1988-80';
620
+
621
+ case 'csiso153gost1976874':
622
+ case 'gost1976874':
623
+ case 'isoir153':
624
+ case 'stsev35888':
625
+ return 'GOST_19768-74';
626
+
627
+ case 'csiso150':
628
+ case 'csiso150greekccitt':
629
+ case 'greekccitt':
630
+ case 'isoir150':
631
+ return 'greek-ccitt';
632
+
633
+ case 'csiso88greek7':
634
+ case 'greek7':
635
+ case 'isoir88':
636
+ return 'greek7';
637
+
638
+ case 'csiso18greek7old':
639
+ case 'greek7old':
640
+ case 'isoir18':
641
+ return 'greek7-old';
642
+
643
+ case 'cshpdesktop':
644
+ case 'hpdesktop':
645
+ return 'HP-DeskTop';
646
+
647
+ case 'cshplegal':
648
+ case 'hplegal':
649
+ return 'HP-Legal';
650
+
651
+ case 'cshpmath8':
652
+ case 'hpmath8':
653
+ return 'HP-Math8';
654
+
655
+ case 'cshppifont':
656
+ case 'hppifont':
657
+ return 'HP-Pi-font';
658
+
659
+ case 'cshproman8':
660
+ case 'hproman8':
661
+ case 'r8':
662
+ case 'roman8':
663
+ return 'hp-roman8';
664
+
665
+ case 'hzgb2312':
666
+ return 'HZ-GB-2312';
667
+
668
+ case 'csibmsymbols':
669
+ case 'ibmsymbols':
670
+ return 'IBM-Symbols';
671
+
672
+ case 'csibmthai':
673
+ case 'ibmthai':
674
+ return 'IBM-Thai';
675
+
676
+ case 'cp37':
677
+ case 'csibm37':
678
+ case 'ebcdiccpca':
679
+ case 'ebcdiccpnl':
680
+ case 'ebcdiccpus':
681
+ case 'ebcdiccpwt':
682
+ case 'ibm37':
683
+ return 'IBM037';
684
+
685
+ case 'cp38':
686
+ case 'csibm38':
687
+ case 'ebcdicint':
688
+ case 'ibm38':
689
+ return 'IBM038';
690
+
691
+ case 'cp273':
692
+ case 'csibm273':
693
+ case 'ibm273':
694
+ return 'IBM273';
695
+
696
+ case 'cp274':
697
+ case 'csibm274':
698
+ case 'ebcdicbe':
699
+ case 'ibm274':
700
+ return 'IBM274';
701
+
702
+ case 'cp275':
703
+ case 'csibm275':
704
+ case 'ebcdicbr':
705
+ case 'ibm275':
706
+ return 'IBM275';
707
+
708
+ case 'csibm277':
709
+ case 'ebcdiccpdk':
710
+ case 'ebcdiccpno':
711
+ case 'ibm277':
712
+ return 'IBM277';
713
+
714
+ case 'cp278':
715
+ case 'csibm278':
716
+ case 'ebcdiccpfi':
717
+ case 'ebcdiccpse':
718
+ case 'ibm278':
719
+ return 'IBM278';
720
+
721
+ case 'cp280':
722
+ case 'csibm280':
723
+ case 'ebcdiccpit':
724
+ case 'ibm280':
725
+ return 'IBM280';
726
+
727
+ case 'cp281':
728
+ case 'csibm281':
729
+ case 'ebcdicjpe':
730
+ case 'ibm281':
731
+ return 'IBM281';
732
+
733
+ case 'cp284':
734
+ case 'csibm284':
735
+ case 'ebcdiccpes':
736
+ case 'ibm284':
737
+ return 'IBM284';
738
+
739
+ case 'cp285':
740
+ case 'csibm285':
741
+ case 'ebcdiccpgb':
742
+ case 'ibm285':
743
+ return 'IBM285';
744
+
745
+ case 'cp290':
746
+ case 'csibm290':
747
+ case 'ebcdicjpkana':
748
+ case 'ibm290':
749
+ return 'IBM290';
750
+
751
+ case 'cp297':
752
+ case 'csibm297':
753
+ case 'ebcdiccpfr':
754
+ case 'ibm297':
755
+ return 'IBM297';
756
+
757
+ case 'cp420':
758
+ case 'csibm420':
759
+ case 'ebcdiccpar1':
760
+ case 'ibm420':
761
+ return 'IBM420';
762
+
763
+ case 'cp423':
764
+ case 'csibm423':
765
+ case 'ebcdiccpgr':
766
+ case 'ibm423':
767
+ return 'IBM423';
768
+
769
+ case 'cp424':
770
+ case 'csibm424':
771
+ case 'ebcdiccphe':
772
+ case 'ibm424':
773
+ return 'IBM424';
774
+
775
+ case '437':
776
+ case 'cp437':
777
+ case 'cspc8codepage437':
778
+ case 'ibm437':
779
+ return 'IBM437';
780
+
781
+ case 'cp500':
782
+ case 'csibm500':
783
+ case 'ebcdiccpbe':
784
+ case 'ebcdiccpch':
785
+ case 'ibm500':
786
+ return 'IBM500';
787
+
788
+ case 'cp775':
789
+ case 'cspc775baltic':
790
+ case 'ibm775':
791
+ return 'IBM775';
792
+
793
+ case '850':
794
+ case 'cp850':
795
+ case 'cspc850multilingual':
796
+ case 'ibm850':
797
+ return 'IBM850';
798
+
799
+ case '851':
800
+ case 'cp851':
801
+ case 'csibm851':
802
+ case 'ibm851':
803
+ return 'IBM851';
804
+
805
+ case '852':
806
+ case 'cp852':
807
+ case 'cspcp852':
808
+ case 'ibm852':
809
+ return 'IBM852';
810
+
811
+ case '855':
812
+ case 'cp855':
813
+ case 'csibm855':
814
+ case 'ibm855':
815
+ return 'IBM855';
816
+
817
+ case '857':
818
+ case 'cp857':
819
+ case 'csibm857':
820
+ case 'ibm857':
821
+ return 'IBM857';
822
+
823
+ case 'ccsid858':
824
+ case 'cp858':
825
+ case 'ibm858':
826
+ case 'pcmultilingual850euro':
827
+ return 'IBM00858';
828
+
829
+ case '860':
830
+ case 'cp860':
831
+ case 'csibm860':
832
+ case 'ibm860':
833
+ return 'IBM860';
834
+
835
+ case '861':
836
+ case 'cp861':
837
+ case 'cpis':
838
+ case 'csibm861':
839
+ case 'ibm861':
840
+ return 'IBM861';
841
+
842
+ case '862':
843
+ case 'cp862':
844
+ case 'cspc862latinhebrew':
845
+ case 'ibm862':
846
+ return 'IBM862';
847
+
848
+ case '863':
849
+ case 'cp863':
850
+ case 'csibm863':
851
+ case 'ibm863':
852
+ return 'IBM863';
853
+
854
+ case 'cp864':
855
+ case 'csibm864':
856
+ case 'ibm864':
857
+ return 'IBM864';
858
+
859
+ case '865':
860
+ case 'cp865':
861
+ case 'csibm865':
862
+ case 'ibm865':
863
+ return 'IBM865';
864
+
865
+ case '866':
866
+ case 'cp866':
867
+ case 'csibm866':
868
+ case 'ibm866':
869
+ return 'IBM866';
870
+
871
+ case 'cp868':
872
+ case 'cpar':
873
+ case 'csibm868':
874
+ case 'ibm868':
875
+ return 'IBM868';
876
+
877
+ case '869':
878
+ case 'cp869':
879
+ case 'cpgr':
880
+ case 'csibm869':
881
+ case 'ibm869':
882
+ return 'IBM869';
883
+
884
+ case 'cp870':
885
+ case 'csibm870':
886
+ case 'ebcdiccproece':
887
+ case 'ebcdiccpyu':
888
+ case 'ibm870':
889
+ return 'IBM870';
890
+
891
+ case 'cp871':
892
+ case 'csibm871':
893
+ case 'ebcdiccpis':
894
+ case 'ibm871':
895
+ return 'IBM871';
896
+
897
+ case 'cp880':
898
+ case 'csibm880':
899
+ case 'ebcdiccyrillic':
900
+ case 'ibm880':
901
+ return 'IBM880';
902
+
903
+ case 'cp891':
904
+ case 'csibm891':
905
+ case 'ibm891':
906
+ return 'IBM891';
907
+
908
+ case 'cp903':
909
+ case 'csibm903':
910
+ case 'ibm903':
911
+ return 'IBM903';
912
+
913
+ case '904':
914
+ case 'cp904':
915
+ case 'csibbm904':
916
+ case 'ibm904':
917
+ return 'IBM904';
918
+
919
+ case 'cp905':
920
+ case 'csibm905':
921
+ case 'ebcdiccptr':
922
+ case 'ibm905':
923
+ return 'IBM905';
924
+
925
+ case 'cp918':
926
+ case 'csibm918':
927
+ case 'ebcdiccpar2':
928
+ case 'ibm918':
929
+ return 'IBM918';
930
+
931
+ case 'ccsid924':
932
+ case 'cp924':
933
+ case 'ebcdiclatin9euro':
934
+ case 'ibm924':
935
+ return 'IBM00924';
936
+
937
+ case 'cp1026':
938
+ case 'csibm1026':
939
+ case 'ibm1026':
940
+ return 'IBM1026';
941
+
942
+ case 'ibm1047':
943
+ return 'IBM1047';
944
+
945
+ case 'ccsid1140':
946
+ case 'cp1140':
947
+ case 'ebcdicus37euro':
948
+ case 'ibm1140':
949
+ return 'IBM01140';
950
+
951
+ case 'ccsid1141':
952
+ case 'cp1141':
953
+ case 'ebcdicde273euro':
954
+ case 'ibm1141':
955
+ return 'IBM01141';
956
+
957
+ case 'ccsid1142':
958
+ case 'cp1142':
959
+ case 'ebcdicdk277euro':
960
+ case 'ebcdicno277euro':
961
+ case 'ibm1142':
962
+ return 'IBM01142';
963
+
964
+ case 'ccsid1143':
965
+ case 'cp1143':
966
+ case 'ebcdicfi278euro':
967
+ case 'ebcdicse278euro':
968
+ case 'ibm1143':
969
+ return 'IBM01143';
970
+
971
+ case 'ccsid1144':
972
+ case 'cp1144':
973
+ case 'ebcdicit280euro':
974
+ case 'ibm1144':
975
+ return 'IBM01144';
976
+
977
+ case 'ccsid1145':
978
+ case 'cp1145':
979
+ case 'ebcdices284euro':
980
+ case 'ibm1145':
981
+ return 'IBM01145';
982
+
983
+ case 'ccsid1146':
984
+ case 'cp1146':
985
+ case 'ebcdicgb285euro':
986
+ case 'ibm1146':
987
+ return 'IBM01146';
988
+
989
+ case 'ccsid1147':
990
+ case 'cp1147':
991
+ case 'ebcdicfr297euro':
992
+ case 'ibm1147':
993
+ return 'IBM01147';
994
+
995
+ case 'ccsid1148':
996
+ case 'cp1148':
997
+ case 'ebcdicinternational500euro':
998
+ case 'ibm1148':
999
+ return 'IBM01148';
1000
+
1001
+ case 'ccsid1149':
1002
+ case 'cp1149':
1003
+ case 'ebcdicis871euro':
1004
+ case 'ibm1149':
1005
+ return 'IBM01149';
1006
+
1007
+ case 'csiso143iecp271':
1008
+ case 'iecp271':
1009
+ case 'isoir143':
1010
+ return 'IEC_P27-1';
1011
+
1012
+ case 'csiso49inis':
1013
+ case 'inis':
1014
+ case 'isoir49':
1015
+ return 'INIS';
1016
+
1017
+ case 'csiso50inis8':
1018
+ case 'inis8':
1019
+ case 'isoir50':
1020
+ return 'INIS-8';
1021
+
1022
+ case 'csiso51iniscyrillic':
1023
+ case 'iniscyrillic':
1024
+ case 'isoir51':
1025
+ return 'INIS-cyrillic';
1026
+
1027
+ case 'csinvariant':
1028
+ case 'invariant':
1029
+ return 'INVARIANT';
1030
+
1031
+ case 'iso2022cn':
1032
+ return 'ISO-2022-CN';
1033
+
1034
+ case 'iso2022cnext':
1035
+ return 'ISO-2022-CN-EXT';
1036
+
1037
+ case 'csiso2022jp':
1038
+ case 'iso2022jp':
1039
+ return 'ISO-2022-JP';
1040
+
1041
+ case 'csiso2022jp2':
1042
+ case 'iso2022jp2':
1043
+ return 'ISO-2022-JP-2';
1044
+
1045
+ case 'csiso2022kr':
1046
+ case 'iso2022kr':
1047
+ return 'ISO-2022-KR';
1048
+
1049
+ case 'cswindows30latin1':
1050
+ case 'iso88591windows30latin1':
1051
+ return 'ISO-8859-1-Windows-3.0-Latin-1';
1052
+
1053
+ case 'cswindows31latin1':
1054
+ case 'iso88591windows31latin1':
1055
+ return 'ISO-8859-1-Windows-3.1-Latin-1';
1056
+
1057
+ case 'csisolatin2':
1058
+ case 'iso88592':
1059
+ case 'iso885921987':
1060
+ case 'isoir101':
1061
+ case 'l2':
1062
+ case 'latin2':
1063
+ return 'ISO-8859-2';
1064
+
1065
+ case 'cswindows31latin2':
1066
+ case 'iso88592windowslatin2':
1067
+ return 'ISO-8859-2-Windows-Latin-2';
1068
+
1069
+ case 'csisolatin3':
1070
+ case 'iso88593':
1071
+ case 'iso885931988':
1072
+ case 'isoir109':
1073
+ case 'l3':
1074
+ case 'latin3':
1075
+ return 'ISO-8859-3';
1076
+
1077
+ case 'csisolatin4':
1078
+ case 'iso88594':
1079
+ case 'iso885941988':
1080
+ case 'isoir110':
1081
+ case 'l4':
1082
+ case 'latin4':
1083
+ return 'ISO-8859-4';
1084
+
1085
+ case 'csisolatincyrillic':
1086
+ case 'cyrillic':
1087
+ case 'iso88595':
1088
+ case 'iso885951988':
1089
+ case 'isoir144':
1090
+ return 'ISO-8859-5';
1091
+
1092
+ case 'arabic':
1093
+ case 'asmo708':
1094
+ case 'csisolatinarabic':
1095
+ case 'ecma114':
1096
+ case 'iso88596':
1097
+ case 'iso885961987':
1098
+ case 'isoir127':
1099
+ return 'ISO-8859-6';
1100
+
1101
+ case 'csiso88596e':
1102
+ case 'iso88596e':
1103
+ return 'ISO-8859-6-E';
1104
+
1105
+ case 'csiso88596i':
1106
+ case 'iso88596i':
1107
+ return 'ISO-8859-6-I';
1108
+
1109
+ case 'csisolatingreek':
1110
+ case 'ecma118':
1111
+ case 'elot928':
1112
+ case 'greek':
1113
+ case 'greek8':
1114
+ case 'iso88597':
1115
+ case 'iso885971987':
1116
+ case 'isoir126':
1117
+ return 'ISO-8859-7';
1118
+
1119
+ case 'csisolatinhebrew':
1120
+ case 'hebrew':
1121
+ case 'iso88598':
1122
+ case 'iso885981988':
1123
+ case 'isoir138':
1124
+ return 'ISO-8859-8';
1125
+
1126
+ case 'csiso88598e':
1127
+ case 'iso88598e':
1128
+ return 'ISO-8859-8-E';
1129
+
1130
+ case 'csiso88598i':
1131
+ case 'iso88598i':
1132
+ return 'ISO-8859-8-I';
1133
+
1134
+ case 'cswindows31latin5':
1135
+ case 'iso88599windowslatin5':
1136
+ return 'ISO-8859-9-Windows-Latin-5';
1137
+
1138
+ case 'csisolatin6':
1139
+ case 'iso885910':
1140
+ case 'iso8859101992':
1141
+ case 'isoir157':
1142
+ case 'l6':
1143
+ case 'latin6':
1144
+ return 'ISO-8859-10';
1145
+
1146
+ case 'iso885913':
1147
+ return 'ISO-8859-13';
1148
+
1149
+ case 'iso885914':
1150
+ case 'iso8859141998':
1151
+ case 'isoceltic':
1152
+ case 'isoir199':
1153
+ case 'l8':
1154
+ case 'latin8':
1155
+ return 'ISO-8859-14';
1156
+
1157
+ case 'iso885915':
1158
+ case 'latin9':
1159
+ return 'ISO-8859-15';
1160
+
1161
+ case 'iso885916':
1162
+ case 'iso8859162001':
1163
+ case 'isoir226':
1164
+ case 'l10':
1165
+ case 'latin10':
1166
+ return 'ISO-8859-16';
1167
+
1168
+ case 'iso10646j1':
1169
+ return 'ISO-10646-J-1';
1170
+
1171
+ case 'csunicode':
1172
+ case 'iso10646ucs2':
1173
+ return 'ISO-10646-UCS-2';
1174
+
1175
+ case 'csucs4':
1176
+ case 'iso10646ucs4':
1177
+ return 'ISO-10646-UCS-4';
1178
+
1179
+ case 'csunicodeascii':
1180
+ case 'iso10646ucsbasic':
1181
+ return 'ISO-10646-UCS-Basic';
1182
+
1183
+ case 'csunicodelatin1':
1184
+ case 'iso10646':
1185
+ case 'iso10646unicodelatin1':
1186
+ return 'ISO-10646-Unicode-Latin1';
1187
+
1188
+ case 'csiso10646utf1':
1189
+ case 'iso10646utf1':
1190
+ return 'ISO-10646-UTF-1';
1191
+
1192
+ case 'csiso115481':
1193
+ case 'iso115481':
1194
+ case 'isotr115481':
1195
+ return 'ISO-11548-1';
1196
+
1197
+ case 'csiso90':
1198
+ case 'isoir90':
1199
+ return 'iso-ir-90';
1200
+
1201
+ case 'csunicodeibm1261':
1202
+ case 'isounicodeibm1261':
1203
+ return 'ISO-Unicode-IBM-1261';
1204
+
1205
+ case 'csunicodeibm1264':
1206
+ case 'isounicodeibm1264':
1207
+ return 'ISO-Unicode-IBM-1264';
1208
+
1209
+ case 'csunicodeibm1265':
1210
+ case 'isounicodeibm1265':
1211
+ return 'ISO-Unicode-IBM-1265';
1212
+
1213
+ case 'csunicodeibm1268':
1214
+ case 'isounicodeibm1268':
1215
+ return 'ISO-Unicode-IBM-1268';
1216
+
1217
+ case 'csunicodeibm1276':
1218
+ case 'isounicodeibm1276':
1219
+ return 'ISO-Unicode-IBM-1276';
1220
+
1221
+ case 'csiso646basic1983':
1222
+ case 'iso646basic1983':
1223
+ case 'ref':
1224
+ return 'ISO_646.basic:1983';
1225
+
1226
+ case 'csiso2intlrefversion':
1227
+ case 'irv':
1228
+ case 'iso646irv1983':
1229
+ case 'isoir2':
1230
+ return 'ISO_646.irv:1983';
1231
+
1232
+ case 'csiso2033':
1233
+ case 'e13b':
1234
+ case 'iso20331983':
1235
+ case 'isoir98':
1236
+ return 'ISO_2033-1983';
1237
+
1238
+ case 'csiso5427cyrillic':
1239
+ case 'iso5427':
1240
+ case 'isoir37':
1241
+ return 'ISO_5427';
1242
+
1243
+ case 'iso5427cyrillic1981':
1244
+ case 'iso54271981':
1245
+ case 'isoir54':
1246
+ return 'ISO_5427:1981';
1247
+
1248
+ case 'csiso5428greek':
1249
+ case 'iso54281980':
1250
+ case 'isoir55':
1251
+ return 'ISO_5428:1980';
1252
+
1253
+ case 'csiso6937add':
1254
+ case 'iso6937225':
1255
+ case 'isoir152':
1256
+ return 'ISO_6937-2-25';
1257
+
1258
+ case 'csisotextcomm':
1259
+ case 'iso69372add':
1260
+ case 'isoir142':
1261
+ return 'ISO_6937-2-add';
1262
+
1263
+ case 'csiso8859supp':
1264
+ case 'iso8859supp':
1265
+ case 'isoir154':
1266
+ case 'latin125':
1267
+ return 'ISO_8859-supp';
1268
+
1269
+ case 'csiso10367box':
1270
+ case 'iso10367box':
1271
+ case 'isoir155':
1272
+ return 'ISO_10367-box';
1273
+
1274
+ case 'csiso15italian':
1275
+ case 'iso646it':
1276
+ case 'isoir15':
1277
+ case 'it':
1278
+ return 'IT';
1279
+
1280
+ case 'csiso13jisc6220jp':
1281
+ case 'isoir13':
1282
+ case 'jisc62201969':
1283
+ case 'jisc62201969jp':
1284
+ case 'katakana':
1285
+ case 'x2017':
1286
+ return 'JIS_C6220-1969-jp';
1287
+
1288
+ case 'csiso14jisc6220ro':
1289
+ case 'iso646jp':
1290
+ case 'isoir14':
1291
+ case 'jisc62201969ro':
1292
+ case 'jp':
1293
+ return 'JIS_C6220-1969-ro';
1294
+
1295
+ case 'csiso42jisc62261978':
1296
+ case 'isoir42':
1297
+ case 'jisc62261978':
1298
+ return 'JIS_C6226-1978';
1299
+
1300
+ case 'csiso87jisx208':
1301
+ case 'isoir87':
1302
+ case 'jisc62261983':
1303
+ case 'jisx2081983':
1304
+ case 'x208':
1305
+ return 'JIS_C6226-1983';
1306
+
1307
+ case 'csiso91jisc62291984a':
1308
+ case 'isoir91':
1309
+ case 'jisc62291984a':
1310
+ case 'jpocra':
1311
+ return 'JIS_C6229-1984-a';
1312
+
1313
+ case 'csiso92jisc62991984b':
1314
+ case 'iso646jpocrb':
1315
+ case 'isoir92':
1316
+ case 'jisc62291984b':
1317
+ case 'jpocrb':
1318
+ return 'JIS_C6229-1984-b';
1319
+
1320
+ case 'csiso93jis62291984badd':
1321
+ case 'isoir93':
1322
+ case 'jisc62291984badd':
1323
+ case 'jpocrbadd':
1324
+ return 'JIS_C6229-1984-b-add';
1325
+
1326
+ case 'csiso94jis62291984hand':
1327
+ case 'isoir94':
1328
+ case 'jisc62291984hand':
1329
+ case 'jpocrhand':
1330
+ return 'JIS_C6229-1984-hand';
1331
+
1332
+ case 'csiso95jis62291984handadd':
1333
+ case 'isoir95':
1334
+ case 'jisc62291984handadd':
1335
+ case 'jpocrhandadd':
1336
+ return 'JIS_C6229-1984-hand-add';
1337
+
1338
+ case 'csiso96jisc62291984kana':
1339
+ case 'isoir96':
1340
+ case 'jisc62291984kana':
1341
+ return 'JIS_C6229-1984-kana';
1342
+
1343
+ case 'csjisencoding':
1344
+ case 'jisencoding':
1345
+ return 'JIS_Encoding';
1346
+
1347
+ case 'cshalfwidthkatakana':
1348
+ case 'jisx201':
1349
+ case 'x201':
1350
+ return 'JIS_X0201';
1351
+
1352
+ case 'csiso159jisx2121990':
1353
+ case 'isoir159':
1354
+ case 'jisx2121990':
1355
+ case 'x212':
1356
+ return 'JIS_X0212-1990';
1357
+
1358
+ case 'csiso141jusib1002':
1359
+ case 'iso646yu':
1360
+ case 'isoir141':
1361
+ case 'js':
1362
+ case 'jusib1002':
1363
+ case 'yu':
1364
+ return 'JUS_I.B1.002';
1365
+
1366
+ case 'csiso147macedonian':
1367
+ case 'isoir147':
1368
+ case 'jusib1003mac':
1369
+ case 'macedonian':
1370
+ return 'JUS_I.B1.003-mac';
1371
+
1372
+ case 'csiso146serbian':
1373
+ case 'isoir146':
1374
+ case 'jusib1003serb':
1375
+ case 'serbian':
1376
+ return 'JUS_I.B1.003-serb';
1377
+
1378
+ case 'koi7switched':
1379
+ return 'KOI7-switched';
1380
+
1381
+ case 'cskoi8r':
1382
+ case 'koi8r':
1383
+ return 'KOI8-R';
1384
+
1385
+ case 'koi8u':
1386
+ return 'KOI8-U';
1387
+
1388
+ case 'csksc5636':
1389
+ case 'iso646kr':
1390
+ case 'ksc5636':
1391
+ return 'KSC5636';
1392
+
1393
+ case 'cskz1048':
1394
+ case 'kz1048':
1395
+ case 'rk1048':
1396
+ case 'strk10482002':
1397
+ return 'KZ-1048';
1398
+
1399
+ case 'csiso19latingreek':
1400
+ case 'isoir19':
1401
+ case 'latingreek':
1402
+ return 'latin-greek';
1403
+
1404
+ case 'csiso27latingreek1':
1405
+ case 'isoir27':
1406
+ case 'latingreek1':
1407
+ return 'Latin-greek-1';
1408
+
1409
+ case 'csiso158lap':
1410
+ case 'isoir158':
1411
+ case 'lap':
1412
+ case 'latinlap':
1413
+ return 'latin-lap';
1414
+
1415
+ case 'csmacintosh':
1416
+ case 'mac':
1417
+ case 'macintosh':
1418
+ return 'macintosh';
1419
+
1420
+ case 'csmicrosoftpublishing':
1421
+ case 'microsoftpublishing':
1422
+ return 'Microsoft-Publishing';
1423
+
1424
+ case 'csmnem':
1425
+ case 'mnem':
1426
+ return 'MNEM';
1427
+
1428
+ case 'csmnemonic':
1429
+ case 'mnemonic':
1430
+ return 'MNEMONIC';
1431
+
1432
+ case 'csiso86hungarian':
1433
+ case 'hu':
1434
+ case 'iso646hu':
1435
+ case 'isoir86':
1436
+ case 'msz77953':
1437
+ return 'MSZ_7795.3';
1438
+
1439
+ case 'csnatsdano':
1440
+ case 'isoir91':
1441
+ case 'natsdano':
1442
+ return 'NATS-DANO';
1443
+
1444
+ case 'csnatsdanoadd':
1445
+ case 'isoir92':
1446
+ case 'natsdanoadd':
1447
+ return 'NATS-DANO-ADD';
1448
+
1449
+ case 'csnatssefi':
1450
+ case 'isoir81':
1451
+ case 'natssefi':
1452
+ return 'NATS-SEFI';
1453
+
1454
+ case 'csnatssefiadd':
1455
+ case 'isoir82':
1456
+ case 'natssefiadd':
1457
+ return 'NATS-SEFI-ADD';
1458
+
1459
+ case 'csiso151cuba':
1460
+ case 'cuba':
1461
+ case 'iso646cu':
1462
+ case 'isoir151':
1463
+ case 'ncnc1081':
1464
+ return 'NC_NC00-10:81';
1465
+
1466
+ case 'csiso69french':
1467
+ case 'fr':
1468
+ case 'iso646fr':
1469
+ case 'isoir69':
1470
+ case 'nfz62010':
1471
+ return 'NF_Z_62-010';
1472
+
1473
+ case 'csiso25french':
1474
+ case 'iso646fr1':
1475
+ case 'isoir25':
1476
+ case 'nfz620101973':
1477
+ return 'NF_Z_62-010_(1973)';
1478
+
1479
+ case 'csiso60danishnorwegian':
1480
+ case 'csiso60norwegian1':
1481
+ case 'iso646no':
1482
+ case 'isoir60':
1483
+ case 'no':
1484
+ case 'ns45511':
1485
+ return 'NS_4551-1';
1486
+
1487
+ case 'csiso61norwegian2':
1488
+ case 'iso646no2':
1489
+ case 'isoir61':
1490
+ case 'no2':
1491
+ case 'ns45512':
1492
+ return 'NS_4551-2';
1493
+
1494
+ case 'osdebcdicdf3irv':
1495
+ return 'OSD_EBCDIC_DF03_IRV';
1496
+
1497
+ case 'osdebcdicdf41':
1498
+ return 'OSD_EBCDIC_DF04_1';
1499
+
1500
+ case 'osdebcdicdf415':
1501
+ return 'OSD_EBCDIC_DF04_15';
1502
+
1503
+ case 'cspc8danishnorwegian':
1504
+ case 'pc8danishnorwegian':
1505
+ return 'PC8-Danish-Norwegian';
1506
+
1507
+ case 'cspc8turkish':
1508
+ case 'pc8turkish':
1509
+ return 'PC8-Turkish';
1510
+
1511
+ case 'csiso16portuguese':
1512
+ case 'iso646pt':
1513
+ case 'isoir16':
1514
+ case 'pt':
1515
+ return 'PT';
1516
+
1517
+ case 'csiso84portuguese2':
1518
+ case 'iso646pt2':
1519
+ case 'isoir84':
1520
+ case 'pt2':
1521
+ return 'PT2';
1522
+
1523
+ case 'cp154':
1524
+ case 'csptcp154':
1525
+ case 'cyrillicasian':
1526
+ case 'pt154':
1527
+ case 'ptcp154':
1528
+ return 'PTCP154';
1529
+
1530
+ case 'scsu':
1531
+ return 'SCSU';
1532
+
1533
+ case 'csiso10swedish':
1534
+ case 'fi':
1535
+ case 'iso646fi':
1536
+ case 'iso646se':
1537
+ case 'isoir10':
1538
+ case 'se':
1539
+ case 'sen850200b':
1540
+ return 'SEN_850200_B';
1541
+
1542
+ case 'csiso11swedishfornames':
1543
+ case 'iso646se2':
1544
+ case 'isoir11':
1545
+ case 'se2':
1546
+ case 'sen850200c':
1547
+ return 'SEN_850200_C';
1548
+
1549
+ case 'csiso102t617bit':
1550
+ case 'isoir102':
1551
+ case 't617bit':
1552
+ return 'T.61-7bit';
1553
+
1554
+ case 'csiso103t618bit':
1555
+ case 'isoir103':
1556
+ case 't61':
1557
+ case 't618bit':
1558
+ return 'T.61-8bit';
1559
+
1560
+ case 'csiso128t101g2':
1561
+ case 'isoir128':
1562
+ case 't101g2':
1563
+ return 'T.101-G2';
1564
+
1565
+ case 'cstscii':
1566
+ case 'tscii':
1567
+ return 'TSCII';
1568
+
1569
+ case 'csunicode11':
1570
+ case 'unicode11':
1571
+ return 'UNICODE-1-1';
1572
+
1573
+ case 'csunicode11utf7':
1574
+ case 'unicode11utf7':
1575
+ return 'UNICODE-1-1-UTF-7';
1576
+
1577
+ case 'csunknown8bit':
1578
+ case 'unknown8bit':
1579
+ return 'UNKNOWN-8BIT';
1580
+
1581
+ case 'ansix341968':
1582
+ case 'ansix341986':
1583
+ case 'ascii':
1584
+ case 'cp367':
1585
+ case 'csascii':
1586
+ case 'ibm367':
1587
+ case 'iso646irv1991':
1588
+ case 'iso646us':
1589
+ case 'isoir6':
1590
+ case 'us':
1591
+ case 'usascii':
1592
+ return 'US-ASCII';
1593
+
1594
+ case 'csusdk':
1595
+ case 'usdk':
1596
+ return 'us-dk';
1597
+
1598
+ case 'utf7':
1599
+ return 'UTF-7';
1600
+
1601
+ case 'utf8':
1602
+ return 'UTF-8';
1603
+
1604
+ case 'utf16':
1605
+ return 'UTF-16';
1606
+
1607
+ case 'utf16be':
1608
+ return 'UTF-16BE';
1609
+
1610
+ case 'utf16le':
1611
+ return 'UTF-16LE';
1612
+
1613
+ case 'utf32':
1614
+ return 'UTF-32';
1615
+
1616
+ case 'utf32be':
1617
+ return 'UTF-32BE';
1618
+
1619
+ case 'utf32le':
1620
+ return 'UTF-32LE';
1621
+
1622
+ case 'csventurainternational':
1623
+ case 'venturainternational':
1624
+ return 'Ventura-International';
1625
+
1626
+ case 'csventuramath':
1627
+ case 'venturamath':
1628
+ return 'Ventura-Math';
1629
+
1630
+ case 'csventuraus':
1631
+ case 'venturaus':
1632
+ return 'Ventura-US';
1633
+
1634
+ case 'csiso70videotexsupp1':
1635
+ case 'isoir70':
1636
+ case 'videotexsuppl':
1637
+ return 'videotex-suppl';
1638
+
1639
+ case 'csviqr':
1640
+ case 'viqr':
1641
+ return 'VIQR';
1642
+
1643
+ case 'csviscii':
1644
+ case 'viscii':
1645
+ return 'VISCII';
1646
+
1647
+ case 'csshiftjis':
1648
+ case 'cswindows31j':
1649
+ case 'mskanji':
1650
+ case 'shiftjis':
1651
+ case 'windows31j':
1652
+ return 'Windows-31J';
1653
+
1654
+ case 'iso885911':
1655
+ case 'tis620':
1656
+ return 'windows-874';
1657
+
1658
+ case 'cseuckr':
1659
+ case 'csksc56011987':
1660
+ case 'euckr':
1661
+ case 'isoir149':
1662
+ case 'korean':
1663
+ case 'ksc5601':
1664
+ case 'ksc56011987':
1665
+ case 'ksc56011989':
1666
+ case 'windows949':
1667
+ return 'windows-949';
1668
+
1669
+ case 'windows1250':
1670
+ return 'windows-1250';
1671
+
1672
+ case 'windows1251':
1673
+ return 'windows-1251';
1674
+
1675
+ case 'cp819':
1676
+ case 'csisolatin1':
1677
+ case 'ibm819':
1678
+ case 'iso88591':
1679
+ case 'iso885911987':
1680
+ case 'isoir100':
1681
+ case 'l1':
1682
+ case 'latin1':
1683
+ case 'windows1252':
1684
+ return 'windows-1252';
1685
+
1686
+ case 'windows1253':
1687
+ return 'windows-1253';
1688
+
1689
+ case 'csisolatin5':
1690
+ case 'iso88599':
1691
+ case 'iso885991989':
1692
+ case 'isoir148':
1693
+ case 'l5':
1694
+ case 'latin5':
1695
+ case 'windows1254':
1696
+ return 'windows-1254';
1697
+
1698
+ case 'windows1255':
1699
+ return 'windows-1255';
1700
+
1701
+ case 'windows1256':
1702
+ return 'windows-1256';
1703
+
1704
+ case 'windows1257':
1705
+ return 'windows-1257';
1706
+
1707
+ case 'windows1258':
1708
+ return 'windows-1258';
1709
+
1710
+ default:
1711
+ return $charset;
1712
+ }
1713
+ }
1714
+
1715
+ public static function get_curl_version()
1716
+ {
1717
+ if (is_array($curl = curl_version()))
1718
+ {
1719
+ $curl = $curl['version'];
1720
+ }
1721
+ elseif (substr($curl, 0, 5) === 'curl/')
1722
+ {
1723
+ $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
1724
+ }
1725
+ elseif (substr($curl, 0, 8) === 'libcurl/')
1726
+ {
1727
+ $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
1728
+ }
1729
+ else
1730
+ {
1731
+ $curl = 0;
1732
+ }
1733
+ return $curl;
1734
+ }
1735
+
1736
+ /**
1737
+ * Strip HTML comments
1738
+ *
1739
+ * @param string $data Data to strip comments from
1740
+ * @return string Comment stripped string
1741
+ */
1742
+ public static function strip_comments($data)
1743
+ {
1744
+ $output = '';
1745
+ while (($start = strpos($data, '<!--')) !== false)
1746
+ {
1747
+ $output .= substr($data, 0, $start);
1748
+ if (($end = strpos($data, '-->', $start)) !== false)
1749
+ {
1750
+ $data = substr_replace($data, '', 0, $end + 3);
1751
+ }
1752
+ else
1753
+ {
1754
+ $data = '';
1755
+ }
1756
+ }
1757
+ return $output . $data;
1758
+ }
1759
+
1760
+ public static function parse_date($dt)
1761
+ {
1762
+ $parser = SimpleCluvPie_Parse_Date::get();
1763
+ return $parser->parse($dt);
1764
+ }
1765
+
1766
+ /**
1767
+ * Decode HTML entities
1768
+ *
1769
+ * @deprecated Use DOMDocument instead
1770
+ * @param string $data Input data
1771
+ * @return string Output data
1772
+ */
1773
+ public static function entities_decode($data)
1774
+ {
1775
+ $decoder = new SimpleCluvPie_Decode_HTML_Entities($data);
1776
+ return $decoder->parse();
1777
+ }
1778
+
1779
+ /**
1780
+ * Remove RFC822 comments
1781
+ *
1782
+ * @param string $data Data to strip comments from
1783
+ * @return string Comment stripped string
1784
+ */
1785
+ public static function uncomment_rfc822($string)
1786
+ {
1787
+ $string = (string) $string;
1788
+ $position = 0;
1789
+ $length = strlen($string);
1790
+ $depth = 0;
1791
+
1792
+ $output = '';
1793
+
1794
+ while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
1795
+ {
1796
+ $output .= substr($string, $position, $pos - $position);
1797
+ $position = $pos + 1;
1798
+ if ($string[$pos - 1] !== '\\')
1799
+ {
1800
+ $depth++;
1801
+ while ($depth && $position < $length)
1802
+ {
1803
+ $position += strcspn($string, '()', $position);
1804
+ if ($string[$position - 1] === '\\')
1805
+ {
1806
+ $position++;
1807
+ continue;
1808
+ }
1809
+ elseif (isset($string[$position]))
1810
+ {
1811
+ switch ($string[$position])
1812
+ {
1813
+ case '(':
1814
+ $depth++;
1815
+ break;
1816
+
1817
+ case ')':
1818
+ $depth--;
1819
+ break;
1820
+ }
1821
+ $position++;
1822
+ }
1823
+ else
1824
+ {
1825
+ break;
1826
+ }
1827
+ }
1828
+ }
1829
+ else
1830
+ {
1831
+ $output .= '(';
1832
+ }
1833
+ }
1834
+ $output .= substr($string, $position);
1835
+
1836
+ return $output;
1837
+ }
1838
+
1839
+ public static function parse_mime($mime)
1840
+ {
1841
+ if (($pos = strpos($mime, ';')) === false)
1842
+ {
1843
+ return trim($mime);
1844
+ }
1845
+ else
1846
+ {
1847
+ return trim(substr($mime, 0, $pos));
1848
+ }
1849
+ }
1850
+
1851
+ public static function atom_03_construct_type($attribs)
1852
+ {
1853
+ if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
1854
+ {
1855
+ $mode = SIMPLECLUVPIE_CONSTRUCT_BASE64;
1856
+ }
1857
+ else
1858
+ {
1859
+ $mode = SIMPLECLUVPIE_CONSTRUCT_NONE;
1860
+ }
1861
+ if (isset($attribs['']['type']))
1862
+ {
1863
+ switch (strtolower(trim($attribs['']['type'])))
1864
+ {
1865
+ case 'text':
1866
+ case 'text/plain':
1867
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT | $mode;
1868
+
1869
+ case 'html':
1870
+ case 'text/html':
1871
+ return SIMPLECLUVPIE_CONSTRUCT_HTML | $mode;
1872
+
1873
+ case 'xhtml':
1874
+ case 'application/xhtml+xml':
1875
+ return SIMPLECLUVPIE_CONSTRUCT_XHTML | $mode;
1876
+
1877
+ default:
1878
+ return SIMPLECLUVPIE_CONSTRUCT_NONE | $mode;
1879
+ }
1880
+ }
1881
+ else
1882
+ {
1883
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT | $mode;
1884
+ }
1885
+ }
1886
+
1887
+ public static function atom_10_construct_type($attribs)
1888
+ {
1889
+ if (isset($attribs['']['type']))
1890
+ {
1891
+ switch (strtolower(trim($attribs['']['type'])))
1892
+ {
1893
+ case 'text':
1894
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT;
1895
+
1896
+ case 'html':
1897
+ return SIMPLECLUVPIE_CONSTRUCT_HTML;
1898
+
1899
+ case 'xhtml':
1900
+ return SIMPLECLUVPIE_CONSTRUCT_XHTML;
1901
+
1902
+ default:
1903
+ return SIMPLECLUVPIE_CONSTRUCT_NONE;
1904
+ }
1905
+ }
1906
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT;
1907
+ }
1908
+
1909
+ public static function atom_10_content_construct_type($attribs)
1910
+ {
1911
+ if (isset($attribs['']['type']))
1912
+ {
1913
+ $type = strtolower(trim($attribs['']['type']));
1914
+ switch ($type)
1915
+ {
1916
+ case 'text':
1917
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT;
1918
+
1919
+ case 'html':
1920
+ return SIMPLECLUVPIE_CONSTRUCT_HTML;
1921
+
1922
+ case 'xhtml':
1923
+ return SIMPLECLUVPIE_CONSTRUCT_XHTML;
1924
+ }
1925
+ if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
1926
+ {
1927
+ return SIMPLECLUVPIE_CONSTRUCT_NONE;
1928
+ }
1929
+ else
1930
+ {
1931
+ return SIMPLECLUVPIE_CONSTRUCT_BASE64;
1932
+ }
1933
+ }
1934
+ else
1935
+ {
1936
+ return SIMPLECLUVPIE_CONSTRUCT_TEXT;
1937
+ }
1938
+ }
1939
+
1940
+ public static function is_isegment_nz_nc($string)
1941
+ {
1942
+ 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);
1943
+ }
1944
+
1945
+ public static function space_seperated_tokens($string)
1946
+ {
1947
+ $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
1948
+ $string_length = strlen($string);
1949
+
1950
+ $position = strspn($string, $space_characters);
1951
+ $tokens = array();
1952
+
1953
+ while ($position < $string_length)
1954
+ {
1955
+ $len = strcspn($string, $space_characters, $position);
1956
+ $tokens[] = substr($string, $position, $len);
1957
+ $position += $len;
1958
+ $position += strspn($string, $space_characters, $position);
1959
+ }
1960
+
1961
+ return $tokens;
1962
+ }
1963
+
1964
+ /**
1965
+ * Converts a unicode codepoint to a UTF-8 character
1966
+ *
1967
+ * @static
1968
+ * @param int $codepoint Unicode codepoint
1969
+ * @return string UTF-8 character
1970
+ */
1971
+ public static function codepoint_to_utf8($codepoint)
1972
+ {
1973
+ $codepoint = (int) $codepoint;
1974
+ if ($codepoint < 0)
1975
+ {
1976
+ return false;
1977
+ }
1978
+ else if ($codepoint <= 0x7f)
1979
+ {
1980
+ return chr($codepoint);
1981
+ }
1982
+ else if ($codepoint <= 0x7ff)
1983
+ {
1984
+ return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
1985
+ }
1986
+ else if ($codepoint <= 0xffff)
1987
+ {
1988
+ return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
1989
+ }
1990
+ else if ($codepoint <= 0x10ffff)
1991
+ {
1992
+ return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
1993
+ }
1994
+ else
1995
+ {
1996
+ // U+FFFD REPLACEMENT CHARACTER
1997
+ return "\xEF\xBF\xBD";
1998
+ }
1999
+ }
2000
+
2001
+ /**
2002
+ * Similar to parse_str()
2003
+ *
2004
+ * Returns an associative array of name/value pairs, where the value is an
2005
+ * array of values that have used the same name
2006
+ *
2007
+ * @static
2008
+ * @param string $str The input string.
2009
+ * @return array
2010
+ */
2011
+ public static function parse_str($str)
2012
+ {
2013
+ $return = array();
2014
+ $str = explode('&', $str);
2015
+
2016
+ foreach ($str as $section)
2017
+ {
2018
+ if (strpos($section, '=') !== false)
2019
+ {
2020
+ list($name, $value) = explode('=', $section, 2);
2021
+ $return[urldecode($name)][] = urldecode($value);
2022
+ }
2023
+ else
2024
+ {
2025
+ $return[urldecode($section)][] = null;
2026
+ }
2027
+ }
2028
+
2029
+ return $return;
2030
+ }
2031
+
2032
+ /**
2033
+ * Detect XML encoding, as per XML 1.0 Appendix F.1
2034
+ *
2035
+ * @todo Add support for EBCDIC
2036
+ * @param string $data XML data
2037
+ * @param SimpleCluvPie_Registry $registry Class registry
2038
+ * @return array Possible encodings
2039
+ */
2040
+ public static function xml_encoding($data, $registry)
2041
+ {
2042
+ // UTF-32 Big Endian BOM
2043
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
2044
+ {
2045
+ $encoding[] = 'UTF-32BE';
2046
+ }
2047
+ // UTF-32 Little Endian BOM
2048
+ elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
2049
+ {
2050
+ $encoding[] = 'UTF-32LE';
2051
+ }
2052
+ // UTF-16 Big Endian BOM
2053
+ elseif (substr($data, 0, 2) === "\xFE\xFF")
2054
+ {
2055
+ $encoding[] = 'UTF-16BE';
2056
+ }
2057
+ // UTF-16 Little Endian BOM
2058
+ elseif (substr($data, 0, 2) === "\xFF\xFE")
2059
+ {
2060
+ $encoding[] = 'UTF-16LE';
2061
+ }
2062
+ // UTF-8 BOM
2063
+ elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
2064
+ {
2065
+ $encoding[] = 'UTF-8';
2066
+ }
2067
+ // UTF-32 Big Endian Without BOM
2068
+ 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")
2069
+ {
2070
+ if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
2071
+ {
2072
+ $parser = $registry->create('XML_Declaration_Parser', array(SimpleCluvPie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8')));
2073
+ if ($parser->parse())
2074
+ {
2075
+ $encoding[] = $parser->encoding;
2076
+ }
2077
+ }
2078
+ $encoding[] = 'UTF-32BE';
2079
+ }
2080
+ // UTF-32 Little Endian Without BOM
2081
+ 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")
2082
+ {
2083
+ if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
2084
+ {
2085
+ $parser = $registry->create('XML_Declaration_Parser', array(SimpleCluvPie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8')));
2086
+ if ($parser->parse())
2087
+ {
2088
+ $encoding[] = $parser->encoding;
2089
+ }
2090
+ }
2091
+ $encoding[] = 'UTF-32LE';
2092
+ }
2093
+ // UTF-16 Big Endian Without BOM
2094
+ elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
2095
+ {
2096
+ if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
2097
+ {
2098
+ $parser = $registry->create('XML_Declaration_Parser', array(SimpleCluvPie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8')));
2099
+ if ($parser->parse())
2100
+ {
2101
+ $encoding[] = $parser->encoding;
2102
+ }
2103
+ }
2104
+ $encoding[] = 'UTF-16BE';
2105
+ }
2106
+ // UTF-16 Little Endian Without BOM
2107
+ elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
2108
+ {
2109
+ if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
2110
+ {
2111
+ $parser = $registry->create('XML_Declaration_Parser', array(SimpleCluvPie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8')));
2112
+ if ($parser->parse())
2113
+ {
2114
+ $encoding[] = $parser->encoding;
2115
+ }
2116
+ }
2117
+ $encoding[] = 'UTF-16LE';
2118
+ }
2119
+ // US-ASCII (or superset)
2120
+ elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
2121
+ {
2122
+ if ($pos = strpos($data, "\x3F\x3E"))
2123
+ {
2124
+ $parser = $registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
2125
+ if ($parser->parse())
2126
+ {
2127
+ $encoding[] = $parser->encoding;
2128
+ }
2129
+ }
2130
+ $encoding[] = 'UTF-8';
2131
+ }
2132
+ // Fallback to UTF-8
2133
+ else
2134
+ {
2135
+ $encoding[] = 'UTF-8';
2136
+ }
2137
+ return $encoding;
2138
+ }
2139
+
2140
+ public static function output_javascript()
2141
+ {
2142
+ if (function_exists('ob_gzhandler'))
2143
+ {
2144
+ ob_start('ob_gzhandler');
2145
+ }
2146
+ header('Content-type: text/javascript; charset: UTF-8');
2147
+ header('Cache-Control: must-revalidate');
2148
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
2149
+ ?>
2150
+ function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
2151
+ if (placeholder != '') {
2152
+ 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>');
2153
+ }
2154
+ else {
2155
+ 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>');
2156
+ }
2157
+ }
2158
+
2159
+ function embed_flash(bgcolor, width, height, link, loop, type) {
2160
+ 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>');
2161
+ }
2162
+
2163
+ function embed_flv(width, height, link, placeholder, loop, player) {
2164
+ 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>');
2165
+ }
2166
+
2167
+ function embed_wmedia(width, height, link) {
2168
+ document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
2169
+ }
2170
+ <?php
2171
+ }
2172
+
2173
+ /**
2174
+ * Get the SimpleCluvPie build timestamp
2175
+ *
2176
+ * Uses the git index if it exists, otherwise uses the modification time
2177
+ * of the newest file.
2178
+ */
2179
+ public static function get_build()
2180
+ {
2181
+ $root = dirname(dirname(__FILE__));
2182
+ if (file_exists($root . '/.git/index'))
2183
+ {
2184
+ return filemtime($root . '/.git/index');
2185
+ }
2186
+ elseif (file_exists($root . '/SimpleCluvPie'))
2187
+ {
2188
+ $time = 0;
2189
+ foreach (glob($root . '/SimpleCluvPie/*.php') as $file)
2190
+ {
2191
+ if (($mtime = filemtime($file)) > $time)
2192
+ {
2193
+ $time = $mtime;
2194
+ }
2195
+ }
2196
+ return $time;
2197
+ }
2198
+ elseif (file_exists(dirname(__FILE__) . '/Core.php'))
2199
+ {
2200
+ return filemtime(dirname(__FILE__) . '/Core.php');
2201
+ }
2202
+ else
2203
+ {
2204
+ return filemtime(__FILE__);
2205
+ }
2206
+ }
2207
+
2208
+ /**
2209
+ * Format debugging information
2210
+ */
2211
+ public static function debug(&$sp)
2212
+ {
2213
+ $info = 'SimpleCluvPie ' . SIMPLECLUVPIE_VERSION . ' Build ' . SIMPLECLUVPIE_BUILD . "\n";
2214
+ $info .= 'PHP ' . PHP_VERSION . "\n";
2215
+ if ($sp->error() !== null)
2216
+ {
2217
+ $info .= 'Error occurred: ' . $sp->error() . "\n";
2218
+ }
2219
+ else
2220
+ {
2221
+ $info .= "No error found.\n";
2222
+ }
2223
+ $info .= "Extensions:\n";
2224
+ $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
2225
+ foreach ($extensions as $ext)
2226
+ {
2227
+ if (extension_loaded($ext))
2228
+ {
2229
+ $info .= " $ext loaded\n";
2230
+ switch ($ext)
2231
+ {
2232
+ case 'pcre':
2233
+ $info .= ' Version ' . PCRE_VERSION . "\n";
2234
+ break;
2235
+ case 'curl':
2236
+ $version = curl_version();
2237
+ $info .= ' Version ' . $version['version'] . "\n";
2238
+ break;
2239
+ case 'mbstring':
2240
+ $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
2241
+ break;
2242
+ case 'iconv':
2243
+ $info .= ' Version ' . ICONV_VERSION . "\n";
2244
+ break;
2245
+ case 'xml':
2246
+ $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
2247
+ break;
2248
+ }
2249
+ }
2250
+ else
2251
+ {
2252
+ $info .= " $ext not loaded\n";
2253
+ }
2254
+ }
2255
+ return $info;
2256
+ }
2257
+
2258
+ public static function silence_errors($num, $str)
2259
+ {
2260
+ // No-op
2261
+ }
2262
+ }
2263
+
libs/SimpleCluvPie/library/SimpleCluvPie/Net/IPv6.php ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Class to validate and to work with IPv6 addresses.
47
+ *
48
+ * @package SimpleCluvPie
49
+ * @subpackage HTTP
50
+ * @copyright 2003-2005 The PHP Group
51
+ * @license http://www.opensource.org/licenses/bsd-license.php
52
+ * @link http://pear.php.net/package/Net_IPv6
53
+ * @author Alexander Merz <alexander.merz@web.de>
54
+ * @author elfrink at introweb dot nl
55
+ * @author Josh Peck <jmp at joshpeck dot org>
56
+ * @author Geoffrey Sneddon <geoffers@gmail.com>
57
+ */
58
+ class SimpleCluvPie_Net_IPv6
59
+ {
60
+ /**
61
+ * Uncompresses an IPv6 address
62
+ *
63
+ * RFC 4291 allows you to compress concecutive zero pieces in an address to
64
+ * '::'. This method expects a valid IPv6 address and expands the '::' to
65
+ * the required number of zero pieces.
66
+ *
67
+ * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
68
+ * ::1 -> 0:0:0:0:0:0:0:1
69
+ *
70
+ * @author Alexander Merz <alexander.merz@web.de>
71
+ * @author elfrink at introweb dot nl
72
+ * @author Josh Peck <jmp at joshpeck dot org>
73
+ * @copyright 2003-2005 The PHP Group
74
+ * @license http://www.opensource.org/licenses/bsd-license.php
75
+ * @param string $ip An IPv6 address
76
+ * @return string The uncompressed IPv6 address
77
+ */
78
+ public static function uncompress($ip)
79
+ {
80
+ $c1 = -1;
81
+ $c2 = -1;
82
+ if (substr_count($ip, '::') === 1)
83
+ {
84
+ list($ip1, $ip2) = explode('::', $ip);
85
+ if ($ip1 === '')
86
+ {
87
+ $c1 = -1;
88
+ }
89
+ else
90
+ {
91
+ $c1 = substr_count($ip1, ':');
92
+ }
93
+ if ($ip2 === '')
94
+ {
95
+ $c2 = -1;
96
+ }
97
+ else
98
+ {
99
+ $c2 = substr_count($ip2, ':');
100
+ }
101
+ if (strpos($ip2, '.') !== false)
102
+ {
103
+ $c2++;
104
+ }
105
+ // ::
106
+ if ($c1 === -1 && $c2 === -1)
107
+ {
108
+ $ip = '0:0:0:0:0:0:0:0';
109
+ }
110
+ // ::xxx
111
+ else if ($c1 === -1)
112
+ {
113
+ $fill = str_repeat('0:', 7 - $c2);
114
+ $ip = str_replace('::', $fill, $ip);
115
+ }
116
+ // xxx::
117
+ else if ($c2 === -1)
118
+ {
119
+ $fill = str_repeat(':0', 7 - $c1);
120
+ $ip = str_replace('::', $fill, $ip);
121
+ }
122
+ // xxx::xxx
123
+ else
124
+ {
125
+ $fill = ':' . str_repeat('0:', 6 - $c2 - $c1);
126
+ $ip = str_replace('::', $fill, $ip);
127
+ }
128
+ }
129
+ return $ip;
130
+ }
131
+
132
+ /**
133
+ * Compresses an IPv6 address
134
+ *
135
+ * RFC 4291 allows you to compress concecutive zero pieces in an address to
136
+ * '::'. This method expects a valid IPv6 address and compresses consecutive
137
+ * zero pieces to '::'.
138
+ *
139
+ * Example: FF01:0:0:0:0:0:0:101 -> FF01::101
140
+ * 0:0:0:0:0:0:0:1 -> ::1
141
+ *
142
+ * @see uncompress()
143
+ * @param string $ip An IPv6 address
144
+ * @return string The compressed IPv6 address
145
+ */
146
+ public static function compress($ip)
147
+ {
148
+ // Prepare the IP to be compressed
149
+ $ip = self::uncompress($ip);
150
+ $ip_parts = self::split_v6_v4($ip);
151
+
152
+ // Replace all leading zeros
153
+ $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]);
154
+
155
+ // Find bunches of zeros
156
+ if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE))
157
+ {
158
+ $max = 0;
159
+ $pos = null;
160
+ foreach ($matches[0] as $match)
161
+ {
162
+ if (strlen($match[0]) > $max)
163
+ {
164
+ $max = strlen($match[0]);
165
+ $pos = $match[1];
166
+ }
167
+ }
168
+
169
+ $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max);
170
+ }
171
+
172
+ if ($ip_parts[1] !== '')
173
+ {
174
+ return implode(':', $ip_parts);
175
+ }
176
+ else
177
+ {
178
+ return $ip_parts[0];
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Splits an IPv6 address into the IPv6 and IPv4 representation parts
184
+ *
185
+ * RFC 4291 allows you to represent the last two parts of an IPv6 address
186
+ * using the standard IPv4 representation
187
+ *
188
+ * Example: 0:0:0:0:0:0:13.1.68.3
189
+ * 0:0:0:0:0:FFFF:129.144.52.38
190
+ *
191
+ * @param string $ip An IPv6 address
192
+ * @return array [0] contains the IPv6 represented part, and [1] the IPv4 represented part
193
+ */
194
+ private static function split_v6_v4($ip)
195
+ {
196
+ if (strpos($ip, '.') !== false)
197
+ {
198
+ $pos = strrpos($ip, ':');
199
+ $ipv6_part = substr($ip, 0, $pos);
200
+ $ipv4_part = substr($ip, $pos + 1);
201
+ return array($ipv6_part, $ipv4_part);
202
+ }
203
+ else
204
+ {
205
+ return array($ip, '');
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Checks an IPv6 address
211
+ *
212
+ * Checks if the given IP is a valid IPv6 address
213
+ *
214
+ * @param string $ip An IPv6 address
215
+ * @return bool true if $ip is a valid IPv6 address
216
+ */
217
+ public static function check_ipv6($ip)
218
+ {
219
+ $ip = self::uncompress($ip);
220
+ list($ipv6, $ipv4) = self::split_v6_v4($ip);
221
+ $ipv6 = explode(':', $ipv6);
222
+ $ipv4 = explode('.', $ipv4);
223
+ if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4)
224
+ {
225
+ foreach ($ipv6 as $ipv6_part)
226
+ {
227
+ // The section can't be empty
228
+ if ($ipv6_part === '')
229
+ return false;
230
+
231
+ // Nor can it be over four characters
232
+ if (strlen($ipv6_part) > 4)
233
+ return false;
234
+
235
+ // Remove leading zeros (this is safe because of the above)
236
+ $ipv6_part = ltrim($ipv6_part, '0');
237
+ if ($ipv6_part === '')
238
+ $ipv6_part = '0';
239
+
240
+ // Check the value is valid
241
+ $value = hexdec($ipv6_part);
242
+ if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF)
243
+ return false;
244
+ }
245
+ if (count($ipv4) === 4)
246
+ {
247
+ foreach ($ipv4 as $ipv4_part)
248
+ {
249
+ $value = (int) $ipv4_part;
250
+ if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF)
251
+ return false;
252
+ }
253
+ }
254
+ return true;
255
+ }
256
+ else
257
+ {
258
+ return false;
259
+ }
260
+ }
261
+
262
+ /**
263
+ * Checks if the given IP is a valid IPv6 address
264
+ *
265
+ * @codeCoverageIgnore
266
+ * @deprecated Use {@see SimpleCluvPie_Net_IPv6::check_ipv6()} instead
267
+ * @see check_ipv6
268
+ * @param string $ip An IPv6 address
269
+ * @return bool true if $ip is a valid IPv6 address
270
+ */
271
+ public static function checkIPv6($ip)
272
+ {
273
+ return self::check_ipv6($ip);
274
+ }
275
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Parse/Date.php ADDED
@@ -0,0 +1,983 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Date Parser
47
+ *
48
+ * @package SimpleCluvPie
49
+ * @subpackage Parsing
50
+ */
51
+ class SimpleCluvPie_Parse_Date
52
+ {
53
+ /**
54
+ * Input data
55
+ *
56
+ * @access protected
57
+ * @var string
58
+ */
59
+ var $date;
60
+
61
+ /**
62
+ * List of days, calendar day name => ordinal day number in the week
63
+ *
64
+ * @access protected
65
+ * @var array
66
+ */
67
+ var $day = array(
68
+ // English
69
+ 'mon' => 1,
70
+ 'monday' => 1,
71
+ 'tue' => 2,
72
+ 'tuesday' => 2,
73
+ 'wed' => 3,
74
+ 'wednesday' => 3,
75
+ 'thu' => 4,
76
+ 'thursday' => 4,
77
+ 'fri' => 5,
78
+ 'friday' => 5,
79
+ 'sat' => 6,
80
+ 'saturday' => 6,
81
+ 'sun' => 7,
82
+ 'sunday' => 7,
83
+ // Dutch
84
+ 'maandag' => 1,
85
+ 'dinsdag' => 2,
86
+ 'woensdag' => 3,
87
+ 'donderdag' => 4,
88
+ 'vrijdag' => 5,
89
+ 'zaterdag' => 6,
90
+ 'zondag' => 7,
91
+ // French
92
+ 'lundi' => 1,
93
+ 'mardi' => 2,
94
+ 'mercredi' => 3,
95
+ 'jeudi' => 4,
96
+ 'vendredi' => 5,
97
+ 'samedi' => 6,
98
+ 'dimanche' => 7,
99
+ // German
100
+ 'montag' => 1,
101
+ 'dienstag' => 2,
102
+ 'mittwoch' => 3,
103
+ 'donnerstag' => 4,
104
+ 'freitag' => 5,
105
+ 'samstag' => 6,
106
+ 'sonnabend' => 6,
107
+ 'sonntag' => 7,
108
+ // Italian
109
+ 'lunedì' => 1,
110
+ 'martedì' => 2,
111
+ 'mercoledì' => 3,
112
+ 'giovedì' => 4,
113
+ 'venerdì' => 5,
114
+ 'sabato' => 6,
115
+ 'domenica' => 7,
116
+ // Spanish
117
+ 'lunes' => 1,
118
+ 'martes' => 2,
119
+ 'miércoles' => 3,
120
+ 'jueves' => 4,
121
+ 'viernes' => 5,
122
+ 'sábado' => 6,
123
+ 'domingo' => 7,
124
+ // Finnish
125
+ 'maanantai' => 1,
126
+ 'tiistai' => 2,
127
+ 'keskiviikko' => 3,
128
+ 'torstai' => 4,
129
+ 'perjantai' => 5,
130
+ 'lauantai' => 6,
131
+ 'sunnuntai' => 7,
132
+ // Hungarian
133
+ 'hétfő' => 1,
134
+ 'kedd' => 2,
135
+ 'szerda' => 3,
136
+ 'csütörtok' => 4,
137
+ 'péntek' => 5,
138
+ 'szombat' => 6,
139
+ 'vasárnap' => 7,
140
+ // Greek
141
+ 'Δευ' => 1,
142
+ 'Τρι' => 2,
143
+ 'Τετ' => 3,
144
+ 'Πεμ' => 4,
145
+ 'Παρ' => 5,
146
+ 'Σαβ' => 6,
147
+ 'Κυρ' => 7,
148
+ );
149
+
150
+ /**
151
+ * List of months, calendar month name => calendar month number
152
+ *
153
+ * @access protected
154
+ * @var array
155
+ */
156
+ var $month = array(
157
+ // English
158
+ 'jan' => 1,
159
+ 'january' => 1,
160
+ 'feb' => 2,
161
+ 'february' => 2,
162
+ 'mar' => 3,
163
+ 'march' => 3,
164
+ 'apr' => 4,
165
+ 'april' => 4,
166
+ 'may' => 5,
167
+ // No long form of May
168
+ 'jun' => 6,
169
+ 'june' => 6,
170
+ 'jul' => 7,
171
+ 'july' => 7,
172
+ 'aug' => 8,
173
+ 'august' => 8,
174
+ 'sep' => 9,
175
+ 'september' => 9,
176
+ 'oct' => 10,
177
+ 'october' => 10,
178
+ 'nov' => 11,
179
+ 'november' => 11,
180
+ 'dec' => 12,
181
+ 'december' => 12,
182
+ // Dutch
183
+ 'januari' => 1,
184
+ 'februari' => 2,
185
+ 'maart' => 3,
186
+ 'april' => 4,
187
+ 'mei' => 5,
188
+ 'juni' => 6,
189
+ 'juli' => 7,
190
+ 'augustus' => 8,
191
+ 'september' => 9,
192
+ 'oktober' => 10,
193
+ 'november' => 11,
194
+ 'december' => 12,
195
+ // French
196
+ 'janvier' => 1,
197
+ 'février' => 2,
198
+ 'mars' => 3,
199
+ 'avril' => 4,
200
+ 'mai' => 5,
201
+ 'juin' => 6,
202
+ 'juillet' => 7,
203
+ 'août' => 8,
204
+ 'septembre' => 9,
205
+ 'octobre' => 10,
206
+ 'novembre' => 11,
207
+ 'décembre' => 12,
208
+ // German
209
+ 'januar' => 1,
210
+ 'februar' => 2,
211
+ 'märz' => 3,
212
+ 'april' => 4,
213
+ 'mai' => 5,
214
+ 'juni' => 6,
215
+ 'juli' => 7,
216
+ 'august' => 8,
217
+ 'september' => 9,
218
+ 'oktober' => 10,
219
+ 'november' => 11,
220
+ 'dezember' => 12,
221
+ // Italian
222
+ 'gennaio' => 1,
223
+ 'febbraio' => 2,
224
+ 'marzo' => 3,
225
+ 'aprile' => 4,
226
+ 'maggio' => 5,
227
+ 'giugno' => 6,
228
+ 'luglio' => 7,
229
+ 'agosto' => 8,
230
+ 'settembre' => 9,
231
+ 'ottobre' => 10,
232
+ 'novembre' => 11,
233
+ 'dicembre' => 12,
234
+ // Spanish
235
+ 'enero' => 1,
236
+ 'febrero' => 2,
237
+ 'marzo' => 3,
238
+ 'abril' => 4,
239
+ 'mayo' => 5,
240
+ 'junio' => 6,
241
+ 'julio' => 7,
242
+ 'agosto' => 8,
243
+ 'septiembre' => 9,
244
+ 'setiembre' => 9,
245
+ 'octubre' => 10,
246
+ 'noviembre' => 11,
247
+ 'diciembre' => 12,
248
+ // Finnish
249
+ 'tammikuu' => 1,
250
+ 'helmikuu' => 2,
251
+ 'maaliskuu' => 3,
252
+ 'huhtikuu' => 4,
253
+ 'toukokuu' => 5,
254
+ 'kesäkuu' => 6,
255
+ 'heinäkuu' => 7,
256
+ 'elokuu' => 8,
257
+ 'suuskuu' => 9,
258
+ 'lokakuu' => 10,
259
+ 'marras' => 11,
260
+ 'joulukuu' => 12,
261
+ // Hungarian
262
+ 'január' => 1,
263
+ 'február' => 2,
264
+ 'március' => 3,
265
+ 'április' => 4,
266
+ 'május' => 5,
267
+ 'június' => 6,
268
+ 'július' => 7,
269
+ 'augusztus' => 8,
270
+ 'szeptember' => 9,
271
+ 'október' => 10,
272
+ 'november' => 11,
273
+ 'december' => 12,
274
+ // Greek
275
+ 'Ιαν' => 1,
276
+ 'Φεβ' => 2,
277
+ 'Μάώ' => 3,
278
+ 'Μαώ' => 3,
279
+ 'Απρ' => 4,
280
+ 'Μάι' => 5,
281
+ 'Μαϊ' => 5,
282
+ 'Μαι' => 5,
283
+ 'Ιούν' => 6,
284
+ 'Ιον' => 6,
285
+ 'Ιούλ' => 7,
286
+ 'Ιολ' => 7,
287
+ 'Αύγ' => 8,
288
+ 'Αυγ' => 8,
289
+ 'Σεπ' => 9,
290
+ 'Οκτ' => 10,
291
+ 'Νοέ' => 11,
292
+ 'Δεκ' => 12,
293
+ );
294
+
295
+ /**
296
+ * List of timezones, abbreviation => offset from UTC
297
+ *
298
+ * @access protected
299
+ * @var array
300
+ */
301
+ var $timezone = array(
302
+ 'ACDT' => 37800,
303
+ 'ACIT' => 28800,
304
+ 'ACST' => 34200,
305
+ 'ACT' => -18000,
306
+ 'ACWDT' => 35100,
307
+ 'ACWST' => 31500,
308
+ 'AEDT' => 39600,
309
+ 'AEST' => 36000,
310
+ 'AFT' => 16200,
311
+ 'AKDT' => -28800,
312
+ 'AKST' => -32400,
313
+ 'AMDT' => 18000,
314
+ 'AMT' => -14400,
315
+ 'ANAST' => 46800,
316
+ 'ANAT' => 43200,
317
+ 'ART' => -10800,
318
+ 'AZOST' => -3600,
319
+ 'AZST' => 18000,
320
+ 'AZT' => 14400,
321
+ 'BIOT' => 21600,
322
+ 'BIT' => -43200,
323
+ 'BOT' => -14400,
324
+ 'BRST' => -7200,
325
+ 'BRT' => -10800,
326
+ 'BST' => 3600,
327
+ 'BTT' => 21600,
328
+ 'CAST' => 18000,
329
+ 'CAT' => 7200,
330
+ 'CCT' => 23400,
331
+ 'CDT' => -18000,
332
+ 'CEDT' => 7200,
333
+ 'CEST' => 7200,
334
+ 'CET' => 3600,
335
+ 'CGST' => -7200,
336
+ 'CGT' => -10800,
337
+ 'CHADT' => 49500,
338
+ 'CHAST' => 45900,
339
+ 'CIST' => -28800,
340
+ 'CKT' => -36000,
341
+ 'CLDT' => -10800,
342
+ 'CLST' => -14400,
343
+ 'COT' => -18000,
344
+ 'CST' => -21600,
345
+ 'CVT' => -3600,
346
+ 'CXT' => 25200,
347
+ 'DAVT' => 25200,
348
+ 'DTAT' => 36000,
349
+ 'EADT' => -18000,
350
+ 'EAST' => -21600,
351
+ 'EAT' => 10800,
352
+ 'ECT' => -18000,
353
+ 'EDT' => -14400,
354
+ 'EEST' => 10800,
355
+ 'EET' => 7200,
356
+ 'EGT' => -3600,
357
+ 'EKST' => 21600,
358
+ 'EST' => -18000,
359
+ 'FJT' => 43200,
360
+ 'FKDT' => -10800,
361
+ 'FKST' => -14400,
362
+ 'FNT' => -7200,
363
+ 'GALT' => -21600,
364
+ 'GEDT' => 14400,
365
+ 'GEST' => 10800,
366
+ 'GFT' => -10800,
367
+ 'GILT' => 43200,
368
+ 'GIT' => -32400,
369
+ 'GST' => 14400,
370
+ 'GST' => -7200,
371
+ 'GYT' => -14400,
372
+ 'HAA' => -10800,
373
+ 'HAC' => -18000,
374
+ 'HADT' => -32400,
375
+ 'HAE' => -14400,
376
+ 'HAP' => -25200,
377
+ 'HAR' => -21600,
378
+ 'HAST' => -36000,
379
+ 'HAT' => -9000,
380
+ 'HAY' => -28800,
381
+ 'HKST' => 28800,
382
+ 'HMT' => 18000,
383
+ 'HNA' => -14400,
384
+ 'HNC' => -21600,
385
+ 'HNE' => -18000,
386
+ 'HNP' => -28800,
387
+ 'HNR' => -25200,
388
+ 'HNT' => -12600,
389
+ 'HNY' => -32400,
390
+ 'IRDT' => 16200,
391
+ 'IRKST' => 32400,
392
+ 'IRKT' => 28800,
393
+ 'IRST' => 12600,
394
+ 'JFDT' => -10800,
395
+ 'JFST' => -14400,
396
+ 'JST' => 32400,
397
+ 'KGST' => 21600,
398
+ 'KGT' => 18000,
399
+ 'KOST' => 39600,
400
+ 'KOVST' => 28800,
401
+ 'KOVT' => 25200,
402
+ 'KRAST' => 28800,
403
+ 'KRAT' => 25200,
404
+ 'KST' => 32400,
405
+ 'LHDT' => 39600,
406
+ 'LHST' => 37800,
407
+ 'LINT' => 50400,
408
+ 'LKT' => 21600,
409
+ 'MAGST' => 43200,
410
+ 'MAGT' => 39600,
411
+ 'MAWT' => 21600,
412
+ 'MDT' => -21600,
413
+ 'MESZ' => 7200,
414
+ 'MEZ' => 3600,
415
+ 'MHT' => 43200,
416
+ 'MIT' => -34200,
417
+ 'MNST' => 32400,
418
+ 'MSDT' => 14400,
419
+ 'MSST' => 10800,
420
+ 'MST' => -25200,
421
+ 'MUT' => 14400,
422
+ 'MVT' => 18000,
423
+ 'MYT' => 28800,
424
+ 'NCT' => 39600,
425
+ 'NDT' => -9000,
426
+ 'NFT' => 41400,
427
+ 'NMIT' => 36000,
428
+ 'NOVST' => 25200,
429
+ 'NOVT' => 21600,
430
+ 'NPT' => 20700,
431
+ 'NRT' => 43200,
432
+ 'NST' => -12600,
433
+ 'NUT' => -39600,
434
+ 'NZDT' => 46800,
435
+ 'NZST' => 43200,
436
+ 'OMSST' => 25200,
437
+ 'OMST' => 21600,
438
+ 'PDT' => -25200,
439
+ 'PET' => -18000,
440
+ 'PETST' => 46800,
441
+ 'PETT' => 43200,
442
+ 'PGT' => 36000,
443
+ 'PHOT' => 46800,
444
+ 'PHT' => 28800,
445
+ 'PKT' => 18000,
446
+ 'PMDT' => -7200,
447
+ 'PMST' => -10800,
448
+ 'PONT' => 39600,
449
+ 'PST' => -28800,
450
+ 'PWT' => 32400,
451
+ 'PYST' => -10800,
452
+ 'PYT' => -14400,
453
+ 'RET' => 14400,
454
+ 'ROTT' => -10800,
455
+ 'SAMST' => 18000,
456
+ 'SAMT' => 14400,
457
+ 'SAST' => 7200,
458
+ 'SBT' => 39600,
459
+ 'SCDT' => 46800,
460
+ 'SCST' => 43200,
461
+ 'SCT' => 14400,
462
+ 'SEST' => 3600,
463
+ 'SGT' => 28800,
464
+ 'SIT' => 28800,
465
+ 'SRT' => -10800,
466
+ 'SST' => -39600,
467
+ 'SYST' => 10800,
468
+ 'SYT' => 7200,
469
+ 'TFT' => 18000,
470
+ 'THAT' => -36000,
471
+ 'TJT' => 18000,
472
+ 'TKT' => -36000,
473
+ 'TMT' => 18000,
474
+ 'TOT' => 46800,
475
+ 'TPT' => 32400,
476
+ 'TRUT' => 36000,
477
+ 'TVT' => 43200,
478
+ 'TWT' => 28800,
479
+ 'UYST' => -7200,
480
+ 'UYT' => -10800,
481
+ 'UZT' => 18000,
482
+ 'VET' => -14400,
483
+ 'VLAST' => 39600,
484
+ 'VLAT' => 36000,
485
+ 'VOST' => 21600,
486
+ 'VUT' => 39600,
487
+ 'WAST' => 7200,
488
+ 'WAT' => 3600,
489
+ 'WDT' => 32400,
490
+ 'WEST' => 3600,
491
+ 'WFT' => 43200,
492
+ 'WIB' => 25200,
493
+ 'WIT' => 32400,
494
+ 'WITA' => 28800,
495
+ 'WKST' => 18000,
496
+ 'WST' => 28800,
497
+ 'YAKST' => 36000,
498
+ 'YAKT' => 32400,
499
+ 'YAPT' => 36000,
500
+ 'YEKST' => 21600,
501
+ 'YEKT' => 18000,
502
+ );
503
+
504
+ /**
505
+ * Cached PCRE for SimpleCluvPie_Parse_Date::$day
506
+ *
507
+ * @access protected
508
+ * @var string
509
+ */
510
+ var $day_pcre;
511
+
512
+ /**
513
+ * Cached PCRE for SimpleCluvPie_Parse_Date::$month
514
+ *
515
+ * @access protected
516
+ * @var string
517
+ */
518
+ var $month_pcre;
519
+
520
+ /**
521
+ * Array of user-added callback methods
522
+ *
523
+ * @access private
524
+ * @var array
525
+ */
526
+ var $built_in = array();
527
+
528
+ /**
529
+ * Array of user-added callback methods
530
+ *
531
+ * @access private
532
+ * @var array
533
+ */
534
+ var $user = array();
535
+
536
+ /**
537
+ * Create new SimpleCluvPie_Parse_Date object, and set self::day_pcre,
538
+ * self::month_pcre, and self::built_in
539
+ *
540
+ * @access private
541
+ */
542
+ public function __construct()
543
+ {
544
+ $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
545
+ $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
546
+
547
+ static $cache;
548
+ if (!isset($cache[get_class($this)]))
549
+ {
550
+ $all_methods = get_class_methods($this);
551
+
552
+ foreach ($all_methods as $method)
553
+ {
554
+ if (strtolower(substr($method, 0, 5)) === 'date_')
555
+ {
556
+ $cache[get_class($this)][] = $method;
557
+ }
558
+ }
559
+ }
560
+
561
+ foreach ($cache[get_class($this)] as $method)
562
+ {
563
+ $this->built_in[] = $method;
564
+ }
565
+ }
566
+
567
+ /**
568
+ * Get the object
569
+ *
570
+ * @access public
571
+ */
572
+ public static function get()
573
+ {
574
+ static $object;
575
+ if (!$object)
576
+ {
577
+ $object = new SimpleCluvPie_Parse_Date;
578
+ }
579
+ return $object;
580
+ }
581
+
582
+ /**
583
+ * Parse a date
584
+ *
585
+ * @final
586
+ * @access public
587
+ * @param string $date Date to parse
588
+ * @return int Timestamp corresponding to date string, or false on failure
589
+ */
590
+ public function parse($date)
591
+ {
592
+ foreach ($this->user as $method)
593
+ {
594
+ if (($returned = call_user_func($method, $date)) !== false)
595
+ {
596
+ return $returned;
597
+ }
598
+ }
599
+
600
+ foreach ($this->built_in as $method)
601
+ {
602
+ if (($returned = call_user_func(array($this, $method), $date)) !== false)
603
+ {
604
+ return $returned;
605
+ }
606
+ }
607
+
608
+ return false;
609
+ }
610
+
611
+ /**
612
+ * Add a callback method to parse a date
613
+ *
614
+ * @final
615
+ * @access public
616
+ * @param callback $callback
617
+ */
618
+ public function add_callback($callback)
619
+ {
620
+ if (is_callable($callback))
621
+ {
622
+ $this->user[] = $callback;
623
+ }
624
+ else
625
+ {
626
+ trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
627
+ }
628
+ }
629
+
630
+ /**
631
+ * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
632
+ * well as allowing any of upper or lower case "T", horizontal tabs, or
633
+ * spaces to be used as the time seperator (including more than one))
634
+ *
635
+ * @access protected
636
+ * @return int Timestamp
637
+ */
638
+ public function date_w3cdtf($date)
639
+ {
640
+ static $pcre;
641
+ if (!$pcre)
642
+ {
643
+ $year = '([0-9]{4})';
644
+ $month = $day = $hour = $minute = $second = '([0-9]{2})';
645
+ $decimal = '([0-9]*)';
646
+ $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
647
+ $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
648
+ }
649
+ if (preg_match($pcre, $date, $match))
650
+ {
651
+ /*
652
+ Capturing subpatterns:
653
+ 1: Year
654
+ 2: Month
655
+ 3: Day
656
+ 4: Hour
657
+ 5: Minute
658
+ 6: Second
659
+ 7: Decimal fraction of a second
660
+ 8: Zulu
661
+ 9: Timezone ±
662
+ 10: Timezone hours
663
+ 11: Timezone minutes
664
+ */
665
+
666
+ // Fill in empty matches
667
+ for ($i = count($match); $i <= 3; $i++)
668
+ {
669
+ $match[$i] = '1';
670
+ }
671
+
672
+ for ($i = count($match); $i <= 7; $i++)
673
+ {
674
+ $match[$i] = '0';
675
+ }
676
+
677
+ // Numeric timezone
678
+ if (isset($match[9]) && $match[9] !== '')
679
+ {
680
+ $timezone = $match[10] * 3600;
681
+ $timezone += $match[11] * 60;
682
+ if ($match[9] === '-')
683
+ {
684
+ $timezone = 0 - $timezone;
685
+ }
686
+ }
687
+ else
688
+ {
689
+ $timezone = 0;
690
+ }
691
+
692
+ // Convert the number of seconds to an integer, taking decimals into account
693
+ $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
694
+
695
+ return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
696
+ }
697
+ else
698
+ {
699
+ return false;
700
+ }
701
+ }
702
+
703
+ /**
704
+ * Remove RFC822 comments
705
+ *
706
+ * @access protected
707
+ * @param string $data Data to strip comments from
708
+ * @return string Comment stripped string
709
+ */
710
+ public function remove_rfc2822_comments($string)
711
+ {
712
+ $string = (string) $string;
713
+ $position = 0;
714
+ $length = strlen($string);
715
+ $depth = 0;
716
+
717
+ $output = '';
718
+
719
+ while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
720
+ {
721
+ $output .= substr($string, $position, $pos - $position);
722
+ $position = $pos + 1;
723
+ if ($pos === 0 || $string[$pos - 1] !== '\\')
724
+ {
725
+ $depth++;
726
+ while ($depth && $position < $length)
727
+ {
728
+ $position += strcspn($string, '()', $position);
729
+ if ($string[$position - 1] === '\\')
730
+ {
731
+ $position++;
732
+ continue;
733
+ }
734
+ elseif (isset($string[$position]))
735
+ {
736
+ switch ($string[$position])
737
+ {
738
+ case '(':
739
+ $depth++;
740
+ break;
741
+
742
+ case ')':
743
+ $depth--;
744
+ break;
745
+ }
746
+ $position++;
747
+ }
748
+ else
749
+ {
750
+ break;
751
+ }
752
+ }
753
+ }
754
+ else
755
+ {
756
+ $output .= '(';
757
+ }
758
+ }
759
+ $output .= substr($string, $position);
760
+
761
+ return $output;
762
+ }
763
+
764
+ /**
765
+ * Parse RFC2822's date format
766
+ *
767
+ * @access protected
768
+ * @return int Timestamp
769
+ */
770
+ public function date_rfc2822($date)
771
+ {
772
+ static $pcre;
773
+ if (!$pcre)
774
+ {
775
+ $wsp = '[\x09\x20]';
776
+ $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
777
+ $optional_fws = $fws . '?';
778
+ $day_name = $this->day_pcre;
779
+ $month = $this->month_pcre;
780
+ $day = '([0-9]{1,2})';
781
+ $hour = $minute = $second = '([0-9]{2})';
782
+ $year = '([0-9]{2,4})';
783
+ $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
784
+ $character_zone = '([A-Z]{1,5})';
785
+ $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
786
+ $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';
787
+ }
788
+ if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
789
+ {
790
+ /*
791
+ Capturing subpatterns:
792
+ 1: Day name
793
+ 2: Day
794
+ 3: Month
795
+ 4: Year
796
+ 5: Hour
797
+ 6: Minute
798
+ 7: Second
799
+ 8: Timezone ±
800
+ 9: Timezone hours
801
+ 10: Timezone minutes
802
+ 11: Alphabetic timezone
803
+ */
804
+
805
+ // Find the month number
806
+ $month = $this->month[strtolower($match[3])];
807
+
808
+ // Numeric timezone
809
+ if ($match[8] !== '')
810
+ {
811
+ $timezone = $match[9] * 3600;
812
+ $timezone += $match[10] * 60;
813
+ if ($match[8] === '-')
814
+ {
815
+ $timezone = 0 - $timezone;
816
+ }
817
+ }
818
+ // Character timezone
819
+ elseif (isset($this->timezone[strtoupper($match[11])]))
820
+ {
821
+ $timezone = $this->timezone[strtoupper($match[11])];
822
+ }
823
+ // Assume everything else to be -0000
824
+ else
825
+ {
826
+ $timezone = 0;
827
+ }
828
+
829
+ // Deal with 2/3 digit years
830
+ if ($match[4] < 50)
831
+ {
832
+ $match[4] += 2000;
833
+ }
834
+ elseif ($match[4] < 1000)
835
+ {
836
+ $match[4] += 1900;
837
+ }
838
+
839
+ // Second is optional, if it is empty set it to zero
840
+ if ($match[7] !== '')
841
+ {
842
+ $second = $match[7];
843
+ }
844
+ else
845
+ {
846
+ $second = 0;
847
+ }
848
+
849
+ return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
850
+ }
851
+ else
852
+ {
853
+ return false;
854
+ }
855
+ }
856
+
857
+ /**
858
+ * Parse RFC850's date format
859
+ *
860
+ * @access protected
861
+ * @return int Timestamp
862
+ */
863
+ public function date_rfc850($date)
864
+ {
865
+ static $pcre;
866
+ if (!$pcre)
867
+ {
868
+ $space = '[\x09\x20]+';
869
+ $day_name = $this->day_pcre;
870
+ $month = $this->month_pcre;
871
+ $day = '([0-9]{1,2})';
872
+ $year = $hour = $minute = $second = '([0-9]{2})';
873
+ $zone = '([A-Z]{1,5})';
874
+ $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
875
+ }
876
+ if (preg_match($pcre, $date, $match))
877
+ {
878
+ /*
879
+ Capturing subpatterns:
880
+ 1: Day name
881
+ 2: Day
882
+ 3: Month
883
+ 4: Year
884
+ 5: Hour
885
+ 6: Minute
886
+ 7: Second
887
+ 8: Timezone
888
+ */
889
+
890
+ // Month
891
+ $month = $this->month[strtolower($match[3])];
892
+
893
+ // Character timezone
894
+ if (isset($this->timezone[strtoupper($match[8])]))
895
+ {
896
+ $timezone = $this->timezone[strtoupper($match[8])];
897
+ }
898
+ // Assume everything else to be -0000
899
+ else
900
+ {
901
+ $timezone = 0;
902
+ }
903
+
904
+ // Deal with 2 digit year
905
+ if ($match[4] < 50)
906
+ {
907
+ $match[4] += 2000;
908
+ }
909
+ else
910
+ {
911
+ $match[4] += 1900;
912
+ }
913
+
914
+ return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
915
+ }
916
+ else
917
+ {
918
+ return false;
919
+ }
920
+ }
921
+
922
+ /**
923
+ * Parse C99's asctime()'s date format
924
+ *
925
+ * @access protected
926
+ * @return int Timestamp
927
+ */
928
+ public function date_asctime($date)
929
+ {
930
+ static $pcre;
931
+ if (!$pcre)
932
+ {
933
+ $space = '[\x09\x20]+';
934
+ $wday_name = $this->day_pcre;
935
+ $mon_name = $this->month_pcre;
936
+ $day = '([0-9]{1,2})';
937
+ $hour = $sec = $min = '([0-9]{2})';
938
+ $year = '([0-9]{4})';
939
+ $terminator = '\x0A?\x00?';
940
+ $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
941
+ }
942
+ if (preg_match($pcre, $date, $match))
943
+ {
944
+ /*
945
+ Capturing subpatterns:
946
+ 1: Day name
947
+ 2: Month
948
+ 3: Day
949
+ 4: Hour
950
+ 5: Minute
951
+ 6: Second
952
+ 7: Year
953
+ */
954
+
955
+ $month = $this->month[strtolower($match[2])];
956
+ return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
957
+ }
958
+ else
959
+ {
960
+ return false;
961
+ }
962
+ }
963
+
964
+ /**
965
+ * Parse dates using strtotime()
966
+ *
967
+ * @access protected
968
+ * @return int Timestamp
969
+ */
970
+ public function date_strtotime($date)
971
+ {
972
+ $strtotime = strtotime($date);
973
+ if ($strtotime === -1 || $strtotime === false)
974
+ {
975
+ return false;
976
+ }
977
+ else
978
+ {
979
+ return $strtotime;
980
+ }
981
+ }
982
+ }
983
+
libs/SimpleCluvPie/library/SimpleCluvPie/Parser.php ADDED
@@ -0,0 +1,656 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Parses XML into something sane
46
+ *
47
+ *
48
+ * This class can be overloaded with {@see SimpleCluvPie::set_parser_class()}
49
+ *
50
+ * @package SimpleCluvPie
51
+ * @subpackage Parsing
52
+ */
53
+ class SimpleCluvPie_Parser
54
+ {
55
+ var $error_code;
56
+ var $error_string;
57
+ var $current_line;
58
+ var $current_column;
59
+ var $current_byte;
60
+ var $separator = ' ';
61
+ var $namespace = array('');
62
+ var $element = array('');
63
+ var $xml_base = array('');
64
+ var $xml_base_explicit = array(false);
65
+ var $xml_lang = array('');
66
+ var $data = array();
67
+ var $datas = array(array());
68
+ var $current_xhtml_construct = -1;
69
+ var $encoding;
70
+ protected $registry;
71
+
72
+ public function set_registry(SimpleCluvPie_Registry $registry)
73
+ {
74
+ $this->registry = $registry;
75
+ }
76
+
77
+ public function parse(&$data, $encoding, $url = '')
78
+ {
79
+ if (function_exists('Mf2\parse')) {
80
+ // Check for both h-feed and h-entry, as both a feed with no entries
81
+ // and a list of entries without an h-feed wrapper are both valid.
82
+ $position = 0;
83
+ while ($position = strpos($data, 'h-feed', $position)) {
84
+ $start = $position < 200 ? 0 : $position - 200;
85
+ $check = substr($data, $start, 400);
86
+ if (preg_match('/class="[^"]*h-feed/', $check)) {
87
+ return $this->parse_microformats($data, $url);
88
+ }
89
+ $position += 7;
90
+ }
91
+ $position = 0;
92
+ while ($position = strpos($data, 'h-entry', $position)) {
93
+ $start = $position < 200 ? 0 : $position - 200;
94
+ $check = substr($data, $start, 400);
95
+ if (preg_match('/class="[^"]*h-entry/', $check)) {
96
+ return $this->parse_microformats($data, $url);
97
+ }
98
+ $position += 7;
99
+ }
100
+ }
101
+
102
+ // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
103
+ if (strtoupper($encoding) === 'US-ASCII')
104
+ {
105
+ $this->encoding = 'UTF-8';
106
+ }
107
+ else
108
+ {
109
+ $this->encoding = $encoding;
110
+ }
111
+
112
+ // Strip BOM:
113
+ // UTF-32 Big Endian BOM
114
+ if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
115
+ {
116
+ $data = substr($data, 4);
117
+ }
118
+ // UTF-32 Little Endian BOM
119
+ elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
120
+ {
121
+ $data = substr($data, 4);
122
+ }
123
+ // UTF-16 Big Endian BOM
124
+ elseif (substr($data, 0, 2) === "\xFE\xFF")
125
+ {
126
+ $data = substr($data, 2);
127
+ }
128
+ // UTF-16 Little Endian BOM
129
+ elseif (substr($data, 0, 2) === "\xFF\xFE")
130
+ {
131
+ $data = substr($data, 2);
132
+ }
133
+ // UTF-8 BOM
134
+ elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
135
+ {
136
+ $data = substr($data, 3);
137
+ }
138
+
139
+ if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
140
+ {
141
+ $declaration = $this->registry->create('XML_Declaration_Parser', array(substr($data, 5, $pos - 5)));
142
+ if ($declaration->parse())
143
+ {
144
+ $data = substr($data, $pos + 2);
145
+ $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' ."\n". $this->declare_html_entities() . $data;
146
+ }
147
+ else
148
+ {
149
+ $this->error_string = 'SimpleCluvPie bug! Please report this!';
150
+ return false;
151
+ }
152
+ }
153
+
154
+ $return = true;
155
+
156
+ static $xml_is_sane = null;
157
+ if ($xml_is_sane === null)
158
+ {
159
+ $parser_check = xml_parser_create();
160
+ xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
161
+ xml_parser_free($parser_check);
162
+ $xml_is_sane = isset($values[0]['value']);
163
+ }
164
+
165
+ // Create the parser
166
+ if ($xml_is_sane)
167
+ {
168
+ $xml = xml_parser_create_ns($this->encoding, $this->separator);
169
+ xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
170
+ xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
171
+ xml_set_object($xml, $this);
172
+ xml_set_character_data_handler($xml, 'cdata');
173
+ xml_set_element_handler($xml, 'tag_open', 'tag_close');
174
+
175
+ // Parse!
176
+ if (!xml_parse($xml, $data, true))
177
+ {
178
+ $this->error_code = xml_get_error_code($xml);
179
+ $this->error_string = xml_error_string($this->error_code);
180
+ $return = false;
181
+ }
182
+ $this->current_line = xml_get_current_line_number($xml);
183
+ $this->current_column = xml_get_current_column_number($xml);
184
+ $this->current_byte = xml_get_current_byte_index($xml);
185
+ xml_parser_free($xml);
186
+ return $return;
187
+ }
188
+ else
189
+ {
190
+ libxml_clear_errors();
191
+ $xml = new XMLReader();
192
+ $xml->xml($data);
193
+ while (@$xml->read())
194
+ {
195
+ switch ($xml->nodeType)
196
+ {
197
+
198
+ case constant('XMLReader::END_ELEMENT'):
199
+ if ($xml->namespaceURI !== '')
200
+ {
201
+ $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
202
+ }
203
+ else
204
+ {
205
+ $tagName = $xml->localName;
206
+ }
207
+ $this->tag_close(null, $tagName);
208
+ break;
209
+ case constant('XMLReader::ELEMENT'):
210
+ $empty = $xml->isEmptyElement;
211
+ if ($xml->namespaceURI !== '')
212
+ {
213
+ $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
214
+ }
215
+ else
216
+ {
217
+ $tagName = $xml->localName;
218
+ }
219
+ $attributes = array();
220
+ while ($xml->moveToNextAttribute())
221
+ {
222
+ if ($xml->namespaceURI !== '')
223
+ {
224
+ $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
225
+ }
226
+ else
227
+ {
228
+ $attrName = $xml->localName;
229
+ }
230
+ $attributes[$attrName] = $xml->value;
231
+ }
232
+ $this->tag_open(null, $tagName, $attributes);
233
+ if ($empty)
234
+ {
235
+ $this->tag_close(null, $tagName);
236
+ }
237
+ break;
238
+ case constant('XMLReader::TEXT'):
239
+
240
+ case constant('XMLReader::CDATA'):
241
+ $this->cdata(null, $xml->value);
242
+ break;
243
+ }
244
+ }
245
+ if ($error = libxml_get_last_error())
246
+ {
247
+ $this->error_code = $error->code;
248
+ $this->error_string = $error->message;
249
+ $this->current_line = $error->line;
250
+ $this->current_column = $error->column;
251
+ return false;
252
+ }
253
+ else
254
+ {
255
+ return true;
256
+ }
257
+ }
258
+ }
259
+
260
+ public function get_error_code()
261
+ {
262
+ return $this->error_code;
263
+ }
264
+
265
+ public function get_error_string()
266
+ {
267
+ return $this->error_string;
268
+ }
269
+
270
+ public function get_current_line()
271
+ {
272
+ return $this->current_line;
273
+ }
274
+
275
+ public function get_current_column()
276
+ {
277
+ return $this->current_column;
278
+ }
279
+
280
+ public function get_current_byte()
281
+ {
282
+ return $this->current_byte;
283
+ }
284
+
285
+ public function get_data()
286
+ {
287
+ return $this->data;
288
+ }
289
+
290
+ public function tag_open($parser, $tag, $attributes)
291
+ {
292
+ list($this->namespace[], $this->element[]) = $this->split_ns($tag);
293
+
294
+ $attribs = array();
295
+ foreach ($attributes as $name => $value)
296
+ {
297
+ list($attrib_namespace, $attribute) = $this->split_ns($name);
298
+ $attribs[$attrib_namespace][$attribute] = $value;
299
+ }
300
+
301
+ if (isset($attribs[SIMPLECLUVPIE_NAMESPACE_XML]['base']))
302
+ {
303
+ $base = $this->registry->call('Misc', 'absolutize_url', array($attribs[SIMPLECLUVPIE_NAMESPACE_XML]['base'], end($this->xml_base)));
304
+ if ($base !== false)
305
+ {
306
+ $this->xml_base[] = $base;
307
+ $this->xml_base_explicit[] = true;
308
+ }
309
+ }
310
+ else
311
+ {
312
+ $this->xml_base[] = end($this->xml_base);
313
+ $this->xml_base_explicit[] = end($this->xml_base_explicit);
314
+ }
315
+
316
+ if (isset($attribs[SIMPLECLUVPIE_NAMESPACE_XML]['lang']))
317
+ {
318
+ $this->xml_lang[] = $attribs[SIMPLECLUVPIE_NAMESPACE_XML]['lang'];
319
+ }
320
+ else
321
+ {
322
+ $this->xml_lang[] = end($this->xml_lang);
323
+ }
324
+
325
+ if ($this->current_xhtml_construct >= 0)
326
+ {
327
+ $this->current_xhtml_construct++;
328
+ if (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_XHTML)
329
+ {
330
+ $this->data['data'] .= '<' . end($this->element);
331
+ if (isset($attribs['']))
332
+ {
333
+ foreach ($attribs[''] as $name => $value)
334
+ {
335
+ $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
336
+ }
337
+ }
338
+ $this->data['data'] .= '>';
339
+ }
340
+ }
341
+ else
342
+ {
343
+ $this->datas[] =& $this->data;
344
+ $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
345
+ $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));
346
+ if ((end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
347
+ || (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')
348
+ || (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_RSS_20 && in_array(end($this->element), array('title')))
349
+ || (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_RSS_090 && in_array(end($this->element), array('title')))
350
+ || (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_RSS_10 && in_array(end($this->element), array('title'))))
351
+ {
352
+ $this->current_xhtml_construct = 0;
353
+ }
354
+ }
355
+ }
356
+
357
+ public function cdata($parser, $cdata)
358
+ {
359
+ if ($this->current_xhtml_construct >= 0)
360
+ {
361
+ $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
362
+ }
363
+ else
364
+ {
365
+ $this->data['data'] .= $cdata;
366
+ }
367
+ }
368
+
369
+ public function tag_close($parser, $tag)
370
+ {
371
+ if ($this->current_xhtml_construct >= 0)
372
+ {
373
+ $this->current_xhtml_construct--;
374
+ if (end($this->namespace) === SIMPLECLUVPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
375
+ {
376
+ $this->data['data'] .= '</' . end($this->element) . '>';
377
+ }
378
+ }
379
+ if ($this->current_xhtml_construct === -1)
380
+ {
381
+ $this->data =& $this->datas[count($this->datas) - 1];
382
+ array_pop($this->datas);
383
+ }
384
+
385
+ array_pop($this->element);
386
+ array_pop($this->namespace);
387
+ array_pop($this->xml_base);
388
+ array_pop($this->xml_base_explicit);
389
+ array_pop($this->xml_lang);
390
+ }
391
+
392
+ public function split_ns($string)
393
+ {
394
+ static $cache = array();
395
+ if (!isset($cache[$string]))
396
+ {
397
+ if ($pos = strpos($string, $this->separator))
398
+ {
399
+ static $separator_length;
400
+ if (!$separator_length)
401
+ {
402
+ $separator_length = strlen($this->separator);
403
+ }
404
+ $namespace = substr($string, 0, $pos);
405
+ $local_name = substr($string, $pos + $separator_length);
406
+ if (strtolower($namespace) === SIMPLECLUVPIE_NAMESPACE_ITUNES)
407
+ {
408
+ $namespace = SIMPLECLUVPIE_NAMESPACE_ITUNES;
409
+ }
410
+
411
+ // Normalize the Media RSS namespaces
412
+ if ($namespace === SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG ||
413
+ $namespace === SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG2 ||
414
+ $namespace === SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG3 ||
415
+ $namespace === SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG4 ||
416
+ $namespace === SIMPLECLUVPIE_NAMESPACE_MEDIARSS_WRONG5 )
417
+ {
418
+ $namespace = SIMPLECLUVPIE_NAMESPACE_MEDIARSS;
419
+ }
420
+ $cache[$string] = array($namespace, $local_name);
421
+ }
422
+ else
423
+ {
424
+ $cache[$string] = array('', $string);
425
+ }
426
+ }
427
+ return $cache[$string];
428
+ }
429
+
430
+ private function parse_hcard($data, $category = false) {
431
+ $name = '';
432
+ $link = '';
433
+ // Check if h-card is set and pass that information on in the link.
434
+ if (isset($data['type']) && in_array('h-card', $data['type'])) {
435
+ if (isset($data['properties']['name'][0])) {
436
+ $name = $data['properties']['name'][0];
437
+ }
438
+ if (isset($data['properties']['url'][0])) {
439
+ $link = $data['properties']['url'][0];
440
+ if ($name === '') {
441
+ $name = $link;
442
+ }
443
+ else {
444
+ // can't have commas in categories.
445
+ $name = str_replace(',', '', $name);
446
+ }
447
+ $person_tag = $category ? '<span class="person-tag"></span>' : '';
448
+ return '<a class="h-card" href="'.$link.'">'.$person_tag.$name.'</a>';
449
+ }
450
+ }
451
+ return isset($data['value']) ? $data['value'] : '';
452
+ }
453
+
454
+ private function parse_microformats(&$data, $url) {
455
+ $feed_title = '';
456
+ $feed_author = NULL;
457
+ $author_cache = array();
458
+ $items = array();
459
+ $entries = array();
460
+ $mf = Mf2\parse($data, $url);
461
+ // First look for an h-feed.
462
+ $h_feed = array();
463
+ foreach ($mf['items'] as $mf_item) {
464
+ if (in_array('h-feed', $mf_item['type'])) {
465
+ $h_feed = $mf_item;
466
+ break;
467
+ }
468
+ // Also look for an h-feed in the children of each top level item.
469
+ if (!isset($mf_item['children'][0]['type'])) continue;
470
+ if (in_array('h-feed', $mf_item['children'][0]['type'])) {
471
+ $h_feed = $mf_item['children'][0];
472
+ // In this case the parent of the h-feed may be an h-card, so use it as
473
+ // the feed_author.
474
+ if (in_array('h-card', $mf_item['type'])) $feed_author = $mf_item;
475
+ break;
476
+ }
477
+ }
478
+ if (isset($h_feed['children'])) {
479
+ $entries = $h_feed['children'];
480
+ // Also set the feed title and store author from the h-feed if available.
481
+ if (isset($mf['items'][0]['properties']['name'][0])) {
482
+ $feed_title = $mf['items'][0]['properties']['name'][0];
483
+ }
484
+ if (isset($mf['items'][0]['properties']['author'][0])) {
485
+ $feed_author = $mf['items'][0]['properties']['author'][0];
486
+ }
487
+ }
488
+ else {
489
+ $entries = $mf['items'];
490
+ }
491
+ for ($i = 0; $i < count($entries); $i++) {
492
+ $entry = $entries[$i];
493
+ if (in_array('h-entry', $entry['type'])) {
494
+ $item = array();
495
+ $title = '';
496
+ $description = '';
497
+ if (isset($entry['properties']['url'][0])) {
498
+ $link = $entry['properties']['url'][0];
499
+ if (isset($link['value'])) $link = $link['value'];
500
+ $item['link'] = array(array('data' => $link));
501
+ }
502
+ if (isset($entry['properties']['uid'][0])) {
503
+ $guid = $entry['properties']['uid'][0];
504
+ if (isset($guid['value'])) $guid = $guid['value'];
505
+ $item['guid'] = array(array('data' => $guid));
506
+ }
507
+ if (isset($entry['properties']['name'][0])) {
508
+ $title = $entry['properties']['name'][0];
509
+ if (isset($title['value'])) $title = $title['value'];
510
+ $item['title'] = array(array('data' => $title));
511
+ }
512
+ if (isset($entry['properties']['author'][0]) || isset($feed_author)) {
513
+ // author is a special case, it can be plain text or an h-card array.
514
+ // If it's plain text it can also be a url that should be followed to
515
+ // get the actual h-card.
516
+ $author = isset($entry['properties']['author'][0]) ?
517
+ $entry['properties']['author'][0] : $feed_author;
518
+ if (!is_string($author)) {
519
+ $author = $this->parse_hcard($author);
520
+ }
521
+ else if (strpos($author, 'http') === 0) {
522
+ if (isset($author_cache[$author])) {
523
+ $author = $author_cache[$author];
524
+ }
525
+ else {
526
+ $mf = Mf2\fetch($author);
527
+ foreach ($mf['items'] as $hcard) {
528
+ // Only interested in an h-card by itself in this case.
529
+ if (!in_array('h-card', $hcard['type'])) {
530
+ continue;
531
+ }
532
+ // It must have a url property matching what we fetched.
533
+ if (!isset($hcard['properties']['url']) ||
534
+ !(in_array($author, $hcard['properties']['url']))) {
535
+ continue;
536
+ }
537
+ // Save parse_hcard the trouble of finding the correct url.
538
+ $hcard['properties']['url'][0] = $author;
539
+ // Cache this h-card for the next h-entry to check.
540
+ $author_cache[$author] = $this->parse_hcard($hcard);
541
+ $author = $author_cache[$author];
542
+ break;
543
+ }
544
+ }
545
+ }
546
+ $item['author'] = array(array('data' => $author));
547
+ }
548
+ if (isset($entry['properties']['photo'][0])) {
549
+ // If a photo is also in content, don't need to add it again here.
550
+ $content = '';
551
+ if (isset($entry['properties']['content'][0]['html'])) {
552
+ $content = $entry['properties']['content'][0]['html'];
553
+ }
554
+ $photo_list = array();
555
+ for ($j = 0; $j < count($entry['properties']['photo']); $j++) {
556
+ $photo = $entry['properties']['photo'][$j];
557
+ if (strpos($content, $photo) === false) {
558
+ $photo_list[] = $photo;
559
+ }
560
+ }
561
+ // When there's more than one photo show the first and use a lightbox.
562
+ $count = count($photo_list);
563
+ if ($count > 1) {
564
+ $description = '<p>';
565
+ for ($j = 0; $j < $count; $j++) {
566
+ $hidden = $j === 0 ? '' : 'class="hidden" ';
567
+ $description .= '<a href="'.$photo_list[$j].'" '.$hidden.
568
+ 'data-lightbox="image-set-'.$i.'">'.
569
+ '<img src="'.$photo_list[$j].'"></a>';
570
+ }
571
+ $description .= '<br><b>'.$count.' photos</b></p>';
572
+ }
573
+ else if ($count == 1) {
574
+ $description = '<p><img src="'.$photo_list[0].'"></p>';
575
+ }
576
+ }
577
+ if (isset($entry['properties']['content'][0]['html'])) {
578
+ // e-content['value'] is the same as p-name when they are on the same
579
+ // element. Use this to replace title with a strip_tags version so
580
+ // that alt text from images is not included in the title.
581
+ if ($entry['properties']['content'][0]['value'] === $title) {
582
+ $title = strip_tags($entry['properties']['content'][0]['html']);
583
+ $item['title'] = array(array('data' => $title));
584
+ }
585
+ $description .= $entry['properties']['content'][0]['html'];
586
+ if (isset($entry['properties']['in-reply-to'][0]['value'])) {
587
+ $in_reply_to = $entry['properties']['in-reply-to'][0]['value'];
588
+ $description .= '<p><span class="in-reply-to"></span> '.
589
+ '<a href="'.$in_reply_to.'">'.$in_reply_to.'</a><p>';
590
+ }
591
+ $item['description'] = array(array('data' => $description));
592
+ }
593
+ if (isset($entry['properties']['category'])) {
594
+ $category_csv = '';
595
+ // Categories can also contain h-cards.
596
+ foreach ($entry['properties']['category'] as $category) {
597
+ if ($category_csv !== '') $category_csv .= ', ';
598
+ if (is_string($category)) {
599
+ // Can't have commas in categories.
600
+ $category_csv .= str_replace(',', '', $category);
601
+ }
602
+ else {
603
+ $category_csv .= $this->parse_hcard($category, true);
604
+ }
605
+ }
606
+ $item['category'] = array(array('data' => $category_csv));
607
+ }
608
+ if (isset($entry['properties']['published'][0])) {
609
+ $timestamp = strtotime($entry['properties']['published'][0]);
610
+ $pub_date = date('F j Y g:ia', $timestamp).' GMT';
611
+ $item['pubDate'] = array(array('data' => $pub_date));
612
+ }
613
+ // The title and description are set to the empty string to represent
614
+ // a deleted item (which also makes it an invalid rss item).
615
+ if (isset($entry['properties']['deleted'][0])) {
616
+ $item['title'] = array(array('data' => ''));
617
+ $item['description'] = array(array('data' => ''));
618
+ }
619
+ $items[] = array('child' => array('' => $item));
620
+ }
621
+ }
622
+ // Mimic RSS data format when storing microformats.
623
+ $link = array(array('data' => $url));
624
+ $image = '';
625
+ if (!is_string($feed_author) &&
626
+ isset($feed_author['properties']['photo'][0])) {
627
+ $image = array(array('child' => array('' => array('url' =>
628
+ array(array('data' => $feed_author['properties']['photo'][0]))))));
629
+ }
630
+ // Use the a name given for the h-feed, or get the title from the html.
631
+ if ($feed_title !== '') {
632
+ $feed_title = array(array('data' => htmlspecialchars($feed_title)));
633
+ }
634
+ else if ($position = strpos($data, '<title>')) {
635
+ $start = $position < 200 ? 0 : $position - 200;
636
+ $check = substr($data, $start, 400);
637
+ $matches = array();
638
+ if (preg_match('/<title>(.+)<\/title>/', $check, $matches)) {
639
+ $feed_title = array(array('data' => htmlspecialchars($matches[1])));
640
+ }
641
+ }
642
+ $channel = array('channel' => array(array('child' => array('' =>
643
+ array('link' => $link, 'image' => $image, 'title' => $feed_title,
644
+ 'item' => $items)))));
645
+ $rss = array(array('attribs' => array('' => array('version' => '2.0')),
646
+ 'child' => array('' => $channel)));
647
+ $this->data = array('child' => array('' => array('rss' => $rss)));
648
+ return true;
649
+ }
650
+
651
+ private function declare_html_entities() {
652
+ // This is required because the RSS specification says that entity-encoded
653
+ // html is allowed, but the xml specification says they must be declared.
654
+ return '<!DOCTYPE html [ <!ENTITY nbsp "&#x00A0;"> <!ENTITY iexcl "&#x00A1;"> <!ENTITY cent "&#x00A2;"> <!ENTITY pound "&#x00A3;"> <!ENTITY curren "&#x00A4;"> <!ENTITY yen "&#x00A5;"> <!ENTITY brvbar "&#x00A6;"> <!ENTITY sect "&#x00A7;"> <!ENTITY uml "&#x00A8;"> <!ENTITY copy "&#x00A9;"> <!ENTITY ordf "&#x00AA;"> <!ENTITY laquo "&#x00AB;"> <!ENTITY not "&#x00AC;"> <!ENTITY shy "&#x00AD;"> <!ENTITY reg "&#x00AE;"> <!ENTITY macr "&#x00AF;"> <!ENTITY deg "&#x00B0;"> <!ENTITY plusmn "&#x00B1;"> <!ENTITY sup2 "&#x00B2;"> <!ENTITY sup3 "&#x00B3;"> <!ENTITY acute "&#x00B4;"> <!ENTITY micro "&#x00B5;"> <!ENTITY para "&#x00B6;"> <!ENTITY middot "&#x00B7;"> <!ENTITY cedil "&#x00B8;"> <!ENTITY sup1 "&#x00B9;"> <!ENTITY ordm "&#x00BA;"> <!ENTITY raquo "&#x00BB;"> <!ENTITY frac14 "&#x00BC;"> <!ENTITY frac12 "&#x00BD;"> <!ENTITY frac34 "&#x00BE;"> <!ENTITY iquest "&#x00BF;"> <!ENTITY Agrave "&#x00C0;"> <!ENTITY Aacute "&#x00C1;"> <!ENTITY Acirc "&#x00C2;"> <!ENTITY Atilde "&#x00C3;"> <!ENTITY Auml "&#x00C4;"> <!ENTITY Aring "&#x00C5;"> <!ENTITY AElig "&#x00C6;"> <!ENTITY Ccedil "&#x00C7;"> <!ENTITY Egrave "&#x00C8;"> <!ENTITY Eacute "&#x00C9;"> <!ENTITY Ecirc "&#x00CA;"> <!ENTITY Euml "&#x00CB;"> <!ENTITY Igrave "&#x00CC;"> <!ENTITY Iacute "&#x00CD;"> <!ENTITY Icirc "&#x00CE;"> <!ENTITY Iuml "&#x00CF;"> <!ENTITY ETH "&#x00D0;"> <!ENTITY Ntilde "&#x00D1;"> <!ENTITY Ograve "&#x00D2;"> <!ENTITY Oacute "&#x00D3;"> <!ENTITY Ocirc "&#x00D4;"> <!ENTITY Otilde "&#x00D5;"> <!ENTITY Ouml "&#x00D6;"> <!ENTITY times "&#x00D7;"> <!ENTITY Oslash "&#x00D8;"> <!ENTITY Ugrave "&#x00D9;"> <!ENTITY Uacute "&#x00DA;"> <!ENTITY Ucirc "&#x00DB;"> <!ENTITY Uuml "&#x00DC;"> <!ENTITY Yacute "&#x00DD;"> <!ENTITY THORN "&#x00DE;"> <!ENTITY szlig "&#x00DF;"> <!ENTITY agrave "&#x00E0;"> <!ENTITY aacute "&#x00E1;"> <!ENTITY acirc "&#x00E2;"> <!ENTITY atilde "&#x00E3;"> <!ENTITY auml "&#x00E4;"> <!ENTITY aring "&#x00E5;"> <!ENTITY aelig "&#x00E6;"> <!ENTITY ccedil "&#x00E7;"> <!ENTITY egrave "&#x00E8;"> <!ENTITY eacute "&#x00E9;"> <!ENTITY ecirc "&#x00EA;"> <!ENTITY euml "&#x00EB;"> <!ENTITY igrave "&#x00EC;"> <!ENTITY iacute "&#x00ED;"> <!ENTITY icirc "&#x00EE;"> <!ENTITY iuml "&#x00EF;"> <!ENTITY eth "&#x00F0;"> <!ENTITY ntilde "&#x00F1;"> <!ENTITY ograve "&#x00F2;"> <!ENTITY oacute "&#x00F3;"> <!ENTITY ocirc "&#x00F4;"> <!ENTITY otilde "&#x00F5;"> <!ENTITY ouml "&#x00F6;"> <!ENTITY divide "&#x00F7;"> <!ENTITY oslash "&#x00F8;"> <!ENTITY ugrave "&#x00F9;"> <!ENTITY uacute "&#x00FA;"> <!ENTITY ucirc "&#x00FB;"> <!ENTITY uuml "&#x00FC;"> <!ENTITY yacute "&#x00FD;"> <!ENTITY thorn "&#x00FE;"> <!ENTITY yuml "&#x00FF;"> <!ENTITY OElig "&#x0152;"> <!ENTITY oelig "&#x0153;"> <!ENTITY Scaron "&#x0160;"> <!ENTITY scaron "&#x0161;"> <!ENTITY Yuml "&#x0178;"> <!ENTITY fnof "&#x0192;"> <!ENTITY circ "&#x02C6;"> <!ENTITY tilde "&#x02DC;"> <!ENTITY Alpha "&#x0391;"> <!ENTITY Beta "&#x0392;"> <!ENTITY Gamma "&#x0393;"> <!ENTITY Epsilon "&#x0395;"> <!ENTITY Zeta "&#x0396;"> <!ENTITY Eta "&#x0397;"> <!ENTITY Theta "&#x0398;"> <!ENTITY Iota "&#x0399;"> <!ENTITY Kappa "&#x039A;"> <!ENTITY Lambda "&#x039B;"> <!ENTITY Mu "&#x039C;"> <!ENTITY Nu "&#x039D;"> <!ENTITY Xi "&#x039E;"> <!ENTITY Omicron "&#x039F;"> <!ENTITY Pi "&#x03A0;"> <!ENTITY Rho "&#x03A1;"> <!ENTITY Sigma "&#x03A3;"> <!ENTITY Tau "&#x03A4;"> <!ENTITY Upsilon "&#x03A5;"> <!ENTITY Phi "&#x03A6;"> <!ENTITY Chi "&#x03A7;"> <!ENTITY Psi "&#x03A8;"> <!ENTITY Omega "&#x03A9;"> <!ENTITY alpha "&#x03B1;"> <!ENTITY beta "&#x03B2;"> <!ENTITY gamma "&#x03B3;"> <!ENTITY delta "&#x03B4;"> <!ENTITY epsilon "&#x03B5;"> <!ENTITY zeta "&#x03B6;"> <!ENTITY eta "&#x03B7;"> <!ENTITY theta "&#x03B8;"> <!ENTITY iota "&#x03B9;"> <!ENTITY kappa "&#x03BA;"> <!ENTITY lambda "&#x03BB;"> <!ENTITY mu "&#x03BC;"> <!ENTITY nu "&#x03BD;"> <!ENTITY xi "&#x03BE;"> <!ENTITY omicron "&#x03BF;"> <!ENTITY pi "&#x03C0;"> <!ENTITY rho "&#x03C1;"> <!ENTITY sigmaf "&#x03C2;"> <!ENTITY sigma "&#x03C3;"> <!ENTITY tau "&#x03C4;"> <!ENTITY upsilon "&#x03C5;"> <!ENTITY phi "&#x03C6;"> <!ENTITY chi "&#x03C7;"> <!ENTITY psi "&#x03C8;"> <!ENTITY omega "&#x03C9;"> <!ENTITY thetasym "&#x03D1;"> <!ENTITY upsih "&#x03D2;"> <!ENTITY piv "&#x03D6;"> <!ENTITY ensp "&#x2002;"> <!ENTITY emsp "&#x2003;"> <!ENTITY thinsp "&#x2009;"> <!ENTITY zwnj "&#x200C;"> <!ENTITY zwj "&#x200D;"> <!ENTITY lrm "&#x200E;"> <!ENTITY rlm "&#x200F;"> <!ENTITY ndash "&#x2013;"> <!ENTITY mdash "&#x2014;"> <!ENTITY lsquo "&#x2018;"> <!ENTITY rsquo "&#x2019;"> <!ENTITY sbquo "&#x201A;"> <!ENTITY ldquo "&#x201C;"> <!ENTITY rdquo "&#x201D;"> <!ENTITY bdquo "&#x201E;"> <!ENTITY dagger "&#x2020;"> <!ENTITY Dagger "&#x2021;"> <!ENTITY bull "&#x2022;"> <!ENTITY hellip "&#x2026;"> <!ENTITY permil "&#x2030;"> <!ENTITY prime "&#x2032;"> <!ENTITY Prime "&#x2033;"> <!ENTITY lsaquo "&#x2039;"> <!ENTITY rsaquo "&#x203A;"> <!ENTITY oline "&#x203E;"> <!ENTITY frasl "&#x2044;"> <!ENTITY euro "&#x20AC;"> <!ENTITY image "&#x2111;"> <!ENTITY weierp "&#x2118;"> <!ENTITY real "&#x211C;"> <!ENTITY trade "&#x2122;"> <!ENTITY alefsym "&#x2135;"> <!ENTITY larr "&#x2190;"> <!ENTITY uarr "&#x2191;"> <!ENTITY rarr "&#x2192;"> <!ENTITY darr "&#x2193;"> <!ENTITY harr "&#x2194;"> <!ENTITY crarr "&#x21B5;"> <!ENTITY lArr "&#x21D0;"> <!ENTITY uArr "&#x21D1;"> <!ENTITY rArr "&#x21D2;"> <!ENTITY dArr "&#x21D3;"> <!ENTITY hArr "&#x21D4;"> <!ENTITY forall "&#x2200;"> <!ENTITY part "&#x2202;"> <!ENTITY exist "&#x2203;"> <!ENTITY empty "&#x2205;"> <!ENTITY nabla "&#x2207;"> <!ENTITY isin "&#x2208;"> <!ENTITY notin "&#x2209;"> <!ENTITY ni "&#x220B;"> <!ENTITY prod "&#x220F;"> <!ENTITY sum "&#x2211;"> <!ENTITY minus "&#x2212;"> <!ENTITY lowast "&#x2217;"> <!ENTITY radic "&#x221A;"> <!ENTITY prop "&#x221D;"> <!ENTITY infin "&#x221E;"> <!ENTITY ang "&#x2220;"> <!ENTITY and "&#x2227;"> <!ENTITY or "&#x2228;"> <!ENTITY cap "&#x2229;"> <!ENTITY cup "&#x222A;"> <!ENTITY int "&#x222B;"> <!ENTITY there4 "&#x2234;"> <!ENTITY sim "&#x223C;"> <!ENTITY cong "&#x2245;"> <!ENTITY asymp "&#x2248;"> <!ENTITY ne "&#x2260;"> <!ENTITY equiv "&#x2261;"> <!ENTITY le "&#x2264;"> <!ENTITY ge "&#x2265;"> <!ENTITY sub "&#x2282;"> <!ENTITY sup "&#x2283;"> <!ENTITY nsub "&#x2284;"> <!ENTITY sube "&#x2286;"> <!ENTITY supe "&#x2287;"> <!ENTITY oplus "&#x2295;"> <!ENTITY otimes "&#x2297;"> <!ENTITY perp "&#x22A5;"> <!ENTITY sdot "&#x22C5;"> <!ENTITY lceil "&#x2308;"> <!ENTITY rceil "&#x2309;"> <!ENTITY lfloor "&#x230A;"> <!ENTITY rfloor "&#x230B;"> <!ENTITY lang "&#x2329;"> <!ENTITY rang "&#x232A;"> <!ENTITY loz "&#x25CA;"> <!ENTITY spades "&#x2660;"> <!ENTITY clubs "&#x2663;"> <!ENTITY hearts "&#x2665;"> <!ENTITY diams "&#x2666;"> ]>';
655
+ }
656
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Rating.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles `<media:rating>` or `<itunes:explicit>` tags as defined in Media RSS and iTunes RSS respectively
46
+ *
47
+ * Used by {@see SimpleCluvPie_Enclosure::get_rating()} and {@see SimpleCluvPie_Enclosure::get_ratings()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_rating_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Rating
55
+ {
56
+ /**
57
+ * Rating scheme
58
+ *
59
+ * @var string
60
+ * @see get_scheme()
61
+ */
62
+ var $scheme;
63
+
64
+ /**
65
+ * Rating value
66
+ *
67
+ * @var string
68
+ * @see get_value()
69
+ */
70
+ var $value;
71
+
72
+ /**
73
+ * Constructor, used to input the data
74
+ *
75
+ * For documentation on all the parameters, see the corresponding
76
+ * properties and their accessors
77
+ */
78
+ public function __construct($scheme = null, $value = null)
79
+ {
80
+ $this->scheme = $scheme;
81
+ $this->value = $value;
82
+ }
83
+
84
+ /**
85
+ * String-ified version
86
+ *
87
+ * @return string
88
+ */
89
+ public function __toString()
90
+ {
91
+ // There is no $this->data here
92
+ return md5(serialize($this));
93
+ }
94
+
95
+ /**
96
+ * Get the organizational scheme for the rating
97
+ *
98
+ * @return string|null
99
+ */
100
+ public function get_scheme()
101
+ {
102
+ if ($this->scheme !== null)
103
+ {
104
+ return $this->scheme;
105
+ }
106
+ else
107
+ {
108
+ return null;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Get the value of the rating
114
+ *
115
+ * @return string|null
116
+ */
117
+ public function get_value()
118
+ {
119
+ if ($this->value !== null)
120
+ {
121
+ return $this->value;
122
+ }
123
+ else
124
+ {
125
+ return null;
126
+ }
127
+ }
128
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Registry.php ADDED
@@ -0,0 +1,224 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles creating objects and calling methods
46
+ *
47
+ * Access this via {@see SimpleCluvPie::get_registry()}
48
+ *
49
+ * @package SimpleCluvPie
50
+ */
51
+ class SimpleCluvPie_Registry
52
+ {
53
+ /**
54
+ * Default class mapping
55
+ *
56
+ * Overriding classes *must* subclass these.
57
+ *
58
+ * @var array
59
+ */
60
+ protected $default = array(
61
+ 'Cache' => 'SimpleCluvPie_Cache',
62
+ 'Locator' => 'SimpleCluvPie_Locator',
63
+ 'Parser' => 'SimpleCluvPie_Parser',
64
+ 'File' => 'SimpleCluvPie_File',
65
+ 'Sanitize' => 'SimpleCluvPie_Sanitize',
66
+ 'Item' => 'SimpleCluvPie_Item',
67
+ 'Author' => 'SimpleCluvPie_Author',
68
+ 'Category' => 'SimpleCluvPie_Category',
69
+ 'Enclosure' => 'SimpleCluvPie_Enclosure',
70
+ 'Caption' => 'SimpleCluvPie_Caption',
71
+ 'Copyright' => 'SimpleCluvPie_Copyright',
72
+ 'Credit' => 'SimpleCluvPie_Credit',
73
+ 'Rating' => 'SimpleCluvPie_Rating',
74
+ 'Restriction' => 'SimpleCluvPie_Restriction',
75
+ 'Content_Type_Sniffer' => 'SimpleCluvPie_Content_Type_Sniffer',
76
+ 'Source' => 'SimpleCluvPie_Source',
77
+ 'Misc' => 'SimpleCluvPie_Misc',
78
+ 'XML_Declaration_Parser' => 'SimpleCluvPie_XML_Declaration_Parser',
79
+ 'Parse_Date' => 'SimpleCluvPie_Parse_Date',
80
+ );
81
+
82
+ /**
83
+ * Class mapping
84
+ *
85
+ * @see register()
86
+ * @var array
87
+ */
88
+ protected $classes = array();
89
+
90
+ /**
91
+ * Legacy classes
92
+ *
93
+ * @see register()
94
+ * @var array
95
+ */
96
+ protected $legacy = array();
97
+
98
+ /**
99
+ * Constructor
100
+ *
101
+ * No-op
102
+ */
103
+ public function __construct() { }
104
+
105
+ /**
106
+ * Register a class
107
+ *
108
+ * @param string $type See {@see $default} for names
109
+ * @param string $class Class name, must subclass the corresponding default
110
+ * @param bool $legacy Whether to enable legacy support for this class
111
+ * @return bool Successfulness
112
+ */
113
+ public function register($type, $class, $legacy = false)
114
+ {
115
+ if (!@is_subclass_of($class, $this->default[$type]))
116
+ {
117
+ return false;
118
+ }
119
+
120
+ $this->classes[$type] = $class;
121
+
122
+ if ($legacy)
123
+ {
124
+ $this->legacy[] = $class;
125
+ }
126
+
127
+ return true;
128
+ }
129
+
130
+ /**
131
+ * Get the class registered for a type
132
+ *
133
+ * Where possible, use {@see create()} or {@see call()} instead
134
+ *
135
+ * @param string $type
136
+ * @return string|null
137
+ */
138
+ public function get_class($type)
139
+ {
140
+ if (!empty($this->classes[$type]))
141
+ {
142
+ return $this->classes[$type];
143
+ }
144
+ if (!empty($this->default[$type]))
145
+ {
146
+ return $this->default[$type];
147
+ }
148
+
149
+ return null;
150
+ }
151
+
152
+ /**
153
+ * Create a new instance of a given type
154
+ *
155
+ * @param string $type
156
+ * @param array $parameters Parameters to pass to the constructor
157
+ * @return object Instance of class
158
+ */
159
+ public function &create($type, $parameters = array())
160
+ {
161
+ $class = $this->get_class($type);
162
+
163
+ if (in_array($class, $this->legacy))
164
+ {
165
+ switch ($type)
166
+ {
167
+ case 'locator':
168
+ // Legacy: file, timeout, useragent, file_class, max_checked_feeds, content_type_sniffer_class
169
+ // Specified: file, timeout, useragent, max_checked_feeds
170
+ $replacement = array($this->get_class('file'), $parameters[3], $this->get_class('content_type_sniffer'));
171
+ array_splice($parameters, 3, 1, $replacement);
172
+ break;
173
+ }
174
+ }
175
+
176
+ if (!method_exists($class, '__construct'))
177
+ {
178
+ $instance = new $class;
179
+ }
180
+ else
181
+ {
182
+ $reflector = new ReflectionClass($class);
183
+ $instance = $reflector->newInstanceArgs($parameters);
184
+ }
185
+
186
+ if (method_exists($instance, 'set_registry'))
187
+ {
188
+ $instance->set_registry($this);
189
+ }
190
+ return $instance;
191
+ }
192
+
193
+ /**
194
+ * Call a static method for a type
195
+ *
196
+ * @param string $type
197
+ * @param string $method
198
+ * @param array $parameters
199
+ * @return mixed
200
+ */
201
+ public function &call($type, $method, $parameters = array())
202
+ {
203
+ $class = $this->get_class($type);
204
+
205
+ if (in_array($class, $this->legacy))
206
+ {
207
+ switch ($type)
208
+ {
209
+ case 'Cache':
210
+ // For backwards compatibility with old non-static
211
+ // Cache::create() methods
212
+ if ($method === 'get_handler')
213
+ {
214
+ $result = @call_user_func_array(array($class, 'create'), $parameters);
215
+ return $result;
216
+ }
217
+ break;
218
+ }
219
+ }
220
+
221
+ $result = call_user_func_array(array($class, $method), $parameters);
222
+ return $result;
223
+ }
224
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Restriction.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles `<media:restriction>` as defined in Media RSS
46
+ *
47
+ * Used by {@see SimpleCluvPie_Enclosure::get_restriction()} and {@see SimpleCluvPie_Enclosure::get_restrictions()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_restriction_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Restriction
55
+ {
56
+ /**
57
+ * Relationship ('allow'/'deny')
58
+ *
59
+ * @var string
60
+ * @see get_relationship()
61
+ */
62
+ var $relationship;
63
+
64
+ /**
65
+ * Type of restriction
66
+ *
67
+ * @var string
68
+ * @see get_type()
69
+ */
70
+ var $type;
71
+
72
+ /**
73
+ * Restricted values
74
+ *
75
+ * @var string
76
+ * @see get_value()
77
+ */
78
+ var $value;
79
+
80
+ /**
81
+ * Constructor, used to input the data
82
+ *
83
+ * For documentation on all the parameters, see the corresponding
84
+ * properties and their accessors
85
+ */
86
+ public function __construct($relationship = null, $type = null, $value = null)
87
+ {
88
+ $this->relationship = $relationship;
89
+ $this->type = $type;
90
+ $this->value = $value;
91
+ }
92
+
93
+ /**
94
+ * String-ified version
95
+ *
96
+ * @return string
97
+ */
98
+ public function __toString()
99
+ {
100
+ // There is no $this->data here
101
+ return md5(serialize($this));
102
+ }
103
+
104
+ /**
105
+ * Get the relationship
106
+ *
107
+ * @return string|null Either 'allow' or 'deny'
108
+ */
109
+ public function get_relationship()
110
+ {
111
+ if ($this->relationship !== null)
112
+ {
113
+ return $this->relationship;
114
+ }
115
+ else
116
+ {
117
+ return null;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Get the type
123
+ *
124
+ * @return string|null
125
+ */
126
+ public function get_type()
127
+ {
128
+ if ($this->type !== null)
129
+ {
130
+ return $this->type;
131
+ }
132
+ else
133
+ {
134
+ return null;
135
+ }
136
+ }
137
+
138
+ /**
139
+ * Get the list of restricted things
140
+ *
141
+ * @return string|null
142
+ */
143
+ public function get_value()
144
+ {
145
+ if ($this->value !== null)
146
+ {
147
+ return $this->value;
148
+ }
149
+ else
150
+ {
151
+ return null;
152
+ }
153
+ }
154
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Sanitize.php ADDED
@@ -0,0 +1,589 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Used for data cleanup and post-processing
46
+ *
47
+ *
48
+ * This class can be overloaded with {@see SimpleCluvPie::set_sanitize_class()}
49
+ *
50
+ * @package SimpleCluvPie
51
+ * @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
52
+ */
53
+ class SimpleCluvPie_Sanitize
54
+ {
55
+ // Private vars
56
+ var $base;
57
+
58
+ // Options
59
+ var $remove_div = true;
60
+ var $image_handler = '';
61
+ var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
62
+ var $encode_instead_of_strip = false;
63
+ var $strip_attributes = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
64
+ var $add_attributes = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none'));
65
+ var $strip_comments = false;
66
+ var $output_encoding = 'UTF-8';
67
+ var $enable_cache = true;
68
+ var $cache_location = './cache';
69
+ var $cache_name_function = 'md5';
70
+ var $timeout = 10;
71
+ var $useragent = '';
72
+ var $force_fsockopen = false;
73
+ var $replace_url_attributes = null;
74
+
75
+ public function __construct()
76
+ {
77
+ // Set defaults
78
+ $this->set_url_replacements(null);
79
+ }
80
+
81
+ public function remove_div($enable = true)
82
+ {
83
+ $this->remove_div = (bool) $enable;
84
+ }
85
+
86
+ public function set_image_handler($page = false)
87
+ {
88
+ if ($page)
89
+ {
90
+ $this->image_handler = (string) $page;
91
+ }
92
+ else
93
+ {
94
+ $this->image_handler = false;
95
+ }
96
+ }
97
+
98
+ public function set_registry(SimpleCluvPie_Registry $registry)
99
+ {
100
+ $this->registry = $registry;
101
+ }
102
+
103
+ public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimpleCluvPie_Cache')
104
+ {
105
+ if (isset($enable_cache))
106
+ {
107
+ $this->enable_cache = (bool) $enable_cache;
108
+ }
109
+
110
+ if ($cache_location)
111
+ {
112
+ $this->cache_location = (string) $cache_location;
113
+ }
114
+
115
+ if ($cache_name_function)
116
+ {
117
+ $this->cache_name_function = (string) $cache_name_function;
118
+ }
119
+ }
120
+
121
+ public function pass_file_data($file_class = 'SimpleCluvPie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
122
+ {
123
+ if ($timeout)
124
+ {
125
+ $this->timeout = (string) $timeout;
126
+ }
127
+
128
+ if ($useragent)
129
+ {
130
+ $this->useragent = (string) $useragent;
131
+ }
132
+
133
+ if ($force_fsockopen)
134
+ {
135
+ $this->force_fsockopen = (string) $force_fsockopen;
136
+ }
137
+ }
138
+
139
+ public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
140
+ {
141
+ if ($tags)
142
+ {
143
+ if (is_array($tags))
144
+ {
145
+ $this->strip_htmltags = $tags;
146
+ }
147
+ else
148
+ {
149
+ $this->strip_htmltags = explode(',', $tags);
150
+ }
151
+ }
152
+ else
153
+ {
154
+ $this->strip_htmltags = false;
155
+ }
156
+ }
157
+
158
+ public function encode_instead_of_strip($encode = false)
159
+ {
160
+ $this->encode_instead_of_strip = (bool) $encode;
161
+ }
162
+
163
+ public function strip_attributes($attribs = array('bgsound', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
164
+ {
165
+ if ($attribs)
166
+ {
167
+ if (is_array($attribs))
168
+ {
169
+ $this->strip_attributes = $attribs;
170
+ }
171
+ else
172
+ {
173
+ $this->strip_attributes = explode(',', $attribs);
174
+ }
175
+ }
176
+ else
177
+ {
178
+ $this->strip_attributes = false;
179
+ }
180
+ }
181
+
182
+ public function add_attributes($attribs = array('audio' => array('preload' => 'none'), 'iframe' => array('sandbox' => 'allow-scripts allow-same-origin'), 'video' => array('preload' => 'none')))
183
+ {
184
+ if ($attribs)
185
+ {
186
+ if (is_array($attribs))
187
+ {
188
+ $this->add_attributes = $attribs;
189
+ }
190
+ else
191
+ {
192
+ $this->add_attributes = explode(',', $attribs);
193
+ }
194
+ }
195
+ else
196
+ {
197
+ $this->add_attributes = false;
198
+ }
199
+ }
200
+
201
+ public function strip_comments($strip = false)
202
+ {
203
+ $this->strip_comments = (bool) $strip;
204
+ }
205
+
206
+ public function set_output_encoding($encoding = 'UTF-8')
207
+ {
208
+ $this->output_encoding = (string) $encoding;
209
+ }
210
+
211
+ /**
212
+ * Set element/attribute key/value pairs of HTML attributes
213
+ * containing URLs that need to be resolved relative to the feed
214
+ *
215
+ * Defaults to |a|@href, |area|@href, |blockquote|@cite, |del|@cite,
216
+ * |form|@action, |img|@longdesc, |img|@src, |input|@src, |ins|@cite,
217
+ * |q|@cite
218
+ *
219
+ * @since 1.0
220
+ * @param array|null $element_attribute Element/attribute key/value pairs, null for default
221
+ */
222
+ public function set_url_replacements($element_attribute = null)
223
+ {
224
+ if ($element_attribute === null)
225
+ {
226
+ $element_attribute = array(
227
+ 'a' => 'href',
228
+ 'area' => 'href',
229
+ 'blockquote' => 'cite',
230
+ 'del' => 'cite',
231
+ 'form' => 'action',
232
+ 'img' => array(
233
+ 'longdesc',
234
+ 'src'
235
+ ),
236
+ 'input' => 'src',
237
+ 'ins' => 'cite',
238
+ 'q' => 'cite'
239
+ );
240
+ }
241
+ $this->replace_url_attributes = (array) $element_attribute;
242
+ }
243
+
244
+ public function sanitize($data, $type, $base = '')
245
+ {
246
+ $data = trim($data);
247
+ if ($data !== '' || $type & SIMPLECLUVPIE_CONSTRUCT_IRI)
248
+ {
249
+ if ($type & SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML)
250
+ {
251
+ 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]*' . SIMPLECLUVPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
252
+ {
253
+ $type |= SIMPLECLUVPIE_CONSTRUCT_HTML;
254
+ }
255
+ else
256
+ {
257
+ $type |= SIMPLECLUVPIE_CONSTRUCT_TEXT;
258
+ }
259
+ }
260
+
261
+ if ($type & SIMPLECLUVPIE_CONSTRUCT_BASE64)
262
+ {
263
+ $data = base64_decode($data);
264
+ }
265
+
266
+ if ($type & (SIMPLECLUVPIE_CONSTRUCT_HTML | SIMPLECLUVPIE_CONSTRUCT_XHTML))
267
+ {
268
+
269
+ if (!class_exists('DOMDocument'))
270
+ {
271
+ throw new SimpleCluvPie_Exception('DOMDocument not found, unable to use sanitizer');
272
+ }
273
+ $document = new DOMDocument();
274
+ $document->encoding = 'UTF-8';
275
+
276
+ // See https://github.com/simplecluvpie/simplecluvpie/issues/334
277
+ $unique_tag = '#'.uniqid().'#';
278
+ $data = trim($unique_tag . $data . $unique_tag);
279
+
280
+ $data = $this->preprocess($data, $type);
281
+
282
+ set_error_handler(array('SimpleCluvPie_Misc', 'silence_errors'));
283
+ $document->loadHTML($data);
284
+ restore_error_handler();
285
+
286
+ $xpath = new DOMXPath($document);
287
+
288
+ // Strip comments
289
+ if ($this->strip_comments)
290
+ {
291
+ $comments = $xpath->query('//comment()');
292
+
293
+ foreach ($comments as $comment)
294
+ {
295
+ $comment->parentNode->removeChild($comment);
296
+ }
297
+ }
298
+
299
+ // Strip out HTML tags and attributes that might cause various security problems.
300
+ // Based on recommendations by Mark Pilgrim at:
301
+ // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
302
+ if ($this->strip_htmltags)
303
+ {
304
+ foreach ($this->strip_htmltags as $tag)
305
+ {
306
+ $this->strip_tag($tag, $document, $xpath, $type);
307
+ }
308
+ }
309
+
310
+ if ($this->strip_attributes)
311
+ {
312
+ foreach ($this->strip_attributes as $attrib)
313
+ {
314
+ $this->strip_attr($attrib, $xpath);
315
+ }
316
+ }
317
+
318
+ if ($this->add_attributes)
319
+ {
320
+ foreach ($this->add_attributes as $tag => $valuePairs)
321
+ {
322
+ $this->add_attr($tag, $valuePairs, $document);
323
+ }
324
+ }
325
+
326
+ // Replace relative URLs
327
+ $this->base = $base;
328
+ foreach ($this->replace_url_attributes as $element => $attributes)
329
+ {
330
+ $this->replace_urls($document, $element, $attributes);
331
+ }
332
+
333
+ // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
334
+ if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
335
+ {
336
+ $images = $document->getElementsByTagName('img');
337
+ foreach ($images as $img)
338
+ {
339
+ if ($img->hasAttribute('src'))
340
+ {
341
+ $image_url = call_user_func($this->cache_name_function, $img->getAttribute('src'));
342
+ $cache = $this->registry->call('Cache', 'get_handler', array($this->cache_location, $image_url, 'spi'));
343
+
344
+ if ($cache->load())
345
+ {
346
+ $img->setAttribute('src', $this->image_handler . $image_url);
347
+ }
348
+ else
349
+ {
350
+ $file = $this->registry->create('File', array($img->getAttribute('src'), $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen));
351
+ $headers = $file->headers;
352
+
353
+ if ($file->success && ($file->method & SIMPLECLUVPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
354
+ {
355
+ if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
356
+ {
357
+ $img->setAttribute('src', $this->image_handler . $image_url);
358
+ }
359
+ else
360
+ {
361
+ trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+ }
368
+
369
+ // Finally, convert to a HTML string
370
+ $data = trim($document->saveHTML());
371
+ $result = explode($unique_tag, $data);
372
+ // The tags may not be found again if there was invalid markup.
373
+ $data = count($result) === 3 ? $result[1] : '';
374
+
375
+ if ($this->remove_div)
376
+ {
377
+ $data = preg_replace('/^<div' . SIMPLECLUVPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
378
+ $data = preg_replace('/<\/div>$/', '', $data);
379
+ }
380
+ else
381
+ {
382
+ $data = preg_replace('/^<div' . SIMPLECLUVPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
383
+ }
384
+ }
385
+
386
+ if ($type & SIMPLECLUVPIE_CONSTRUCT_IRI)
387
+ {
388
+ $absolute = $this->registry->call('Misc', 'absolutize_url', array($data, $base));
389
+ if ($absolute !== false)
390
+ {
391
+ $data = $absolute;
392
+ }
393
+ }
394
+
395
+ if ($type & (SIMPLECLUVPIE_CONSTRUCT_TEXT | SIMPLECLUVPIE_CONSTRUCT_IRI))
396
+ {
397
+ $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
398
+ }
399
+
400
+ if ($this->output_encoding !== 'UTF-8')
401
+ {
402
+ $data = $this->registry->call('Misc', 'change_encoding', array($data, 'UTF-8', $this->output_encoding));
403
+ }
404
+ }
405
+ return $data;
406
+ }
407
+
408
+ protected function preprocess($html, $type)
409
+ {
410
+ $ret = '';
411
+ $html = preg_replace('%</?(?:html|body)[^>]*?'.'>%is', '', $html);
412
+ if ($type & ~SIMPLECLUVPIE_CONSTRUCT_XHTML)
413
+ {
414
+ // Atom XHTML constructs are wrapped with a div by default
415
+ // Note: No protection if $html contains a stray </div>!
416
+ $html = '<div>' . $html . '</div>';
417
+ $ret .= '<!DOCTYPE html>';
418
+ $content_type = 'text/html';
419
+ }
420
+ else
421
+ {
422
+ $ret .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
423
+ $content_type = 'application/xhtml+xml';
424
+ }
425
+
426
+ $ret .= '<html><head>';
427
+ $ret .= '<meta http-equiv="Content-Type" content="' . $content_type . '; charset=utf-8" />';
428
+ $ret .= '</head><body>' . $html . '</body></html>';
429
+ return $ret;
430
+ }
431
+
432
+ public function replace_urls($document, $tag, $attributes)
433
+ {
434
+ if (!is_array($attributes))
435
+ {
436
+ $attributes = array($attributes);
437
+ }
438
+
439
+ if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
440
+ {
441
+ $elements = $document->getElementsByTagName($tag);
442
+ foreach ($elements as $element)
443
+ {
444
+ foreach ($attributes as $attribute)
445
+ {
446
+ if ($element->hasAttribute($attribute))
447
+ {
448
+ $value = $this->registry->call('Misc', 'absolutize_url', array($element->getAttribute($attribute), $this->base));
449
+ if ($value !== false)
450
+ {
451
+ $element->setAttribute($attribute, $value);
452
+ }
453
+ }
454
+ }
455
+ }
456
+ }
457
+ }
458
+
459
+ public function do_strip_htmltags($match)
460
+ {
461
+ if ($this->encode_instead_of_strip)
462
+ {
463
+ if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
464
+ {
465
+ $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
466
+ $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
467
+ return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
468
+ }
469
+ else
470
+ {
471
+ return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
472
+ }
473
+ }
474
+ elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
475
+ {
476
+ return $match[4];
477
+ }
478
+ else
479
+ {
480
+ return '';
481
+ }
482
+ }
483
+
484
+ protected function strip_tag($tag, $document, $xpath, $type)
485
+ {
486
+ $elements = $xpath->query('body//' . $tag);
487
+ if ($this->encode_instead_of_strip)
488
+ {
489
+ foreach ($elements as $element)
490
+ {
491
+ $fragment = $document->createDocumentFragment();
492
+
493
+ // For elements which aren't script or style, include the tag itself
494
+ if (!in_array($tag, array('script', 'style')))
495
+ {
496
+ $text = '<' . $tag;
497
+ if ($element->hasAttributes())
498
+ {
499
+ $attrs = array();
500
+ foreach ($element->attributes as $name => $attr)
501
+ {
502
+ $value = $attr->value;
503
+
504
+ // In XHTML, empty values should never exist, so we repeat the value
505
+ if (empty($value) && ($type & SIMPLECLUVPIE_CONSTRUCT_XHTML))
506
+ {
507
+ $value = $name;
508
+ }
509
+ // For HTML, empty is fine
510
+ elseif (empty($value) && ($type & SIMPLECLUVPIE_CONSTRUCT_HTML))
511
+ {
512
+ $attrs[] = $name;
513
+ continue;
514
+ }
515
+
516
+ // Standard attribute text
517
+ $attrs[] = $name . '="' . $attr->value . '"';
518
+ }
519
+ $text .= ' ' . implode(' ', $attrs);
520
+ }
521
+ $text .= '>';
522
+ $fragment->appendChild(new DOMText($text));
523
+ }
524
+
525
+ $number = $element->childNodes->length;
526
+ for ($i = $number; $i > 0; $i--)
527
+ {
528
+ $child = $element->childNodes->item(0);
529
+ $fragment->appendChild($child);
530
+ }
531
+
532
+ if (!in_array($tag, array('script', 'style')))
533
+ {
534
+ $fragment->appendChild(new DOMText('</' . $tag . '>'));
535
+ }
536
+
537
+ $element->parentNode->replaceChild($fragment, $element);
538
+ }
539
+
540
+ return;
541
+ }
542
+ elseif (in_array($tag, array('script', 'style')))
543
+ {
544
+ foreach ($elements as $element)
545
+ {
546
+ $element->parentNode->removeChild($element);
547
+ }
548
+
549
+ return;
550
+ }
551
+ else
552
+ {
553
+ foreach ($elements as $element)
554
+ {
555
+ $fragment = $document->createDocumentFragment();
556
+ $number = $element->childNodes->length;
557
+ for ($i = $number; $i > 0; $i--)
558
+ {
559
+ $child = $element->childNodes->item(0);
560
+ $fragment->appendChild($child);
561
+ }
562
+
563
+ $element->parentNode->replaceChild($fragment, $element);
564
+ }
565
+ }
566
+ }
567
+
568
+ protected function strip_attr($attrib, $xpath)
569
+ {
570
+ $elements = $xpath->query('//*[@' . $attrib . ']');
571
+
572
+ foreach ($elements as $element)
573
+ {
574
+ $element->removeAttribute($attrib);
575
+ }
576
+ }
577
+
578
+ protected function add_attr($tag, $valuePairs, $document)
579
+ {
580
+ $elements = $document->getElementsByTagName($tag);
581
+ foreach ($elements as $element)
582
+ {
583
+ foreach ($valuePairs as $attrib => $value)
584
+ {
585
+ $element->setAttribute($attrib, $value);
586
+ }
587
+ }
588
+ }
589
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/Source.php ADDED
@@ -0,0 +1,610 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+ /**
45
+ * Handles `<atom:source>`
46
+ *
47
+ * Used by {@see SimpleCluvPie_Item::get_source()}
48
+ *
49
+ * This class can be overloaded with {@see SimpleCluvPie::set_source_class()}
50
+ *
51
+ * @package SimpleCluvPie
52
+ * @subpackage API
53
+ */
54
+ class SimpleCluvPie_Source
55
+ {
56
+ var $item;
57
+ var $data = array();
58
+ protected $registry;
59
+
60
+ public function __construct($item, $data)
61
+ {
62
+ $this->item = $item;
63
+ $this->data = $data;
64
+ }
65
+
66
+ public function set_registry(SimpleCluvPie_Registry $registry)
67
+ {
68
+ $this->registry = $registry;
69
+ }
70
+
71
+ public function __toString()
72
+ {
73
+ return md5(serialize($this->data));
74
+ }
75
+
76
+ public function get_source_tags($namespace, $tag)
77
+ {
78
+ if (isset($this->data['child'][$namespace][$tag]))
79
+ {
80
+ return $this->data['child'][$namespace][$tag];
81
+ }
82
+ else
83
+ {
84
+ return null;
85
+ }
86
+ }
87
+
88
+ public function get_base($element = array())
89
+ {
90
+ return $this->item->get_base($element);
91
+ }
92
+
93
+ public function sanitize($data, $type, $base = '')
94
+ {
95
+ return $this->item->sanitize($data, $type, $base);
96
+ }
97
+
98
+ public function get_item()
99
+ {
100
+ return $this->item;
101
+ }
102
+
103
+ public function get_title()
104
+ {
105
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'title'))
106
+ {
107
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
108
+ }
109
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'title'))
110
+ {
111
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
112
+ }
113
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'title'))
114
+ {
115
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
116
+ }
117
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'title'))
118
+ {
119
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
120
+ }
121
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'title'))
122
+ {
123
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
124
+ }
125
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'title'))
126
+ {
127
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
128
+ }
129
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'title'))
130
+ {
131
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
132
+ }
133
+ else
134
+ {
135
+ return null;
136
+ }
137
+ }
138
+
139
+ public function get_category($key = 0)
140
+ {
141
+ $categories = $this->get_categories();
142
+ if (isset($categories[$key]))
143
+ {
144
+ return $categories[$key];
145
+ }
146
+ else
147
+ {
148
+ return null;
149
+ }
150
+ }
151
+
152
+ public function get_categories()
153
+ {
154
+ $categories = array();
155
+
156
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'category') as $category)
157
+ {
158
+ $term = null;
159
+ $scheme = null;
160
+ $label = null;
161
+ if (isset($category['attribs']['']['term']))
162
+ {
163
+ $term = $this->sanitize($category['attribs']['']['term'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
164
+ }
165
+ if (isset($category['attribs']['']['scheme']))
166
+ {
167
+ $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
168
+ }
169
+ if (isset($category['attribs']['']['label']))
170
+ {
171
+ $label = $this->sanitize($category['attribs']['']['label'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
172
+ }
173
+ $categories[] = $this->registry->create('Category', array($term, $scheme, $label));
174
+ }
175
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'category') as $category)
176
+ {
177
+ // This is really the label, but keep this as the term also for BC.
178
+ // Label will also work on retrieving because that falls back to term.
179
+ $term = $this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
180
+ if (isset($category['attribs']['']['domain']))
181
+ {
182
+ $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
183
+ }
184
+ else
185
+ {
186
+ $scheme = null;
187
+ }
188
+ $categories[] = $this->registry->create('Category', array($term, $scheme, null));
189
+ }
190
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'subject') as $category)
191
+ {
192
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
193
+ }
194
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'subject') as $category)
195
+ {
196
+ $categories[] = $this->registry->create('Category', array($this->sanitize($category['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
197
+ }
198
+
199
+ if (!empty($categories))
200
+ {
201
+ return array_unique($categories);
202
+ }
203
+ else
204
+ {
205
+ return null;
206
+ }
207
+ }
208
+
209
+ public function get_author($key = 0)
210
+ {
211
+ $authors = $this->get_authors();
212
+ if (isset($authors[$key]))
213
+ {
214
+ return $authors[$key];
215
+ }
216
+ else
217
+ {
218
+ return null;
219
+ }
220
+ }
221
+
222
+ public function get_authors()
223
+ {
224
+ $authors = array();
225
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'author') as $author)
226
+ {
227
+ $name = null;
228
+ $uri = null;
229
+ $email = null;
230
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
231
+ {
232
+ $name = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
233
+ }
234
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
235
+ {
236
+ $uri = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
237
+ }
238
+ if (isset($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
239
+ {
240
+ $email = $this->sanitize($author['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
241
+ }
242
+ if ($name !== null || $email !== null || $uri !== null)
243
+ {
244
+ $authors[] = $this->registry->create('Author', array($name, $uri, $email));
245
+ }
246
+ }
247
+ if ($author = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'author'))
248
+ {
249
+ $name = null;
250
+ $url = null;
251
+ $email = null;
252
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
253
+ {
254
+ $name = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
255
+ }
256
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
257
+ {
258
+ $url = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
259
+ }
260
+ if (isset($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
261
+ {
262
+ $email = $this->sanitize($author[0]['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
263
+ }
264
+ if ($name !== null || $email !== null || $url !== null)
265
+ {
266
+ $authors[] = $this->registry->create('Author', array($name, $url, $email));
267
+ }
268
+ }
269
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'creator') as $author)
270
+ {
271
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
272
+ }
273
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'creator') as $author)
274
+ {
275
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
276
+ }
277
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'author') as $author)
278
+ {
279
+ $authors[] = $this->registry->create('Author', array($this->sanitize($author['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT), null, null));
280
+ }
281
+
282
+ if (!empty($authors))
283
+ {
284
+ return array_unique($authors);
285
+ }
286
+ else
287
+ {
288
+ return null;
289
+ }
290
+ }
291
+
292
+ public function get_contributor($key = 0)
293
+ {
294
+ $contributors = $this->get_contributors();
295
+ if (isset($contributors[$key]))
296
+ {
297
+ return $contributors[$key];
298
+ }
299
+ else
300
+ {
301
+ return null;
302
+ }
303
+ }
304
+
305
+ public function get_contributors()
306
+ {
307
+ $contributors = array();
308
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
309
+ {
310
+ $name = null;
311
+ $uri = null;
312
+ $email = null;
313
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
314
+ {
315
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
316
+ }
317
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
318
+ {
319
+ $uri = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['uri'][0]));
320
+ }
321
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
322
+ {
323
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
324
+ }
325
+ if ($name !== null || $email !== null || $uri !== null)
326
+ {
327
+ $contributors[] = $this->registry->create('Author', array($name, $uri, $email));
328
+ }
329
+ }
330
+ foreach ((array) $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
331
+ {
332
+ $name = null;
333
+ $url = null;
334
+ $email = null;
335
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
336
+ {
337
+ $name = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
338
+ }
339
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
340
+ {
341
+ $url = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['url'][0]));
342
+ }
343
+ if (isset($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
344
+ {
345
+ $email = $this->sanitize($contributor['child'][SIMPLECLUVPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
346
+ }
347
+ if ($name !== null || $email !== null || $url !== null)
348
+ {
349
+ $contributors[] = $this->registry->create('Author', array($name, $url, $email));
350
+ }
351
+ }
352
+
353
+ if (!empty($contributors))
354
+ {
355
+ return array_unique($contributors);
356
+ }
357
+ else
358
+ {
359
+ return null;
360
+ }
361
+ }
362
+
363
+ public function get_link($key = 0, $rel = 'alternate')
364
+ {
365
+ $links = $this->get_links($rel);
366
+ if (isset($links[$key]))
367
+ {
368
+ return $links[$key];
369
+ }
370
+ else
371
+ {
372
+ return null;
373
+ }
374
+ }
375
+
376
+ /**
377
+ * Added for parity between the parent-level and the item/entry-level.
378
+ */
379
+ public function get_permalink()
380
+ {
381
+ return $this->get_link(0);
382
+ }
383
+
384
+ public function get_links($rel = 'alternate')
385
+ {
386
+ if (!isset($this->data['links']))
387
+ {
388
+ $this->data['links'] = array();
389
+ if ($links = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'link'))
390
+ {
391
+ foreach ($links as $link)
392
+ {
393
+ if (isset($link['attribs']['']['href']))
394
+ {
395
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
396
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
397
+ }
398
+ }
399
+ }
400
+ if ($links = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'link'))
401
+ {
402
+ foreach ($links as $link)
403
+ {
404
+ if (isset($link['attribs']['']['href']))
405
+ {
406
+ $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
407
+ $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($link));
408
+
409
+ }
410
+ }
411
+ }
412
+ if ($links = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'link'))
413
+ {
414
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
415
+ }
416
+ if ($links = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'link'))
417
+ {
418
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
419
+ }
420
+ if ($links = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'link'))
421
+ {
422
+ $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
423
+ }
424
+
425
+ $keys = array_keys($this->data['links']);
426
+ foreach ($keys as $key)
427
+ {
428
+ if ($this->registry->call('Misc', 'is_isegment_nz_nc', array($key)))
429
+ {
430
+ if (isset($this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
431
+ {
432
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
433
+ $this->data['links'][$key] =& $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
434
+ }
435
+ else
436
+ {
437
+ $this->data['links'][SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
438
+ }
439
+ }
440
+ elseif (substr($key, 0, 41) === SIMPLECLUVPIE_IANA_LINK_RELATIONS_REGISTRY)
441
+ {
442
+ $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
443
+ }
444
+ $this->data['links'][$key] = array_unique($this->data['links'][$key]);
445
+ }
446
+ }
447
+
448
+ if (isset($this->data['links'][$rel]))
449
+ {
450
+ return $this->data['links'][$rel];
451
+ }
452
+ else
453
+ {
454
+ return null;
455
+ }
456
+ }
457
+
458
+ public function get_description()
459
+ {
460
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'subtitle'))
461
+ {
462
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
463
+ }
464
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'tagline'))
465
+ {
466
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
467
+ }
468
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_10, 'description'))
469
+ {
470
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
471
+ }
472
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_090, 'description'))
473
+ {
474
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
475
+ }
476
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'description'))
477
+ {
478
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
479
+ }
480
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'description'))
481
+ {
482
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
483
+ }
484
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'description'))
485
+ {
486
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
487
+ }
488
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'summary'))
489
+ {
490
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
491
+ }
492
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'subtitle'))
493
+ {
494
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
495
+ }
496
+ else
497
+ {
498
+ return null;
499
+ }
500
+ }
501
+
502
+ public function get_copyright()
503
+ {
504
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'rights'))
505
+ {
506
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_10_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
507
+ }
508
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_03, 'copyright'))
509
+ {
510
+ return $this->sanitize($return[0]['data'], $this->registry->call('Misc', 'atom_03_construct_type', array($return[0]['attribs'])), $this->get_base($return[0]));
511
+ }
512
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'copyright'))
513
+ {
514
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
515
+ }
516
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'rights'))
517
+ {
518
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
519
+ }
520
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'rights'))
521
+ {
522
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
523
+ }
524
+ else
525
+ {
526
+ return null;
527
+ }
528
+ }
529
+
530
+ public function get_language()
531
+ {
532
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_RSS_20, 'language'))
533
+ {
534
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
535
+ }
536
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_11, 'language'))
537
+ {
538
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
539
+ }
540
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_DC_10, 'language'))
541
+ {
542
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
543
+ }
544
+ elseif (isset($this->data['xml_lang']))
545
+ {
546
+ return $this->sanitize($this->data['xml_lang'], SIMPLECLUVPIE_CONSTRUCT_TEXT);
547
+ }
548
+ else
549
+ {
550
+ return null;
551
+ }
552
+ }
553
+
554
+ public function get_latitude()
555
+ {
556
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
557
+ {
558
+ return (float) $return[0]['data'];
559
+ }
560
+ elseif (($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
561
+ {
562
+ return (float) $match[1];
563
+ }
564
+ else
565
+ {
566
+ return null;
567
+ }
568
+ }
569
+
570
+ public function get_longitude()
571
+ {
572
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
573
+ {
574
+ return (float) $return[0]['data'];
575
+ }
576
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
577
+ {
578
+ return (float) $return[0]['data'];
579
+ }
580
+ elseif (($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
581
+ {
582
+ return (float) $match[2];
583
+ }
584
+ else
585
+ {
586
+ return null;
587
+ }
588
+ }
589
+
590
+ public function get_image_url()
591
+ {
592
+ if ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ITUNES, 'image'))
593
+ {
594
+ return $this->sanitize($return[0]['attribs']['']['href'], SIMPLECLUVPIE_CONSTRUCT_IRI);
595
+ }
596
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'logo'))
597
+ {
598
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
599
+ }
600
+ elseif ($return = $this->get_source_tags(SIMPLECLUVPIE_NAMESPACE_ATOM_10, 'icon'))
601
+ {
602
+ return $this->sanitize($return[0]['data'], SIMPLECLUVPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
603
+ }
604
+ else
605
+ {
606
+ return null;
607
+ }
608
+ }
609
+ }
610
+
libs/SimpleCluvPie/library/SimpleCluvPie/XML/Declaration/Parser.php ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Parses the XML Declaration
47
+ *
48
+ * @package SimpleCluvPie
49
+ * @subpackage Parsing
50
+ */
51
+ class SimpleCluvPie_XML_Declaration_Parser
52
+ {
53
+ /**
54
+ * XML Version
55
+ *
56
+ * @access public
57
+ * @var string
58
+ */
59
+ var $version = '1.0';
60
+
61
+ /**
62
+ * Encoding
63
+ *
64
+ * @access public
65
+ * @var string
66
+ */
67
+ var $encoding = 'UTF-8';
68
+
69
+ /**
70
+ * Standalone
71
+ *
72
+ * @access public
73
+ * @var bool
74
+ */
75
+ var $standalone = false;
76
+
77
+ /**
78
+ * Current state of the state machine
79
+ *
80
+ * @access private
81
+ * @var string
82
+ */
83
+ var $state = 'before_version_name';
84
+
85
+ /**
86
+ * Input data
87
+ *
88
+ * @access private
89
+ * @var string
90
+ */
91
+ var $data = '';
92
+
93
+ /**
94
+ * Input data length (to avoid calling strlen() everytime this is needed)
95
+ *
96
+ * @access private
97
+ * @var int
98
+ */
99
+ var $data_length = 0;
100
+
101
+ /**
102
+ * Current position of the pointer
103
+ *
104
+ * @var int
105
+ * @access private
106
+ */
107
+ var $position = 0;
108
+
109
+ /**
110
+ * Create an instance of the class with the input data
111
+ *
112
+ * @access public
113
+ * @param string $data Input data
114
+ */
115
+ public function __construct($data)
116
+ {
117
+ $this->data = $data;
118
+ $this->data_length = strlen($this->data);
119
+ }
120
+
121
+ /**
122
+ * Parse the input data
123
+ *
124
+ * @access public
125
+ * @return bool true on success, false on failure
126
+ */
127
+ public function parse()
128
+ {
129
+ while ($this->state && $this->state !== 'emit' && $this->has_data())
130
+ {
131
+ $state = $this->state;
132
+ $this->$state();
133
+ }
134
+ $this->data = '';
135
+ if ($this->state === 'emit')
136
+ {
137
+ return true;
138
+ }
139
+ else
140
+ {
141
+ $this->version = '';
142
+ $this->encoding = '';
143
+ $this->standalone = '';
144
+ return false;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Check whether there is data beyond the pointer
150
+ *
151
+ * @access private
152
+ * @return bool true if there is further data, false if not
153
+ */
154
+ public function has_data()
155
+ {
156
+ return (bool) ($this->position < $this->data_length);
157
+ }
158
+
159
+ /**
160
+ * Advance past any whitespace
161
+ *
162
+ * @return int Number of whitespace characters passed
163
+ */
164
+ public function skip_whitespace()
165
+ {
166
+ $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
167
+ $this->position += $whitespace;
168
+ return $whitespace;
169
+ }
170
+
171
+ /**
172
+ * Read value
173
+ */
174
+ public function get_value()
175
+ {
176
+ $quote = substr($this->data, $this->position, 1);
177
+ if ($quote === '"' || $quote === "'")
178
+ {
179
+ $this->position++;
180
+ $len = strcspn($this->data, $quote, $this->position);
181
+ if ($this->has_data())
182
+ {
183
+ $value = substr($this->data, $this->position, $len);
184
+ $this->position += $len + 1;
185
+ return $value;
186
+ }
187
+ }
188
+ return false;
189
+ }
190
+
191
+ public function before_version_name()
192
+ {
193
+ if ($this->skip_whitespace())
194
+ {
195
+ $this->state = 'version_name';
196
+ }
197
+ else
198
+ {
199
+ $this->state = false;
200
+ }
201
+ }
202
+
203
+ public function version_name()
204
+ {
205
+ if (substr($this->data, $this->position, 7) === 'version')
206
+ {
207
+ $this->position += 7;
208
+ $this->skip_whitespace();
209
+ $this->state = 'version_equals';
210
+ }
211
+ else
212
+ {
213
+ $this->state = false;
214
+ }
215
+ }
216
+
217
+ public function version_equals()
218
+ {
219
+ if (substr($this->data, $this->position, 1) === '=')
220
+ {
221
+ $this->position++;
222
+ $this->skip_whitespace();
223
+ $this->state = 'version_value';
224
+ }
225
+ else
226
+ {
227
+ $this->state = false;
228
+ }
229
+ }
230
+
231
+ public function version_value()
232
+ {
233
+ if ($this->version = $this->get_value())
234
+ {
235
+ $this->skip_whitespace();
236
+ if ($this->has_data())
237
+ {
238
+ $this->state = 'encoding_name';
239
+ }
240
+ else
241
+ {
242
+ $this->state = 'emit';
243
+ }
244
+ }
245
+ else
246
+ {
247
+ $this->state = false;
248
+ }
249
+ }
250
+
251
+ public function encoding_name()
252
+ {
253
+ if (substr($this->data, $this->position, 8) === 'encoding')
254
+ {
255
+ $this->position += 8;
256
+ $this->skip_whitespace();
257
+ $this->state = 'encoding_equals';
258
+ }
259
+ else
260
+ {
261
+ $this->state = 'standalone_name';
262
+ }
263
+ }
264
+
265
+ public function encoding_equals()
266
+ {
267
+ if (substr($this->data, $this->position, 1) === '=')
268
+ {
269
+ $this->position++;
270
+ $this->skip_whitespace();
271
+ $this->state = 'encoding_value';
272
+ }
273
+ else
274
+ {
275
+ $this->state = false;
276
+ }
277
+ }
278
+
279
+ public function encoding_value()
280
+ {
281
+ if ($this->encoding = $this->get_value())
282
+ {
283
+ $this->skip_whitespace();
284
+ if ($this->has_data())
285
+ {
286
+ $this->state = 'standalone_name';
287
+ }
288
+ else
289
+ {
290
+ $this->state = 'emit';
291
+ }
292
+ }
293
+ else
294
+ {
295
+ $this->state = false;
296
+ }
297
+ }
298
+
299
+ public function standalone_name()
300
+ {
301
+ if (substr($this->data, $this->position, 10) === 'standalone')
302
+ {
303
+ $this->position += 10;
304
+ $this->skip_whitespace();
305
+ $this->state = 'standalone_equals';
306
+ }
307
+ else
308
+ {
309
+ $this->state = false;
310
+ }
311
+ }
312
+
313
+ public function standalone_equals()
314
+ {
315
+ if (substr($this->data, $this->position, 1) === '=')
316
+ {
317
+ $this->position++;
318
+ $this->skip_whitespace();
319
+ $this->state = 'standalone_value';
320
+ }
321
+ else
322
+ {
323
+ $this->state = false;
324
+ }
325
+ }
326
+
327
+ public function standalone_value()
328
+ {
329
+ if ($standalone = $this->get_value())
330
+ {
331
+ switch ($standalone)
332
+ {
333
+ case 'yes':
334
+ $this->standalone = true;
335
+ break;
336
+
337
+ case 'no':
338
+ $this->standalone = false;
339
+ break;
340
+
341
+ default:
342
+ $this->state = false;
343
+ return;
344
+ }
345
+
346
+ $this->skip_whitespace();
347
+ if ($this->has_data())
348
+ {
349
+ $this->state = false;
350
+ }
351
+ else
352
+ {
353
+ $this->state = 'emit';
354
+ }
355
+ }
356
+ else
357
+ {
358
+ $this->state = false;
359
+ }
360
+ }
361
+ }
libs/SimpleCluvPie/library/SimpleCluvPie/gzdecode.php ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * SimpleCluvPie
4
+ *
5
+ * A PHP-Based RSS and Atom Feed Framework.
6
+ * Takes the hard work out of managing a complete RSS/Atom solution.
7
+ *
8
+ * Copyright (c) 2004-2016, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
9
+ * All rights reserved.
10
+ *
11
+ * Redistribution and use in source and binary forms, with or without modification, are
12
+ * permitted provided that the following conditions are met:
13
+ *
14
+ * * Redistributions of source code must retain the above copyright notice, this list of
15
+ * conditions and the following disclaimer.
16
+ *
17
+ * * Redistributions in binary form must reproduce the above copyright notice, this list
18
+ * of conditions and the following disclaimer in the documentation and/or other materials
19
+ * provided with the distribution.
20
+ *
21
+ * * Neither the name of the SimpleCluvPie Team nor the names of its contributors may be used
22
+ * to endorse or promote products derived from this software without specific prior
23
+ * written permission.
24
+ *
25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
26
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
28
+ * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
32
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33
+ * POSSIBILITY OF SUCH DAMAGE.
34
+ *
35
+ * @package SimpleCluvPie
36
+ * @copyright 2004-2016 Ryan Parman, Geoffrey Sneddon, Ryan McCue
37
+ * @author Ryan Parman
38
+ * @author Geoffrey Sneddon
39
+ * @author Ryan McCue
40
+ * @link http://simplecluvpie.org/ SimpleCluvPie
41
+ * @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
+ */
43
+
44
+
45
+ /**
46
+ * Decode 'gzip' encoded HTTP data
47
+ *
48
+ * @package SimpleCluvPie
49
+ * @subpackage HTTP
50
+ * @link http://www.gzip.org/format.txt
51
+ */
52
+ class SimpleCluvPie_gzdecode
53
+ {
54
+ /**
55
+ * Compressed data
56
+ *
57
+ * @access private
58
+ * @var string
59
+ * @see gzdecode::$data
60
+ */
61
+ var $compressed_data;
62
+
63
+ /**
64
+ * Size of compressed data
65
+ *
66
+ * @access private
67
+ * @var int
68
+ */
69
+ var $compressed_size;
70
+
71
+ /**
72
+ * Minimum size of a valid gzip string
73
+ *
74
+ * @access private
75
+ * @var int
76
+ */
77
+ var $min_compressed_size = 18;
78
+
79
+ /**
80
+ * Current position of pointer
81
+ *
82
+ * @access private
83
+ * @var int
84
+ */
85
+ var $position = 0;
86
+
87
+ /**
88
+ * Flags (FLG)
89
+ *
90
+ * @access private
91
+ * @var int
92
+ */
93
+ var $flags;
94
+
95
+ /**
96
+ * Uncompressed data
97
+ *
98
+ * @access public
99
+ * @see gzdecode::$compressed_data
100
+ * @var string
101
+ */
102
+ var $data;
103
+
104
+ /**
105
+ * Modified time
106
+ *
107
+ * @access public
108
+ * @var int
109
+ */
110
+ var $MTIME;
111
+
112
+ /**
113
+ * Extra Flags
114
+ *
115
+ * @access public
116
+ * @var int
117
+ */
118
+ var $XFL;
119
+
120
+ /**
121
+ * Operating System
122
+ *
123
+ * @access public
124
+ * @var int
125
+ */
126
+ var $OS;
127
+
128
+ /**
129
+ * Subfield ID 1
130
+ *
131
+ * @access public
132
+ * @see gzdecode::$extra_field
133
+ * @see gzdecode::$SI2
134
+ * @var string
135
+ */
136
+ var $SI1;
137
+
138
+ /**
139
+ * Subfield ID 2
140
+ *
141
+ * @access public
142
+ * @see gzdecode::$extra_field
143
+ * @see gzdecode::$SI1
144
+ * @var string
145
+ */
146
+ var $SI2;
147
+
148
+ /**
149
+ * Extra field content
150
+ *
151
+ * @access public
152
+ * @see gzdecode::$SI1
153
+ * @see gzdecode::$SI2
154
+ * @var string
155
+ */
156
+ var $extra_field;
157
+
158
+ /**
159
+ * Original filename
160
+ *
161
+ * @access public
162
+ * @var string
163
+ */
164
+ var $filename;
165
+
166
+ /**
167
+ * Human readable comment
168
+ *
169
+ * @access public
170
+ * @var string
171
+ */
172
+ var $comment;
173
+
174
+ /**
175
+ * Don't allow anything to be set
176
+ *
177
+ * @param string $name
178
+ * @param mixed $value
179
+ */
180
+ public function __set($name, $value)
181
+ {
182
+ trigger_error("Cannot write property $name", E_USER_ERROR);
183
+ }
184
+
185
+ /**
186
+ * Set the compressed string and related properties
187
+ *
188
+ * @param string $data
189
+ */
190
+ public function __construct($data)
191
+ {
192
+ $this->compressed_data = $data;
193
+ $this->compressed_size = strlen($data);
194
+ }
195
+
196
+ /**
197
+ * Decode the GZIP stream
198
+ *
199
+ * @return bool Successfulness
200
+ */
201
+ public function parse()
202
+ {
203
+ if ($this->compressed_size >= $this->min_compressed_size)
204
+ {
205
+ // Check ID1, ID2, and CM
206
+ if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
207
+ {
208
+ return false;
209
+ }
210
+
211
+ // Get the FLG (FLaGs)
212
+ $this->flags = ord($this->compressed_data[3]);
213
+
214
+ // FLG bits above (1 << 4) are reserved
215
+ if ($this->flags > 0x1F)
216
+ {
217
+ return false;
218
+ }
219
+
220
+ // Advance the pointer after the above
221
+ $this->position += 4;
222
+
223
+ // MTIME
224
+ $mtime = substr($this->compressed_data, $this->position, 4);
225
+ // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
226
+ if (current(unpack('S', "\x00\x01")) === 1)
227
+ {
228
+ $mtime = strrev($mtime);
229
+ }
230
+ $this->MTIME = current(unpack('l', $mtime));
231
+ $this->position += 4;
232
+
233
+ // Get the XFL (eXtra FLags)
234
+ $this->XFL = ord($this->compressed_data[$this->position++]);
235
+
236
+ // Get the OS (Operating System)
237
+ $this->OS = ord($this->compressed_data[$this->position++]);
238
+
239
+ // Parse the FEXTRA
240
+ if ($this->flags & 4)
241
+ {
242
+ // Read subfield IDs
243
+ $this->SI1 = $this->compressed_data[$this->position++];
244
+ $this->SI2 = $this->compressed_data[$this->position++];
245
+
246
+ // SI2 set to zero is reserved for future use
247
+ if ($this->SI2 === "\x00")
248
+ {
249
+ return false;
250
+ }
251
+
252
+ // Get the length of the extra field
253
+ $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
254
+ $this->position += 2;
255
+
256
+ // Check the length of the string is still valid
257
+ $this->min_compressed_size += $len + 4;
258
+ if ($this->compressed_size >= $this->min_compressed_size)
259
+ {
260
+ // Set the extra field to the given data
261
+ $this->extra_field = substr($this->compressed_data, $this->position, $len);
262
+ $this->position += $len;
263
+ }
264
+ else
265
+ {
266
+ return false;
267
+ }
268
+ }
269
+
270
+ // Parse the FNAME
271
+ if ($this->flags & 8)
272
+ {
273
+ // Get the length of the filename
274
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
275
+
276
+ // Check the length of the string is still valid
277
+ $this->min_compressed_size += $len + 1;
278
+ if ($this->compressed_size >= $this->min_compressed_size)
279
+ {
280
+ // Set the original filename to the given string
281
+ $this->filename = substr($this->compressed_data, $this->position, $len);
282
+ $this->position += $len + 1;
283
+ }
284
+ else
285
+ {
286
+ return false;
287
+ }
288
+ }
289
+
290
+ // Parse the FCOMMENT
291
+ if ($this->flags & 16)
292
+ {
293
+ // Get the length of the comment
294
+ $len = strcspn($this->compressed_data, "\x00", $this->position);
295
+
296
+ // Check the length of the string is still valid
297
+ $this->min_compressed_size += $len + 1;
298
+ if ($this->compressed_size >= $this->min_compressed_size)
299
+ {
300
+ // Set the original comment to the given string
301
+ $this->comment = substr($this->compressed_data, $this->position, $len);
302
+ $this->position += $len + 1;
303
+ }
304
+ else
305
+ {
306
+ return false;
307
+ }
308
+ }
309
+
310
+ // Parse the FHCRC
311
+ if ($this->flags & 2)
312
+ {
313
+ // Check the length of the string is still valid
314
+ $this->min_compressed_size += $len + 2;
315
+ if ($this->compressed_size >= $this->min_compressed_size)
316
+ {
317
+ // Read the CRC
318
+ $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
319
+
320
+ // Check the CRC matches
321
+ if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
322
+ {
323
+ $this->position += 2;
324
+ }
325
+ else
326
+ {
327
+ return false;
328
+ }
329
+ }
330
+ else
331
+ {
332
+ return false;
333
+ }
334
+ }
335
+
336
+ // Decompress the actual data
337
+ if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
338
+ {
339
+ return false;
340
+ }
341
+ else
342
+ {
343
+ $this->position = $this->compressed_size - 8;
344
+ }
345
+
346
+ // Check CRC of data
347
+ $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
348
+ $this->position += 4;
349
+ /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
350
+ {
351
+ return false;
352
+ }*/
353
+
354
+ // Check ISIZE of data
355
+ $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
356
+ $this->position += 4;
357
+ if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
358
+ {
359
+ return false;
360
+ }
361
+
362
+ // Wow, against all odds, we've actually got a valid gzip string
363
+ return true;
364
+ }
365
+ else
366
+ {
367
+ return false;
368
+ }
369
+ }
370
+ }
readme.txt CHANGED
@@ -1,536 +1,545 @@
1
- === CommentLuv ===
2
- Contributors: commentluv,bompus
3
- Donate link:http://comluv.com/about/donate
4
- Tags: commentluv, comments, last blog post, linkluv, comment luv , commentlove, comment love
5
- Requires at least: 3.6
6
- Tested up to: 4.5.1
7
- Stable tag: 2.94.7
8
-
9
- Reward your readers by automatically placing a link to their last blog post at the end of their comment. Encourage a community and discover new posts.
10
-
11
- == Description ==
12
-
13
- [Upgrade to CommentLuv Pro](http://www.commentluv.com "Upgrade to CommentLuv Pro")
14
-
15
- CommentLuv Pro has even more amazing features that can bring even more traffic and comments to your blog by giving you the ability to fight spam, add keywords, integrate twitterlink, add a top commentators widget, social enticements and by having it installed on your site, you get advanced backlink features on EVERY CommentLuv blog when you comment (there are 10's of thousands of CommentLuv blogs)
16
-
17
- **New**
18
- Get a free 10 week blogging course, premium content with no charge at all. See why I'm giving this away on the first email, click the button in the settings page to start your course (and find out why I'm giving it away)
19
-
20
- [About](http://www.commentluv.com/get-more-comments-and-traffic-with-commentluv-premium/ "About") | [Features](http://www.commentluv.com "Features") | [Pricing](http://www.commentluv.com "Pricing")
21
-
22
- This plugin will visit the site of the comment author while they type their comment and retrieve their last blog posts which they can choose to include at the bottom of their comment when they click submit.
23
-
24
- It has been found to increase comments and the community spirit for the thousands of blogs that have installed it. With a simple install you will immediately start to find new and interesting blog posts from your own blog and community. You will even be able to build your list/network/community even more by offering your readers the opportunity to register to your site to unlock advanced features of the plugin like being able to choose from any of their 10 last posts when they comment or other features like dofollow links and more.
25
-
26
- The plugin requires WP or WP MS version of at least 3.0 and will work with administrators and logged on users provided they have their homepage url set in their profile page in the dashboard of the site.
27
-
28
- You can get a free companion plugin at http://www.commentluv.com
29
-
30
- [youtube http://www.youtube.com/watch?v=7wod9ZtiHaU]
31
-
32
- Now with updated function to allow you to delete or spam comments where the user has removed their url after getting a last blog post link (helps prevents spammer abuse)
33
-
34
- NOTE!
35
-
36
- The links that CommentLuv adds are valuable for the people that leave comments so you will need to make sure that spammers do not try to take advantage of your blog by filling it with useless comments just to get a link. Be a good blogger and prevent them from leaving their crap on your site by requiring moderation on first comments and do not accept 'great post thanks!' type of comments.
37
-
38
- There has been great success in beating spam by installing [G.A.S.P](http://wordpress.org/plugins/growmap-anti-spambot-plugin/ "Growmap Anti Spambot Plugin") . It will bring your blog back under your control and it's free!
39
-
40
- remember.. if you let anyone comment on your blog without restriction then you WILL get spammed whether you have CommentLuv or not. Be strict with your comment policy and be take responsibility for your own blog by being selective with the comments you accept and the internet will be a happier, spam free and useful place again! :-)
41
-
42
- Many thanks to the following who provided translations
43
-
44
- Italian [Gianni Diuno](http://gidibao.net/ "Italian translation")
45
- Polish [Mariusz Kolacz](http://techformator.pl/ "Polish translation")
46
- Lithuanian [Mantas Malcius](http://mantas.malcius.lt/ "Lithuanian translation")
47
- Georgian [Kasia Ciszewski](http://www.findmyhosting.com/ "Lithuanian translation")
48
- Dutch [Rene](http://wpwebshop.com/ "Dutch translation")
49
- Portuguese (BR) [Diego Uczak](http://www.korvo.com.br/ "Portuguese Translation")
50
- Malaysian [Ariff](http://ariffshah.com/ "Malaysian Translation")
51
- Hindi [Outshine Solutions](http://outshinesolutions.com/ "Hindi Translation")
52
- Indonesian [Mokhamad Oky](http://rainerflame.com/ "Indonesian Translation")
53
- Chinese (simplified) [Third Eye](http://obugs.net "Simplified Chinese Translation")
54
- Spanish [Valentin Yonte](http://www.activosenred.com/ "Spanish Translation")
55
- German [Jan Ruehling](http://www.cloudliving.de/ "German Translation")
56
- Persian [Amir Heydari](http://www.3eo.ir/ "Persian Translation")
57
- Tamil [Tharun](http://technostreak.com/ "Tamil Translation")
58
- Ukranian [Alyona Lompar](http://www.designcontest.com/ "Ukranian Translation")
59
- Latvian [Edgars Bergs](http://www.yourwebagency.co.uk/ "Latvian Translation")
60
- Romanian [Manuel Cheta](http://obisnuit.eu/ "Romanian Translation")
61
- Norwegian [Hanna](http://www.drommeland.com/ "Norwegian Translation")
62
- French [Jean-Luc Matthys](http://etreheureux.fr/ "French Translation")
63
- Danish [Jimmy Sigenstroem](http://w3blog.dk/ "Danish Translation")
64
- Russian [Max](http://lavo4nik.ru/ "Russian Translation")
65
- Bengali [Amrik Virdi](http://www.techmoody.com "Bengali Translation")
66
- Hebrew [Tobi](http://makemoneyim.com/ "Hebrew Translation")
67
- Vietnamese [Xman](http://thegioimanguon.com "Vietnamese Translation")
68
- Hungarian [Bruno](http://no1tutorials.net/ "Hungarian Translation")
69
- Slovak [Branco Radenovich](http://webhostinggeeks.com/blog/ "Slovak Translation")
70
- Serbian [Diana](http://wpcouponshop.com/ "Serbian Translation")
71
- Turkish [Hakan](http://hakanertr.wordpress.com/ "Turkish Translation")
72
- Swahili [Andrew Mwaniki](http://purehcgdietdrops.com/blog/ "Swahili Translation")
73
-
74
- == Installation ==
75
-
76
- Wordpress : Extract the zip file and just drop the contents in the wp-content/plugins/ directory of your WordPress installation and then activate the Plugin from Plugins page or visit the plugins page in your dashboard, click 'add new' and search for 'commentluv'
77
-
78
- If you're upgrading from an older version, please use the 'reset to default settings' button.
79
-
80
- == Frequently Asked Questions ==
81
-
82
- = Does this plugin add any database tables? =
83
-
84
- No. The link and associated data is saved to the comment meta table
85
-
86
- = My comments form does not show the name and url fields, just the textarea
87
-
88
- Make sure you log out of your blog and view the form as a user would. A logged in user does not see the name, email and url fields because your blog already knows them.
89
-
90
- = My comment replies are not showing as indented or the thread of the comment is not working
91
-
92
- This is entirely down to your theme. Commentluv does nothing to the display of the comments, it just adds the link
93
-
94
- = I installed the plugin but I don't see the comment form or the badge shows but commentluv is not working
95
-
96
- The plugin only works on wordpress comments systems, it does not work on Disqus or livefyre or jetpack or others. If you are using standard wordpress comments but do not see the form or it is asking you to register then make sure your theme supports comments or you have enabled comments in the settings of your blog or theme
97
-
98
- = I am having a problem getting it to work =
99
-
100
- Please see the videos in the settings page for explanations of how they work.
101
-
102
- = Accents in my language are not showing correctly =
103
-
104
- Please tick the box marked "disable UTF8 encoding" in the technical settings area of the plugins settings page
105
-
106
- == Screenshots ==
107
-
108
- 1. settings page
109
-
110
- 2. in use
111
-
112
- 3. comments admin
113
-
114
- 4. edit post comments
115
-
116
- == ChangeLog ==
117
-
118
- = 2.94.7 =
119
- * updated : compatibility
120
- * updated : no longer encoding to UTF8
121
-
122
- = 2.94.5 =
123
- *updat4ed : compatibility
124
-
125
- = 2.94.4 =
126
- * added : Thai translation
127
-
128
- = 2.94.3 =
129
- * added : swahili translation
130
-
131
- = 2.94.1 =
132
- * updated : added message about free 10 week course.
133
- * updated : compatibility notice
134
-
135
- = 2.94 =
136
-
137
- * fixed : undefined index error on display of feed if can't found in settings page
138
- * added : you can now uncheck the option to use the security nonce for ajax calls (in cases where blogs are using a peristent cache)
139
-
140
- = 2.93.9 =
141
-
142
- * updated FAQ
143
-
144
- = 2.93.8 =
145
-
146
- *fixed : videos where not showing in popup (server move broke URLs)
147
- *updated : compatibility declaration
148
-
149
- = 2.93.6 =
150
-
151
- *fixed : feed display in settings page allows for non array return
152
- *fixed : undefined index in ajax processer broke ajax if settings set to show all errors (rare)
153
-
154
- = 2.93.5 =
155
-
156
- * added : option to allow disable of utf8 encode on feed (thanks Eli http://www.un-jardin-bio.com for testing)
157
-
158
- = 2.93.4 =
159
-
160
- * updated : experimental - force to utf8 characters when outputting feed
161
- * updated : vietnamese language update
162
-
163
- = 2.93.3 =
164
-
165
- * updated : readme now says minimum wp 3.6 required
166
- * updated : add_removeluv_link now detects if $post is not available (prevents error on dashboard comments)
167
- * fixed : sidebar for wordpress 3.8 now shows properly (removed width setting on #poststuff div)
168
- * updated : sidebar facebook widget updated to use comluv.com version
169
-
170
- = 2.93.2 =
171
-
172
- * updated : get_user_by_email removed from functions.
173
-
174
- = 2.93.1 =
175
-
176
- * updated : prevent notice in admin for $authurl , check it is in $comment before trying to use it
177
-
178
- = 2.93 =
179
-
180
- * fixed : removed deprecated .live from javascript
181
-
182
- = 2.92.9 =
183
-
184
- * updated : settings page panel for ads
185
- * updated : compatibility setting
186
-
187
- = 2.92.8 =
188
-
189
- * updated : translation for Bengali
190
- * updated : translation for Turkish
191
- * added : allow swap of [type] with 'blog post' so old versions that are updated but not modified will look better
192
-
193
- = 2.92.7 =
194
-
195
- * fixed : enclose title in cdata tags in send feed file function to prevent invalid xml errors
196
-
197
- = 2.92.6 =
198
-
199
- * fixed : special feed was showing special chars for hyphen and quotes in post titles
200
- * fixed : strip tags from feed before displaying in drop down
201
-
202
- = 2.92.5 =
203
-
204
- * fixed : simplepie library changed to use separate class file for File
205
- * updated : better error reporting with simplepie for sites with undiscovered feeds
206
-
207
- = 2.92.4 =
208
-
209
- * updated : make ajax fetch more secure
210
-
211
- = 2.92.3 =
212
-
213
- * updated : fetch feed function updated to try 1 more alternative if all else fails
214
- * fixed : wpdb->prepare notice fix
215
-
216
- = 2.92.2 =
217
-
218
- * updated : updated Italian translation (thanks Gianni!)
219
- * added : Serbian translation (thanks Diana!)
220
- * updated : version checking to show ionCube status
221
- * updated : add version number of plugin to version number of register script call
222
-
223
- = 2.92.1 =
224
-
225
- * added : ability to allow Jetpack comments to activate. (thought it best to still allow free choice, maybe someone wants the advantage they get with commentluv when they comment on other commentluv blogs?)
226
-
227
- = 2.92 =
228
-
229
- * prevent jetpack comments module from being activated so comment is not affected by jetpack plugin upgrades.
230
- * updated : Italian translation
231
-
232
- = 2.91.1 =
233
- * minor mishap with ajax notify signup action. It was in the wrong place!
234
-
235
- = 2.91 =
236
- * new changes implimented for author/category urls
237
- * remove ugly red box for upgrade notice. replace with calming yellow one with a convenient link to update the plugin.
238
- * fixed : prevent DOING_AJAX from being defined if is already defined
239
- * updated : clear output buffer before sending feed
240
- * updated : prevent simplepie deprecated notices from showing when fetching feed if php is set to show them
241
- * updated : add trailing slash to url for fetching feed (some sites that have errors bork without trailing slash)
242
- * updated : do first round of effecient action setting so ajax only functions are much better for memory
243
-
244
- = 2.90.9.9.3 =
245
- * changed : try no whitespace in send_feed_file
246
- * changed : send application/atom+xml header before feed file to maybe prevent invalid mime type errors
247
- * changed : request feed set to feed = atom in fetch_feed
248
- * updated : can now request author/category and tag posts by using appropriate url in comment form of a commentluv enabled site
249
-
250
- = 2.90.9.9.2 =
251
- * added : try to increase memory available to commentluv
252
- * changed : set encoding to match that of the blog in send_feed_file
253
-
254
- = 2.90.9.9.1 =
255
- * fixed : trying new encoding of send_feed_file to match blog encoding
256
-
257
- = 2.90.9.9 =
258
- * fixed : trying updated detection routines to be compatible with new WP 3.4 query code
259
-
260
- = 2.90.9.8 =
261
- * added : Hungarian Translation
262
- * added : Vietnamese Translation
263
- * added : Slovak Translation
264
- * fixed : send_feed only to send post_type of post
265
- * updated : fall back to /?feed=rss2 in url for fetch feed if no feed found
266
- * updated : add query arg to site url when fetching feed so w3 total cache knows not to cache the response
267
- * updated : user can now choose to delete or spam a comment that has a link but no author url (prevent spammer abuse)
268
- * updated : Slovak flag fixed
269
-
270
- = 2.90.9.7 =
271
- * updated : Italian translation by Gianni
272
- * added : make wp_query->is_feed = true if commentluv request detected
273
-
274
- = 2.90.9.6 =
275
- * added : code to prevent wp_head and wp_footer actions on a commentluv request from other sites
276
- * fixed : minor translation string bug in __construct
277
-
278
- = 2.90.9.5 =
279
- * fixed : upgrading to 3.3 meant it would show the link even if admin set to not show link if no author URL in comment
280
- * fixed : footer error about invalid argument if minifying set to on
281
- * fixed : do not show unregistered in info panel if not set to 'registered' for who to show 10 posts
282
-
283
- = 2.90.9.4 =
284
- * added : Hebrew translation
285
- * fixed : do not echo WP 3.0 requirement, use wp_die instead
286
-
287
- = 2.90.9.3 =
288
- * fix : another empty src badge bug
289
- * fix : link not showing in admin page if a setting was enabled
290
- * added : empty index files in directories to prevent indexing of plugins folders
291
- * updated : images updated by Byteful Traveller (byteful.com)
292
-
293
- = 2.90.9.2 =
294
- * fix : sometimes badge was showing empty src
295
- * added : Bengali language
296
- * settings page header
297
- * modify settings page intro
298
- * added : prevent links for comments that have had the URL removed
299
-
300
- = 2.90.9.1 =
301
- * removed : w3 total cache stuff causes fatal errors on activation. removing all w3 stuff completely
302
-
303
- = 2.90.9 =
304
- * added : Danish language
305
- * fixed : minor problems with some checkbox vars
306
- * fixed : issue where an empty link might get added to a comment
307
- * fixed : small bug in settings page that prevented checkbox from being checked for default on if default admin on was unchecked
308
- * fixed : use `home_url()` instead of deprecated `get_bloginfo('home')` in `send_feed()` function
309
- * fixed : url value check compatible with iPad which adds a capital letter for the first letter of a form field
310
-
311
- = 2.90.8.3 =
312
- * fixed : fixed the error with cl_settings not defined (it was not localizing the script)
313
-
314
- = 2.90.8.2 =
315
- * added : french translation
316
- * fixed : sorry! I messed up the code when I tried to remove notices from happening in debug mode which made some blogs have an error.
317
-
318
- = 2.90.8.1 =
319
- * updated italian language (thanks Gianni)
320
- * fixed : fixed all notices when running in DEBUG mode
321
- * fixed : default image display in settings page was not showing after resetting settings
322
-
323
- = 2.90.8 =
324
- * added : Tamil language
325
- * added : Ukranian language
326
- * added : check for home page in detect commentluv request and send back 10 last posts instead of relying on object which my be populated with the contents of a homepage slider
327
- * added : function to count number of approved comments with luvlink made in the past 14 days
328
- * added : Latvian language
329
- * fixed : small issue with Polish language showing weird characters in settings page.
330
- * updated : Polish translation (thanks Mariusz!)
331
- * fixed : minor issue with settings page localized js for badge choice in IE
332
- * added : Romanian language
333
- * fixed : couple of undefined index warnings showing when on debug mode
334
- * fixed : error responseText for parseerror should now show the response body
335
- * added : check for wp_rss function existence before including rss.php to prevent a fatal error if another plugin is including rss.php in every page (eg. energizer plugin)
336
- * added : Norwegian language
337
-
338
- = 2.90.7 =
339
- * added : more detailed error messages to javascript
340
- * added : update version number in db on activation if existing version is less
341
- * added : not authorized error in fetch function if nonce check fails
342
- * added : allow disabling of commentluv request detection (for those getting xml errors when commenting on other sites)
343
- * added : if w3 total cache active, clear cache on commentluv activation/upgrade.
344
- * added : German translation
345
- * added : warning if saving settings with 10 posts only for registered users but registration not enabled
346
- * added : include note about registration not enabled to drop down list (only for admin to see)
347
- * added : auto add commentluv to list of useragents to ignore for w3 pagecache
348
- * bugfix : prevent theme from outputting data before send_feed if commentluv useragent detected
349
- * added : Persian translation
350
-
351
- = 2.90.6 =
352
- * bugfix : causing fatal error on upgrade to 2.90.5 sorry!! It was all my fault
353
- * bugfix : escape titles of other posts when showing info panel.
354
- * bugfix : compatibility with W3 total cache
355
- * removed : attempt at detecting useragent and object buffering to counteract W3 total cache
356
- * added : detection of headers already sent
357
- * added : add register link to drop down list if the link is missing and regisration is enabled
358
- * added : spanish translation
359
- * change : settings page field for register link set to disabled and descriptive text added
360
- * change : add random number of seconds up to 1 week to cron time setting on activation to prevent overload on server when plugin update is released
361
-
362
-
363
- = 2.90.5 =
364
- * bugfix : send feed function needed to wrap titles in <![CDATA[ ]]> to prevent & from causing xml error (thanks @bienvoyager for testing!)
365
- * added : use ob_start as early as possible if commentluv useragent detected
366
- * added : version check with parameters
367
-
368
- = 2.90.3 =
369
- * Added some ajax error messages in case of 404 or 500 server errors
370
- * Added Indonesian language
371
- * Fixed Malaysian language
372
- * Tweaked click notification function to be non blocking
373
-
374
- = 2.90.1 =
375
- * whole new version rewritten from scratch that makes it standalone.
376
-
377
- = 2.81.8 =
378
- * settings page notification block
379
-
380
- = 2.81.7 =
381
- * added : Lithuanian translation
382
- * added : Set nofollow on all links, no links or just unregistered users links
383
- * fix : xhtml compliance on checkbox (thanks @winkpress)
384
- * fix : check commentmeta data is an array
385
-
386
- = 2.81.6 =
387
- * added : Portuguese (Brazil) translation
388
- * fixed : added ; to functions in js file
389
- * added : option to enable compression compatibility for js files and move cl_settings js to footer
390
- * added : Romanian language
391
- * added : Arabic language
392
- * added : Georgian language
393
-
394
- = 2.81.5 =
395
- * fixed : commentluv now available on pages too
396
- * update : change click to hover for showing drop down of last blog posts that were fetched
397
- * added : Polish translation
398
- * update : settings page prettifying (hmm perdy!)
399
- * update : set drop down for last blogs posts event to hover instead of click
400
-
401
- = 2.81.4 =
402
- * Fixed : removeluv link in comments admin would result in 404 (thanks @techpatio)
403
-
404
- = 2.81.3 =
405
- * Change the way to detect if on a multi site install or not
406
- * updated one of the badges
407
-
408
- = 2.81.2 =
409
- * silly me, put the version number wrong!
410
- * Set back to default settings if upgrading from less than 2.81
411
- * Show url field for logged on user if buddypress is active
412
-
413
- = 2.81.1 =
414
- * Prevent empty last post from being included. Also included in API
415
- * Fixed Dutch translation (thanks Rene http://wpwebshop.com)
416
- * Also have commentluv on pages
417
- * updated badges to new version (thanks Byteful Traveller)
418
-
419
- = 2.81 =
420
- * New style.css format for info panel (thanks @Hishaman)
421
- * Only show remove luv link for approved comments
422
- * bug fix : sometimes showed two cluv spans (on beta version comments)
423
-
424
- = 2.80 =
425
- * Wordpress 3.0 Compatible
426
- * Use comments meta table instead of hard coding into the comment content
427
- * Drastically improved commmunication with API for comment status changes
428
- * Near 100% accuracy for API to identify members links for info panel
429
- * New heart icon for registered members. Improves hover rates.
430
- * Removed depreciated function to clean old style additional data
431
- * Added link to remove someones luvlink data in the comments admin page
432
- * Dutch Translation by Rene wppg.me
433
- * Added comments_array filter to make Thesis behave
434
- * Added check to see if link already added (WP 3.0 compatibility)
435
- * thanks to @hishaman for helping the thesis testing
436
- * Added code to settings manager to prevent viewing outside wordpress (and fixed the typo later, thanks speedforce.org)
437
-
438
- = 2.7691 =
439
- * bugfix : choosing a link from an additional url's posts would result in wrong link being included
440
-
441
- = 2.769 =
442
- * Modified hidden post fields so only URL and title sent instead of html A href link
443
- * Modified javascript to take account of new hidden fields.
444
- * Temporary fix to try and fix 404 on wp-post-comments.php when commentluv enabled for logged out user
445
- * thanks to @kwbridge @duane_scott @dannybrown @morpheas7887 for testing and feedback!
446
-
447
- = 2.768 =
448
- * Added nothing.gif to images (for updated error message from API)
449
-
450
- = 2.767 =
451
- * Added conncettimeout to curl call
452
- * Added warning next to 'use template insert' checkbox in settings page
453
-
454
- = 2.766 =
455
- * Check if function has been called before to prevent two links being added.
456
- * updated images (supplied by http://byteful.com)
457
-
458
- = 2.765 =
459
- * Hollys changes. Allow user choice of colour for the info panel background.
460
-
461
- = 2.764 =
462
- * Removed json_decode. Some wp2.9 installs were getting errors
463
-
464
- = 2.763 =
465
- * Added check for hidden fields display to prevent double instances.
466
- * Make css file valid
467
- * Added French translation by Leo http://referenceurfreelance.com
468
-
469
- = 2.762 =
470
- * Added permalink as refer variable in ajax calls for better stat collecting since WP started to use paginated comments
471
- * Added Chinese translation by Denis http://zuoshen.com/
472
- * Added Hebrew translation by Maor http://www.maorb.info/
473
- * Added Russian translation by FatCow
474
- * Updated readme.txt to use new features like changelog
475
- * Check for http:// in url field before firing (to prevent errors for forms that use js hints in form fields)
476
-
477
- = 2.761 =
478
- * 19 Jun 2009 - fix for htmlspecialchars decode causing error in wp < 2.8
479
-
480
- = 2.76 =
481
- * 16 Jun 2009 - Bug fix, use_template checkbox not displaying when selected on settings page (breaker). typo in settings page now uses &lt;?php cl\_display\_badge(); ?&gt;
482
- * added global variable for badgeshown to prevent mulitple instances (template contains function call AND use template check is off)
483
- * fixed output of prepend html using decode html and stripslashes. Added green background to update settings button.
484
-
485
- = 2.74 =
486
- * 14 Jun 2009 - Italian translation added (and fix CR in string on manager page). Thanks go to Gianni Diurno
487
-
488
- = 2.71 =
489
- * 13 Jun 2009 - fix php4 from not allowing last string pos (strrpos)
490
-
491
- = 2.7 =
492
- * 12 Jun 2009 - small fixes for valid xhtml on images and checkbox . remove identifying .-= / =-. from inserted link on display time.
493
-
494
- == Upgrade Notice ==
495
-
496
- = 2.93 =
497
-
498
- updated javascript compatibility and wp3.8 compatibility
499
-
500
- == Configuration ==
501
-
502
- Display Options : Enter the text you want displayed in the comment for the link that is added.
503
-
504
- * [name] -> replaced with comment author name
505
-
506
- * [lastpost] -> replaced with the titled link.
507
-
508
- * CommentLuv on by default -> check this box to enable CommentLuv by default
509
-
510
- * Show info panel -> Shows the heart icon next to links so users can find out more about the comment author
511
-
512
- * Use template insert to show badge and checkbox -> check this box if you want to place the badge and pull down box in a particular place on your page by using the template code.
513
-
514
- * display badge -> choose from 3 different badges, choose no badge or use your own or specified text
515
-
516
- Technical Settings:
517
-
518
- * Authors name field name -> The name value of the field used on your comment form for the comment authors name
519
-
520
- * Email field name -> The name value of the field used on your comment form for the comment authors email
521
-
522
- * Authors URL field name -> The name value of the field used on your comment form for the comment authors site URL
523
-
524
- * Comments Text Area Name -> The name value of the field used on your comment form for the comment
525
-
526
- * update -> updates the settings
527
-
528
- * reset -> if you get in trouble, click this to reset to default settings
529
-
530
- == Adding to your template ==
531
-
532
- Use `<?php cl_display_badge(); ?>` in your comments.php file where you want the badge and checkbox to be shown
533
-
534
- This plugin inserts fields to the comment form at run time. If you find there is no badge shown on the comment form after you first install it, please check your comments.php file for the command `<?php do_action('comment_form', $post->ID); ?>` before the `</form>` tag
535
-
1
+ === CommentLuv ===
2
+ Contributors: commentluv,bompus
3
+ Donate link: http://comluv.com/about/donate
4
+ Tags: commentluv, comments, last blog post, linkluv, comment luv , commentlove, comment love
5
+ Requires at least: 3.6
6
+ Tested up to: 5.0
7
+ Stable tag: 2.94.8
8
+
9
+ Reward your readers by automatically placing a link to their last blog post at the end of their comment. Encourage a community and discover new posts.
10
+
11
+ == Description ==
12
+
13
+ [Upgrade to CommentLuv Pro](http://www.commentluv.com "Upgrade to CommentLuv Pro")
14
+
15
+ CommentLuv Pro has even more amazing features that can bring even more traffic and comments to your blog by giving you the ability to fight spam, add keywords, integrate twitterlink, add a top commentators widget, social enticements and by having it installed on your site, you get advanced backlink features on EVERY CommentLuv blog when you comment (there are 10's of thousands of CommentLuv blogs)
16
+
17
+ **New**
18
+ Get a free 10 week blogging course, premium content with no charge at all. See why I'm giving this away on the first email, click the button in the settings page to start your course (and find out why I'm giving it away)
19
+
20
+ [About](http://www.commentluv.com/get-more-comments-and-traffic-with-commentluv-premium/ "About") | [Features](http://www.commentluv.com "Features") | [Pricing](http://www.commentluv.com "Pricing")
21
+
22
+ This plugin will visit the site of the comment author while they type their comment and retrieve their last blog posts which they can choose to include at the bottom of their comment when they click submit.
23
+
24
+ It has been found to increase comments and the community spirit for the thousands of blogs that have installed it. With a simple install you will immediately start to find new and interesting blog posts from your own blog and community. You will even be able to build your list/network/community even more by offering your readers the opportunity to register to your site to unlock advanced features of the plugin like being able to choose from any of their 10 last posts when they comment or other features like dofollow links and more.
25
+
26
+ The plugin requires WP or WP MS version of at least 3.0 and will work with administrators and logged on users provided they have their homepage url set in their profile page in the dashboard of the site.
27
+
28
+ You can get a free companion plugin at http://www.commentluv.com
29
+
30
+ [youtube http://www.youtube.com/watch?v=7wod9ZtiHaU]
31
+
32
+ Now with updated function to allow you to delete or spam comments where the user has removed their url after getting a last blog post link (helps prevents spammer abuse)
33
+
34
+ NOTE!
35
+
36
+ The links that CommentLuv adds are valuable for the people that leave comments so you will need to make sure that spammers do not try to take advantage of your blog by filling it with useless comments just to get a link. Be a good blogger and prevent them from leaving their crap on your site by requiring moderation on first comments and do not accept 'great post thanks!' type of comments.
37
+
38
+ There has been great success in beating spam by installing [G.A.S.P](http://wordpress.org/plugins/growmap-anti-spambot-plugin/ "Growmap Anti Spambot Plugin") . It will bring your blog back under your control and it's free!
39
+
40
+ remember.. if you let anyone comment on your blog without restriction then you WILL get spammed whether you have CommentLuv or not. Be strict with your comment policy and be take responsibility for your own blog by being selective with the comments you accept and the internet will be a happier, spam free and useful place again! :-)
41
+
42
+ Many thanks to the following who provided translations
43
+
44
+ Italian [Gianni Diuno](http://gidibao.net/ "Italian translation")
45
+ Polish [Mariusz Kolacz](http://techformator.pl/ "Polish translation")
46
+ Lithuanian [Mantas Malcius](http://mantas.malcius.lt/ "Lithuanian translation")
47
+ Georgian [Kasia Ciszewski](http://www.findmyhosting.com/ "Lithuanian translation")
48
+ Dutch [Rene](http://wpwebshop.com/ "Dutch translation")
49
+ Portuguese (BR) [Diego Uczak](http://www.korvo.com.br/ "Portuguese Translation")
50
+ Malaysian [Ariff](http://ariffshah.com/ "Malaysian Translation")
51
+ Hindi [Outshine Solutions](http://outshinesolutions.com/ "Hindi Translation")
52
+ Indonesian [Mokhamad Oky](http://rainerflame.com/ "Indonesian Translation")
53
+ Chinese (simplified) [Third Eye](http://obugs.net "Simplified Chinese Translation")
54
+ Spanish [Valentin Yonte](http://www.activosenred.com/ "Spanish Translation")
55
+ German [Jan Ruehling](http://www.cloudliving.de/ "German Translation")
56
+ Persian [Amir Heydari](http://www.3eo.ir/ "Persian Translation")
57
+ Tamil [Tharun](http://technostreak.com/ "Tamil Translation")
58
+ Ukranian [Alyona Lompar](http://www.designcontest.com/ "Ukranian Translation")
59
+ Latvian [Edgars Bergs](http://www.yourwebagency.co.uk/ "Latvian Translation")
60
+ Romanian [Manuel Cheta](http://obisnuit.eu/ "Romanian Translation")
61
+ Norwegian [Hanna](http://www.drommeland.com/ "Norwegian Translation")
62
+ French [Jean-Luc Matthys](http://etreheureux.fr/ "French Translation")
63
+ Danish [Jimmy Sigenstroem](http://w3blog.dk/ "Danish Translation")
64
+ Russian [Max](http://lavo4nik.ru/ "Russian Translation")
65
+ Bengali [Amrik Virdi](http://www.techmoody.com "Bengali Translation")
66
+ Hebrew [Tobi](http://makemoneyim.com/ "Hebrew Translation")
67
+ Vietnamese [Xman](http://thegioimanguon.com "Vietnamese Translation")
68
+ Hungarian [Bruno](http://no1tutorials.net/ "Hungarian Translation")
69
+ Slovak [Branco Radenovich](http://webhostinggeeks.com/blog/ "Slovak Translation")
70
+ Serbian [Diana](http://wpcouponshop.com/ "Serbian Translation")
71
+ Turkish [Hakan](http://hakanertr.wordpress.com/ "Turkish Translation")
72
+ Swahili [Andrew Mwaniki](http://purehcgdietdrops.com/blog/ "Swahili Translation")
73
+
74
+ == Installation ==
75
+
76
+ Wordpress : Extract the zip file and just drop the contents in the wp-content/plugins/ directory of your WordPress installation and then activate the Plugin from Plugins page or visit the plugins page in your dashboard, click 'add new' and search for 'commentluv'
77
+
78
+ If you're upgrading from an older version, please use the 'reset to default settings' button.
79
+
80
+ == Frequently Asked Questions ==
81
+
82
+ = Does this plugin add any database tables? =
83
+
84
+ No. The link and associated data is saved to the comment meta table
85
+
86
+ = My comments form does not show the name and url fields, just the textarea
87
+
88
+ Make sure you log out of your blog and view the form as a user would. A logged in user does not see the name, email and url fields because your blog already knows them.
89
+
90
+ = My comment replies are not showing as indented or the thread of the comment is not working
91
+
92
+ This is entirely down to your theme. Commentluv does nothing to the display of the comments, it just adds the link
93
+
94
+ = I installed the plugin but I don't see the comment form or the badge shows but commentluv is not working
95
+
96
+ The plugin only works on wordpress comments systems, it does not work on Disqus or livefyre or jetpack or others. If you are using standard wordpress comments but do not see the form or it is asking you to register then make sure your theme supports comments or you have enabled comments in the settings of your blog or theme
97
+
98
+ = I am having a problem getting it to work =
99
+
100
+ Please see the videos in the settings page for explanations of how they work.
101
+
102
+ = Accents in my language are not showing correctly =
103
+
104
+ Please tick the box marked "disable UTF8 encoding" in the technical settings area of the plugins settings page
105
+
106
+ == Screenshots ==
107
+
108
+ 1. settings page
109
+
110
+ 2. in use
111
+
112
+ 3. comments admin
113
+
114
+ 4. edit post comments
115
+
116
+ == ChangeLog ==
117
+
118
+ = 2.94.8 =
119
+ * October 5, 2018
120
+ * fixed : a few PHP notice errors
121
+ * fixed : allow commenters to use https:// or http:// in URL field. Previously, only http:// was allowed
122
+ * fixed : After blog domain name changes or SSL site migrations, API URL setting could be incorrect. If this setting is incorrect, we use various methods to ensure the plugin still functions on the frontend.
123
+ * fixed : possible fix for errors when fetching recent posts from commenters when their blog is SSL
124
+ * fixed : using newer plugin-included simplepie library to assist with connecting to various SSL hosts
125
+ * updated : easier for commenters to use by triggering recent posts fetch on textarea focus AND website blur, helps eliminate need to toggle CommentLuv checkbox off/on to trigger a fetch
126
+
127
+ = 2.94.7 =
128
+ * updated : compatibility
129
+ * updated : no longer encoding to UTF8
130
+
131
+ = 2.94.5 =
132
+ * updated : compatibility
133
+
134
+ = 2.94.4 =
135
+ * added : Thai translation
136
+
137
+ = 2.94.3 =
138
+ * added : swahili translation
139
+
140
+ = 2.94.1 =
141
+ * updated : added message about free 10 week course.
142
+ * updated : compatibility notice
143
+
144
+ = 2.94 =
145
+
146
+ * fixed : undefined index error on display of feed if can't found in settings page
147
+ * added : you can now uncheck the option to use the security nonce for ajax calls (in cases where blogs are using a peristent cache)
148
+
149
+ = 2.93.9 =
150
+
151
+ * updated FAQ
152
+
153
+ = 2.93.8 =
154
+
155
+ *fixed : videos where not showing in popup (server move broke URLs)
156
+ *updated : compatibility declaration
157
+
158
+ = 2.93.6 =
159
+
160
+ *fixed : feed display in settings page allows for non array return
161
+ *fixed : undefined index in ajax processer broke ajax if settings set to show all errors (rare)
162
+
163
+ = 2.93.5 =
164
+
165
+ * added : option to allow disable of utf8 encode on feed (thanks Eli http://www.un-jardin-bio.com for testing)
166
+
167
+ = 2.93.4 =
168
+
169
+ * updated : experimental - force to utf8 characters when outputting feed
170
+ * updated : vietnamese language update
171
+
172
+ = 2.93.3 =
173
+
174
+ * updated : readme now says minimum wp 3.6 required
175
+ * updated : add_removeluv_link now detects if $post is not available (prevents error on dashboard comments)
176
+ * fixed : sidebar for wordpress 3.8 now shows properly (removed width setting on #poststuff div)
177
+ * updated : sidebar facebook widget updated to use comluv.com version
178
+
179
+ = 2.93.2 =
180
+
181
+ * updated : get_user_by_email removed from functions.
182
+
183
+ = 2.93.1 =
184
+
185
+ * updated : prevent notice in admin for $authurl , check it is in $comment before trying to use it
186
+
187
+ = 2.93 =
188
+
189
+ * fixed : removed deprecated .live from javascript
190
+
191
+ = 2.92.9 =
192
+
193
+ * updated : settings page panel for ads
194
+ * updated : compatibility setting
195
+
196
+ = 2.92.8 =
197
+
198
+ * updated : translation for Bengali
199
+ * updated : translation for Turkish
200
+ * added : allow swap of [type] with 'blog post' so old versions that are updated but not modified will look better
201
+
202
+ = 2.92.7 =
203
+
204
+ * fixed : enclose title in cdata tags in send feed file function to prevent invalid xml errors
205
+
206
+ = 2.92.6 =
207
+
208
+ * fixed : special feed was showing special chars for hyphen and quotes in post titles
209
+ * fixed : strip tags from feed before displaying in drop down
210
+
211
+ = 2.92.5 =
212
+
213
+ * fixed : simplepie library changed to use separate class file for File
214
+ * updated : better error reporting with simplepie for sites with undiscovered feeds
215
+
216
+ = 2.92.4 =
217
+
218
+ * updated : make ajax fetch more secure
219
+
220
+ = 2.92.3 =
221
+
222
+ * updated : fetch feed function updated to try 1 more alternative if all else fails
223
+ * fixed : wpdb->prepare notice fix
224
+
225
+ = 2.92.2 =
226
+
227
+ * updated : updated Italian translation (thanks Gianni!)
228
+ * added : Serbian translation (thanks Diana!)
229
+ * updated : version checking to show ionCube status
230
+ * updated : add version number of plugin to version number of register script call
231
+
232
+ = 2.92.1 =
233
+
234
+ * added : ability to allow Jetpack comments to activate. (thought it best to still allow free choice, maybe someone wants the advantage they get with commentluv when they comment on other commentluv blogs?)
235
+
236
+ = 2.92 =
237
+
238
+ * prevent jetpack comments module from being activated so comment is not affected by jetpack plugin upgrades.
239
+ * updated : Italian translation
240
+
241
+ = 2.91.1 =
242
+ * minor mishap with ajax notify signup action. It was in the wrong place!
243
+
244
+ = 2.91 =
245
+ * new changes implimented for author/category urls
246
+ * remove ugly red box for upgrade notice. replace with calming yellow one with a convenient link to update the plugin.
247
+ * fixed : prevent DOING_AJAX from being defined if is already defined
248
+ * updated : clear output buffer before sending feed
249
+ * updated : prevent simplepie deprecated notices from showing when fetching feed if php is set to show them
250
+ * updated : add trailing slash to url for fetching feed (some sites that have errors bork without trailing slash)
251
+ * updated : do first round of effecient action setting so ajax only functions are much better for memory
252
+
253
+ = 2.90.9.9.3 =
254
+ * changed : try no whitespace in send_feed_file
255
+ * changed : send application/atom+xml header before feed file to maybe prevent invalid mime type errors
256
+ * changed : request feed set to feed = atom in fetch_feed
257
+ * updated : can now request author/category and tag posts by using appropriate url in comment form of a commentluv enabled site
258
+
259
+ = 2.90.9.9.2 =
260
+ * added : try to increase memory available to commentluv
261
+ * changed : set encoding to match that of the blog in send_feed_file
262
+
263
+ = 2.90.9.9.1 =
264
+ * fixed : trying new encoding of send_feed_file to match blog encoding
265
+
266
+ = 2.90.9.9 =
267
+ * fixed : trying updated detection routines to be compatible with new WP 3.4 query code
268
+
269
+ = 2.90.9.8 =
270
+ * added : Hungarian Translation
271
+ * added : Vietnamese Translation
272
+ * added : Slovak Translation
273
+ * fixed : send_feed only to send post_type of post
274
+ * updated : fall back to /?feed=rss2 in url for fetch feed if no feed found
275
+ * updated : add query arg to site url when fetching feed so w3 total cache knows not to cache the response
276
+ * updated : user can now choose to delete or spam a comment that has a link but no author url (prevent spammer abuse)
277
+ * updated : Slovak flag fixed
278
+
279
+ = 2.90.9.7 =
280
+ * updated : Italian translation by Gianni
281
+ * added : make wp_query->is_feed = true if commentluv request detected
282
+
283
+ = 2.90.9.6 =
284
+ * added : code to prevent wp_head and wp_footer actions on a commentluv request from other sites
285
+ * fixed : minor translation string bug in __construct
286
+
287
+ = 2.90.9.5 =
288
+ * fixed : upgrading to 3.3 meant it would show the link even if admin set to not show link if no author URL in comment
289
+ * fixed : footer error about invalid argument if minifying set to on
290
+ * fixed : do not show unregistered in info panel if not set to 'registered' for who to show 10 posts
291
+
292
+ = 2.90.9.4 =
293
+ * added : Hebrew translation
294
+ * fixed : do not echo WP 3.0 requirement, use wp_die instead
295
+
296
+ = 2.90.9.3 =
297
+ * fix : another empty src badge bug
298
+ * fix : link not showing in admin page if a setting was enabled
299
+ * added : empty index files in directories to prevent indexing of plugins folders
300
+ * updated : images updated by Byteful Traveller (byteful.com)
301
+
302
+ = 2.90.9.2 =
303
+ * fix : sometimes badge was showing empty src
304
+ * added : Bengali language
305
+ * settings page header
306
+ * modify settings page intro
307
+ * added : prevent links for comments that have had the URL removed
308
+
309
+ = 2.90.9.1 =
310
+ * removed : w3 total cache stuff causes fatal errors on activation. removing all w3 stuff completely
311
+
312
+ = 2.90.9 =
313
+ * added : Danish language
314
+ * fixed : minor problems with some checkbox vars
315
+ * fixed : issue where an empty link might get added to a comment
316
+ * fixed : small bug in settings page that prevented checkbox from being checked for default on if default admin on was unchecked
317
+ * fixed : use `home_url()` instead of deprecated `get_bloginfo('home')` in `send_feed()` function
318
+ * fixed : url value check compatible with iPad which adds a capital letter for the first letter of a form field
319
+
320
+ = 2.90.8.3 =
321
+ * fixed : fixed the error with cl_settings not defined (it was not localizing the script)
322
+
323
+ = 2.90.8.2 =
324
+ * added : french translation
325
+ * fixed : sorry! I messed up the code when I tried to remove notices from happening in debug mode which made some blogs have an error.
326
+
327
+ = 2.90.8.1 =
328
+ * updated italian language (thanks Gianni)
329
+ * fixed : fixed all notices when running in DEBUG mode
330
+ * fixed : default image display in settings page was not showing after resetting settings
331
+
332
+ = 2.90.8 =
333
+ * added : Tamil language
334
+ * added : Ukranian language
335
+ * added : check for home page in detect commentluv request and send back 10 last posts instead of relying on object which my be populated with the contents of a homepage slider
336
+ * added : function to count number of approved comments with luvlink made in the past 14 days
337
+ * added : Latvian language
338
+ * fixed : small issue with Polish language showing weird characters in settings page.
339
+ * updated : Polish translation (thanks Mariusz!)
340
+ * fixed : minor issue with settings page localized js for badge choice in IE
341
+ * added : Romanian language
342
+ * fixed : couple of undefined index warnings showing when on debug mode
343
+ * fixed : error responseText for parseerror should now show the response body
344
+ * added : check for wp_rss function existence before including rss.php to prevent a fatal error if another plugin is including rss.php in every page (eg. energizer plugin)
345
+ * added : Norwegian language
346
+
347
+ = 2.90.7 =
348
+ * added : more detailed error messages to javascript
349
+ * added : update version number in db on activation if existing version is less
350
+ * added : not authorized error in fetch function if nonce check fails
351
+ * added : allow disabling of commentluv request detection (for those getting xml errors when commenting on other sites)
352
+ * added : if w3 total cache active, clear cache on commentluv activation/upgrade.
353
+ * added : German translation
354
+ * added : warning if saving settings with 10 posts only for registered users but registration not enabled
355
+ * added : include note about registration not enabled to drop down list (only for admin to see)
356
+ * added : auto add commentluv to list of useragents to ignore for w3 pagecache
357
+ * bugfix : prevent theme from outputting data before send_feed if commentluv useragent detected
358
+ * added : Persian translation
359
+
360
+ = 2.90.6 =
361
+ * bugfix : causing fatal error on upgrade to 2.90.5 sorry!! It was all my fault
362
+ * bugfix : escape titles of other posts when showing info panel.
363
+ * bugfix : compatibility with W3 total cache
364
+ * removed : attempt at detecting useragent and object buffering to counteract W3 total cache
365
+ * added : detection of headers already sent
366
+ * added : add register link to drop down list if the link is missing and regisration is enabled
367
+ * added : spanish translation
368
+ * change : settings page field for register link set to disabled and descriptive text added
369
+ * change : add random number of seconds up to 1 week to cron time setting on activation to prevent overload on server when plugin update is released
370
+
371
+
372
+ = 2.90.5 =
373
+ * bugfix : send feed function needed to wrap titles in <![CDATA[ ]]> to prevent & from causing xml error (thanks @bienvoyager for testing!)
374
+ * added : use ob_start as early as possible if commentluv useragent detected
375
+ * added : version check with parameters
376
+
377
+ = 2.90.3 =
378
+ * Added some ajax error messages in case of 404 or 500 server errors
379
+ * Added Indonesian language
380
+ * Fixed Malaysian language
381
+ * Tweaked click notification function to be non blocking
382
+
383
+ = 2.90.1 =
384
+ * whole new version rewritten from scratch that makes it standalone.
385
+
386
+ = 2.81.8 =
387
+ * settings page notification block
388
+
389
+ = 2.81.7 =
390
+ * added : Lithuanian translation
391
+ * added : Set nofollow on all links, no links or just unregistered users links
392
+ * fix : xhtml compliance on checkbox (thanks @winkpress)
393
+ * fix : check commentmeta data is an array
394
+
395
+ = 2.81.6 =
396
+ * added : Portuguese (Brazil) translation
397
+ * fixed : added ; to functions in js file
398
+ * added : option to enable compression compatibility for js files and move cl_settings js to footer
399
+ * added : Romanian language
400
+ * added : Arabic language
401
+ * added : Georgian language
402
+
403
+ = 2.81.5 =
404
+ * fixed : commentluv now available on pages too
405
+ * update : change click to hover for showing drop down of last blog posts that were fetched
406
+ * added : Polish translation
407
+ * update : settings page prettifying (hmm perdy!)
408
+ * update : set drop down for last blogs posts event to hover instead of click
409
+
410
+ = 2.81.4 =
411
+ * Fixed : removeluv link in comments admin would result in 404 (thanks @techpatio)
412
+
413
+ = 2.81.3 =
414
+ * Change the way to detect if on a multi site install or not
415
+ * updated one of the badges
416
+
417
+ = 2.81.2 =
418
+ * silly me, put the version number wrong!
419
+ * Set back to default settings if upgrading from less than 2.81
420
+ * Show url field for logged on user if buddypress is active
421
+
422
+ = 2.81.1 =
423
+ * Prevent empty last post from being included. Also included in API
424
+ * Fixed Dutch translation (thanks Rene http://wpwebshop.com)
425
+ * Also have commentluv on pages
426
+ * updated badges to new version (thanks Byteful Traveller)
427
+
428
+ = 2.81 =
429
+ * New style.css format for info panel (thanks @Hishaman)
430
+ * Only show remove luv link for approved comments
431
+ * bug fix : sometimes showed two cluv spans (on beta version comments)
432
+
433
+ = 2.80 =
434
+ * Wordpress 3.0 Compatible
435
+ * Use comments meta table instead of hard coding into the comment content
436
+ * Drastically improved commmunication with API for comment status changes
437
+ * Near 100% accuracy for API to identify members links for info panel
438
+ * New heart icon for registered members. Improves hover rates.
439
+ * Removed depreciated function to clean old style additional data
440
+ * Added link to remove someones luvlink data in the comments admin page
441
+ * Dutch Translation by Rene wppg.me
442
+ * Added comments_array filter to make Thesis behave
443
+ * Added check to see if link already added (WP 3.0 compatibility)
444
+ * thanks to @hishaman for helping the thesis testing
445
+ * Added code to settings manager to prevent viewing outside wordpress (and fixed the typo later, thanks speedforce.org)
446
+
447
+ = 2.7691 =
448
+ * bugfix : choosing a link from an additional url's posts would result in wrong link being included
449
+
450
+ = 2.769 =
451
+ * Modified