PluginProbe
PowerPress Podcasting plugin by Blubrry / trunk
PowerPress Podcasting plugin by Blubrry vtrunk
11.17.9 11.17.8 11.17.7 11.17.6 11.17.4 11.17.3 11.17.2 11.17.1 11.17 11.16.11 11.16.10 11.16.9 11.16.8 11.16.7 11.16.6 11.16.5 11.16.4 11.16.3 11.16.2 11.16.1 11.9.13 11.9.14 11.9.15 11.9.16 11.9.17 All 383 releases
powerpress / powerpressadmin.php

powerpressadmin.php in PowerPress Podcasting plugin by Blubrry trunk, at powerpressadmin.php

6,022 lines 257.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if( !function_exists('add_action') )
4 die("access denied.");
5
6 add_action ('wp_loaded', 'redirect_to_settings');
7
8 function redirect_to_settings() {
9 $General = powerpress_get_settings('powerpress_general');
10 $hasChannels = isset($General['channels']) && $General['channels'] == 1;
11 $hasCats = isset($General['cat_casting']) && $General['cat_casting'] == 1;
12 $hasTax = isset($General['taxonomy_podcasting']) && $General['taxonomy_podcasting'] == 1;
13 $hasPT = isset($General['posttype_podcasting']) && $General['posttype_podcasting'] == 1;
14
15 if (!$hasChannels && !$hasCats && !$hasTax && !$hasPT && isset($_GET['page']) && $_GET['page'] == 'powerpress/powerpressadmin_live_item.php') {
16 wp_redirect(admin_url() . "admin.php?page=powerpressadmin_basic&tab=live-item-tab");
17 }
18 }
19
20 function powerpress_esc_html($escape)
21 {
22 if( is_array($escape) )
23 {
24 foreach( $escape as $index => $value ) {
25 $escape[ $index ] = powerpress_esc_html($value);
26 }
27 }
28 return esc_html($escape);
29 }
30
31 function powerpress_login_create_nonce() {
32 return wp_create_nonce( 'powerpress-link-blubrry' );
33 }
34
35 /** oauth signin url for "connect to blubrry" links, preserves $post->ID if set */
36 function powerpress_get_blubrry_signin_url($nonce) {
37 $args = ['_wpnonce' => $nonce];
38 if (!empty($GLOBALS['post']->ID)) {
39 $args['post_id'] = (int) $GLOBALS['post']->ID;
40 }
41 return add_query_arg(
42 $args,
43 admin_url('admin.php?page=powerpressadmin_onboarding.php&step=blubrrySignin&from=new_post')
44 );
45 }
46
47 /**
48 * Returns array of languages supported by RevAI
49 * @return array
50 */
51 function powerpress_revai_languages(){
52 $languages = array();
53
54 $languages['ar'] = 'Arabic';
55 $languages['bg'] = 'Bulgarian';
56 $languages['ca'] = 'Catalan';
57 $languages['hr'] = 'Croatian';
58 $languages['cs'] = 'Czech';
59 $languages['da'] = 'Danish';
60 $languages['nl'] = 'Dutch';
61 $languages['en'] = 'English';
62 $languages['fa'] = 'Farsi';
63 $languages['fi'] = 'Finnish';
64 $languages['fr'] = 'French';
65 $languages['de'] = 'German';
66 $languages['el'] = 'Greek';
67 $languages['he'] = 'Hebrew';
68 $languages['hi'] = 'Hindi';
69 $languages['hu'] = 'Hungarian';
70 $languages['id'] = 'Indonesian';
71 $languages['it'] = 'Italian';
72 $languages['ja'] = 'Japanese';
73 $languages['ko'] = 'Korean';
74 $languages['lt'] = 'Lithuanian';
75 $languages['lv'] = 'Latvian';
76 $languages['ms'] = 'Malay';
77 $languages['cmn'] = 'Mandarin';
78 $languages['no'] = 'Norwegian';
79 $languages['pl'] = 'Polish';
80 $languages['pt'] = 'Portuguese';
81 $languages['ro'] = 'Romanian';
82 $languages['ru'] = 'Russian';
83 $languages['sk'] = 'Slovak';
84 $languages['sl'] = 'Slovenian';
85 $languages['es'] = 'Spanish';
86 $languages['sv'] = 'Swedish';
87 $languages['ta'] = 'Tamil';
88 $languages['te'] = 'Telugu';
89 $languages['tr'] = 'Turkish';
90
91 return $languages;
92 }
93
94
95 function powerpress_admin_activate()
96 {
97 $Settings = get_option('powerpress_general', array());
98 if( empty($Settings) )
99 {
100 // If no settings exist, see if either PodPress or Podcasting plugins are enabled and import those settings...
101 if( defined('PODPRESS_VERSION') )
102 {
103 powerpress_admin_import_podpress_settings();
104 }
105 else if( isset($GLOBALS['podcasting_player_id']) || defined('PODCASTING_VERSION') )
106 {
107 powerpress_admin_import_podcasting_settings();
108 }
109 }
110 }
111
112 function powerpress_admin_init()
113 {
114 global $wp_rewrite;
115 add_thickbox(); // we use the thckbox for some settings
116 wp_enqueue_script('jquery');
117 wp_enqueue_script('jquery-ui-core'); // Now including the library at Google
118 // Classes to handle notices
119 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-notifications.php');
120 // Powerpress page
121 if( isset($_GET['page']) && strstr($_GET['page'], 'powerpress' ) !== false )
122 {
123 wp_enqueue_script('jquery-ui-tabs');
124 // If we have powerpress credentials, check if the account has been verified
125 $creds = get_option('powerpress_creds');
126 powerpress_check_credentials($creds);
127 //wp_enqueue_script('jquery-ui', 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js');
128 if( preg_match('/powerpressadmin_(mobile|audio|video)player/', $_GET['page']) )
129 {
130 wp_enqueue_style( 'wp-color-picker' );
131 }
132
133 if( preg_match('/powerpressadmin_migrate/', $_GET['page']) )
134 {
135 wp_enqueue_script('media-upload'); // For the readjustment of the thickbox only
136 }
137 }
138
139 if( function_exists('powerpress_admin_jquery_init') )
140 powerpress_admin_jquery_init();
141
142 if( !current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS) )
143 {
144 return;
145 }
146
147 // Check for other podcasting plugin
148 if( defined('PODPRESS_VERSION') || isset($GLOBALS['podcasting_player_id']) || isset($GLOBALS['podcast_channel_active']) || defined('PODCASTING_VERSION') )
149 powerpress_page_message_add_error( __('Another podcasting plugin has been detected, PowerPress is currently disabled.', 'powerpress') );
150
151 global $wp_version;
152 $VersionDiff = version_compare($wp_version, '3.6');
153 if( $VersionDiff < 0 )
154 powerpress_page_message_add_error( __('Blubrry PowerPress requires Wordpress version 3.6 or greater.', 'powerpress') );
155
156 // Check for incompatible plugins:
157 if( isset($GLOBALS['objWPOSFLV']) && is_object($GLOBALS['objWPOSFLV']) )
158 powerpress_page_message_add_error( __('The WP OS FLV plugin is not compatible with Blubrry PowerPress.', 'powerpress') );
159
160 // TEMPORARY: check for chartable prefixes and display a warning if they are there
161 $program_has_chartable = get_option('powerpress_chartable_check');
162 if ($program_has_chartable === false) {
163 // schedule this check to happen in the background
164 if (!wp_next_scheduled('powerpress_check_for_chartable_hook')) {
165 delete_option('powerpress_chartable_check');
166 $scheduled = wp_schedule_single_event(time(), 'powerpress_check_for_chartable_hook');
167 }
168 }
169
170 // display a warning if necessary
171 if ($program_has_chartable == 'has_chartable') {
172 $PowerPressNotificationManager = new PowerPress_Notification_Manager();
173 $message = "With Chartable shutting down, now is the time to switch to Blubrry Stats for reliable, IAB-certified podcast stats. Easily integrate from PowerPress, get comprehensive insights and real support--visit ";
174 $message .= "<a href='https://blubrry.com/services/podcast-statistics/' target='_blank'>Blubrry stats to sign up</a>! ";
175 $message .= "<a href='https://blubrry.com/podcast-insider/2024/11/01/podcasters-transition-from-chartable-to-blubrry-podcast-statistics/' target='_blank'>Learn more here</a>. ";
176 $message .= "And be sure to remove your Chartable redirect by Dec. 12th!";
177 $PowerPressNotificationManager->add('chartable-shutting-downn', $message);
178 }
179
180 // check for a message from programmatic sync
181 $pp_progad_sync_error = get_option("pp_progad_sync_error");
182 if ($pp_progad_sync_error) {
183 powerpress_page_message_add_error($pp_progad_sync_error);
184 delete_option('pp_progad_sync_error');
185 }
186
187 $pp_progad_sync_success = get_option("pp_progad_sync_success");
188 if ($pp_progad_sync_success) {
189 powerpress_page_message_add_notice($pp_progad_sync_success, 'inline');
190 delete_option('pp_progad_sync_success');
191 }
192
193 // Security step, we must be in a powerpress/* page...
194 if( isset($_GET['page']) && ( strstr($_GET['page'], 'powerpress/' ) !== false || strstr($_GET['page'], 'powerpressadmin_' ) !== false ) )
195 {
196 // Save settings here
197 if( isset($_POST[ 'Feed' ]) || isset($_POST[ 'General' ]) )
198 {
199 check_admin_referer('powerpress-edit');
200
201 // Save the posted value in the database
202 $Feed = (isset($_POST['Feed'])?$_POST['Feed']:false);
203 $General = (isset($_POST['General'])?$_POST['General']:false);
204 $FeedSlug = (isset($_POST['feed_slug'])?esc_attr($_POST['feed_slug']):false);
205 $Category = (isset($_POST['cat'])?intval($_POST['cat']):false);
206 $term_taxonomy_id = (isset($_POST['ttid'])?intval($_POST['ttid']):false);
207 $podcast_post_type = (isset($_POST['podcast_post_type'])?esc_attr($_POST['podcast_post_type']):false);
208 $acceptable_extensions = ['jpg', 'jpeg', 'png'];
209 $GeneralPrev = get_option('powerpress_general', array());
210
211 // check if deprecated feature is still being used
212 $taxonomy_podcasting_enabled = !empty($GeneralPrev['taxonomy_podcasting']);
213 $posttype_podcasting_enabled = !empty($GeneralPrev['posttype_podcasting']);
214
215 // New iTunes image
216 if( !empty($_POST['itunes_image_checkbox']) )
217 {
218 $temp = $_FILES['itunes_image_file']['tmp_name'];
219
220 //Make sure the file extension is alright
221 $name = $_FILES['itunes_image_file']['name'];
222 $ext = substr($name, strrpos($name, '.') + 1);
223
224
225 $UploadArray = wp_upload_dir();
226 $upload_url = $UploadArray['baseurl'];
227 if (empty($name) && !empty($Feed['itunes_image']) && strpos($Feed['itunes_image'], $upload_url) === false) {
228 // no uploaded file--URL pasted into field
229 $Feed['itunes_image'] = @media_sideload_image($Feed['itunes_image'], null, null, 'src');
230 }
231 if (!empty($_FILES['itunes_image_file']['tmp_name'])) {
232 if (!in_array(strtolower($ext), $acceptable_extensions)) {
233 unset($Feed['itunes_image']);
234 powerpress_page_message_add_error(__('Apple Podcasts Image has an invalid file type: ' . htmlspecialchars($ext), 'powerpress'));
235 } else {
236 // Check the image...
237 if (file_exists($temp)) {
238 $ImageData = @getimagesize($temp);
239
240 // phpstan: getimagesize returns false on failure, check before accessing
241 if ($ImageData) {
242 $rgb = true; // We assume it is RGB
243 if (defined('POWERPRESS_IMAGICK') && POWERPRESS_IMAGICK) {
244 if ($ImageData[2] == IMAGETYPE_PNG && extension_loaded('imagick')) {
245 $image = new Imagick($temp);
246 if ($image->getImageColorspace() != imagick::COLORSPACE_RGB) {
247 $rgb = false;
248 }
249 }
250 }
251
252 if (empty($ImageData['channels']))
253 $ImageData['channels'] = 3; // Assume it's ok if we cannot detect it.
254 if ($rgb && ($ImageData[2] == IMAGETYPE_JPEG || $ImageData[2] == IMAGETYPE_PNG) && $ImageData[0] == $ImageData[1] && $ImageData[0] >= 1400 && $ImageData[0] <= 3000 && $ImageData['channels'] == 3) // Just check that it is an image, the correct image type and that the image is square
255 {
256 $upload_result = wp_handle_upload($_FILES['itunes_image_file'], array('action' => $_POST['action'], 'test_form' => false));
257 if (is_array($upload_result) && isset($upload_result['error'])) {
258 unset($Feed['itunes_image']);
259 powerpress_page_message_add_error(__('Error saving image', 'powerpress') . ': ' . htmlspecialchars($upload_result['error']));
260 } elseif (is_array($upload_result) && isset($upload_result['url'])) {
261 $Feed['itunes_image'] = $upload_result['url'];
262 } else {
263 unset($Feed['itunes_image']);
264 powerpress_page_message_add_error(__('Error saving image', 'powerpress'));
265 }
266 } else if ($ImageData['channels'] != 3 || $rgb == false) {
267 unset($Feed['itunes_image']);
268 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']) . ' - ' . __('Image must be in RGB color space (CMYK is not supported).', 'powerpress'));
269 } else if ($ImageData[0] != $ImageData[1]) {
270 unset($Feed['itunes_image']);
271 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']) . ' - ' . __('Image must be square, 1400 x 1400 is the required minimum size.', 'powerpress'));
272 } else if ($ImageData[0] != $ImageData[1] || $ImageData[0] < 1400) {
273 unset($Feed['itunes_image']);
274 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']) . ' - ' . __('Image is too small, 1400 x 1400 is the required minimum size.', 'powerpress'));
275 } else if ($ImageData[0] != $ImageData[1] || $ImageData[0] > 3000) {
276 unset($Feed['itunes_image']);
277 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']) . ' - ' . __('Image is too large, 3000 x 3000 is the maximum size allowed.', 'powerpress'));
278 } else {
279 unset($Feed['itunes_image']);
280 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']));
281 }
282 } else {
283 unset($Feed['itunes_image']);
284 powerpress_page_message_add_error(__('Invalid image', 'powerpress') . ': ' . htmlspecialchars($_FILES['itunes_image_file']['name']));
285 }
286 }
287 }
288 }
289 }
290
291 // New mp3 coverart image
292 if( !empty($_POST['coverart_image_checkbox']) )
293 {
294 $temp = $_FILES['coverart_image_file']['tmp_name'];
295
296 //Make sure the file extension is alright
297 $name = $_FILES['coverart_image_file']['name'];
298 $ext = substr($name, strrpos($name, '.') + 1);
299
300 if (!in_array(strtolower($ext), $acceptable_extensions)) {
301 powerpress_page_message_add_error(__('Coverart Image has an invalid file type: ' . htmlspecialchars($ext), 'powerpress') );
302 } else {
303 if (@getimagesize($temp)) // Just check that it is an image, we may add more to this later
304 {
305 $upload_result = wp_handle_upload($_FILES['coverart_image_file'], array('action' => $_POST['action'], 'test_form' => false));
306 if (is_array($upload_result) && isset($upload_result['error'])) {
307 powerpress_page_message_add_error(__('Error saving Coverart image', 'powerpress') . ': ' . $upload_result['error']);
308 } elseif (is_array($upload_result) && isset($upload_result['url'])) {
309 $General['tag_coverart'] = $upload_result['url'];
310 } else {
311 powerpress_page_message_add_error(__('Error saving Coverart image', 'powerpress'));
312 }
313 } else {
314 powerpress_page_message_add_error(__('Invalid Coverat image', 'powerpress') . ': ' . htmlspecialchars($_FILES['coverart_image_file']['name']));
315 }
316 }
317 }
318
319 // New poster image
320 if( !empty($_POST['poster_image_checkbox']) )
321 {
322 $temp = $_FILES['poster_image_file']['tmp_name'];
323
324 //Make sure the file extension is alright
325 $name = $_FILES['poster_image_file']['name'];
326 $ext = substr($name, strrpos($name, '.') + 1);
327
328 if (!in_array(strtolower($ext), $acceptable_extensions)) {
329 powerpress_page_message_add_error(__('Poster Image has an invalid file type: ' . htmlspecialchars($ext), 'powerpress') );
330 } else {
331 if (@getimagesize($temp)) // Just check that it is an image, we may add more to this later
332 {
333 $upload_result = wp_handle_upload($_FILES['poster_image_file'], array('action' => $_POST['action'], 'test_form' => false));
334 if (is_array($upload_result) && isset($upload_result['error'])) {
335 powerpress_page_message_add_error(__('Error saving Poster image', 'powerpress') . ': ' . $upload_result['error']);
336 } elseif (is_array($upload_result) && isset($upload_result['url'])) {
337 $General['poster_image'] = $upload_result['url'];
338 } else {
339 powerpress_page_message_add_error(__('Error saving Poster image', 'powerpress'));
340 }
341 } else {
342 powerpress_page_message_add_error(__('Invalid poster image', 'powerpress') . ': ' . htmlspecialchars($_FILES['poster_image_file']['name']));
343 }
344 }
345 }
346
347
348 // New audio play icon image
349 if( !empty($_POST['audio_custom_play_button_checkbox']) )
350 {
351 $temp = $_FILES['audio_custom_play_button_file']['tmp_name'];
352
353 //Make sure the file extension is alright
354 $name = $_FILES['audio_custom_play_button_file']['name'];
355 $ext = substr($name, strrpos($name, '.') + 1);
356
357 if (!in_array(strtolower($ext), $acceptable_extensions)) {
358 powerpress_page_message_add_error(__('Custom audio play button Image has an invalid file type: ' . htmlspecialchars($ext), 'powerpress') );
359 } else {
360 if (@getimagesize($temp)) // Just check that it is an image, we may add more to this later
361 {
362 $upload_result = wp_handle_upload($_FILES['audio_custom_play_button_file'], array('action' => $_POST['action'], 'test_form' => false));
363 if (is_array($upload_result) && isset($upload_result['error'])) {
364 powerpress_page_message_add_error(__('Error saving Play image', 'powerpress') . ': ' . $upload_result['error']);
365 } elseif (is_array($upload_result) && isset($upload_result['url'])) {
366 $General['audio_custom_play_button'] = $upload_result['url'];
367 } else {
368 powerpress_page_message_add_error(__('Error saving Play image', 'powerpress'));
369 }
370 } else {
371 powerpress_page_message_add_error(__('Invalid play icon image', 'powerpress') . ': ' . htmlspecialchars($_FILES['audio_custom_play_button_file']['name']));
372 }
373 }
374 }
375
376 // New video play icon image powerpress-select-player
377 if( !empty($_POST['video_custom_play_button_checkbox']) )
378 {
379 $temp = $_FILES['video_custom_play_button_file']['tmp_name'];
380
381 //Make sure the file extension is alright
382 $name = $_FILES['video_custom_play_button_file']['name'];
383 $ext = substr($name, strrpos($name, '.') + 1);
384
385 if (!in_array(strtolower($ext), $acceptable_extensions)) {
386 powerpress_page_message_add_error(__('Custom video play button Image has an invalid file type: ' . htmlspecialchars($ext), 'powerpress') );
387 } else {
388 $imageInfo = @getimagesize($temp);
389 if ($imageInfo && $imageInfo[0] == $imageInfo[1] && $imageInfo[0] == 60) // Just check that it is an image, we may add more to this later
390 {
391 $upload_result = wp_handle_upload($_FILES['video_custom_play_button_file'], array('action' => $_POST['action'], 'test_form' => false));
392 if (is_array($upload_result) && isset($upload_result['error'])) {
393 powerpress_page_message_add_error(__('Error saving Video Play icon image', 'powerpress') . ': ' . $upload_result['error']);
394 } elseif (is_array($upload_result) && isset($upload_result['url'])) {
395 $General['video_custom_play_button'] = $upload_result['url'];
396 } else {
397 powerpress_page_message_add_error(__('Error saving Video Play icon image', 'powerpress'));
398 }
399 } else if ($imageInfo) {
400 powerpress_page_message_add_error(__('Invalid play icon image size', 'powerpress') . ': ' . htmlspecialchars($_FILES['video_custom_play_button_file']['name']));
401 } else {
402 powerpress_page_message_add_error(__('Invalid play icon image', 'powerpress') . ': ' . htmlspecialchars($_FILES['video_custom_play_button_file']['name']));
403 }
404 }
405 }
406
407 if( isset($_POST['UpdateDisablePlayer']) )
408 {
409 $player_feed_slug = $_POST['UpdateDisablePlayer'];
410 $General['disable_player'] = array();
411 if( isset($GeneralPrev['disable_player']) )
412 $General['disable_player'] = $GeneralPrev['disable_player'];
413 if( isset($_POST['DisablePlayerFor']) && !empty($_POST['DisablePlayerFor']) )
414 $General['disable_player'][ $player_feed_slug ] = 1;
415 else
416 unset($General['disable_player'][ $player_feed_slug ]);
417 }
418
419 // Check to see if we need to update the feed title
420 if( $FeedSlug && !$podcast_post_type )
421 {
422 $GeneralSettingsTemp = powerpress_get_settings('powerpress_general', false);
423 if( !isset($GeneralSettingsTemp['custom_feeds'][$FeedSlug]) || $GeneralSettingsTemp['custom_feeds'][$FeedSlug] != $Feed['title'] )
424 {
425 if( !$General )
426 $General = array();
427 if( !empty($GeneralSettingsTemp['custom_feeds']) )
428 $General['custom_feeds'] = $GeneralSettingsTemp['custom_feeds'];
429 else
430 $General['custom_feeds'] = array();
431 $General['custom_feeds'][$FeedSlug] = $Feed['title'];
432 }
433 }
434
435 // Update the settings in the database:
436 if( $General )
437 {
438 if( !empty($_POST['action']) && $_POST['action'] == 'powerpress-save-settings' )
439 {
440 if( !isset($General['display_player_excerpt']) ) // If we are modifying appearance settings but this option was not checked...
441 $General['display_player_excerpt'] = 0; // Set it to zero.
442
443 //if( !isset($General['display_player_disable_mobile']) )
444 // $General['display_player_disable_mobile'] = 0;
445
446 $General['disable_dashboard_stats'] = 0;
447 if( !empty($_POST['DisableStatsInDashboard'] ) )
448 $General['disable_dashboard_stats'] = 1;
449 if( !isset($General['allow_feed_comments'] ) )
450 $General['allow_feed_comments'] = 0;
451
452 if( !isset($General['feed_links']) )
453 $General['feed_links'] = 0;
454 if( !isset($General['skip_to_episode_settings']) )
455 $General['skip_to_episode_settings'] = 0;
456
457 // Advanced Features
458 if( !isset($General['player_options'] ) )
459 $General['player_options'] = 0;
460 if( !isset($General['cat_casting'] ) )
461 $General['cat_casting'] = 0;
462 if( !isset($General['channels'] ) )
463 $General['channels'] = 0;
464 if( !isset($General['playlist_player'] ) )
465 $General['playlist_player'] = 0;
466 if(!isset($General['powerpress_network']))
467 $General['powerpress_network'] = 0;
468 if(!isset($General['powerpress_accept_json']))
469 $General['powerpress_accept_json'] = 0;
470 if(!isset($General['pp_show_block_errors']))
471 $General['pp_show_block_errors'] = 0;
472 if(!isset($General['powerpress_self_hosted_media']))
473 $General['powerpress_self_hosted_media'] = 0;
474
475 // Media Presentation Settings
476 $PlayerSettings = array();
477 if( !empty($_POST['PlayerSettings']) )
478 $PlayerSettings = $_POST['PlayerSettings'];
479 if( empty($PlayerSettings['display_pinw']) )
480 $PlayerSettings['display_pinw'] = 0;
481 if( empty($PlayerSettings['display_media_player']) )
482 $PlayerSettings['display_media_player'] = 0;
483 if( empty($PlayerSettings['display_pinw']) ) $PlayerSettings['display_pinw'] = 0;
484 if( empty($PlayerSettings['display_media_player']) ) $PlayerSettings['display_media_player'] = 0;
485
486 $General['player_function'] = abs( $PlayerSettings['display_pinw'] - $PlayerSettings['display_media_player'] );
487 $General['podcast_link'] = 0;
488 if( !empty($PlayerSettings['display_download']) )
489 {
490 $General['podcast_link'] = 1;
491 if( !empty($PlayerSettings['display_download_size']) )
492 {
493 $General['podcast_link'] = 2;
494 if( !empty($PlayerSettings['display_download_duration']) )
495 $General['podcast_link'] = 3;
496 }
497 }
498
499 if( !isset($General['podcast_embed'] ) )
500 $General['podcast_embed'] = 0;
501 if( !isset($General['podcast_embed_in_feed'] ) )
502 $General['podcast_embed_in_feed'] = 0;
503 if( !isset($General['m4a'] ) )
504 $General['m4a'] = '';
505 if( !isset($General['new_window_nofactor'] ) )
506 $General['new_window_nofactor'] = '';
507
508 if( !isset($General['subscribe_links'] ) )
509 $General['subscribe_links'] = false;
510 if( !isset($General['subscribe_feature_email'] ) )
511 $General['subscribe_feature_email'] = false;
512
513 // for user role management
514 if (empty($General['use_caps']) && !empty($GeneralPrev['use_caps'])) { // turning user role management off
515 $users = array('administrator','editor', 'author', 'contributor', 'subscriber');
516 foreach( $users as $null => $user )
517 {
518 $role = get_role($user);
519 if( !empty($role) )
520 {
521 if( $role->has_cap('edit_podcast') )
522 $role->remove_cap('edit_podcast');
523 if( $role->has_cap('view_podcast_stats') )
524 $role->remove_cap('view_podcast_stats');
525 }
526 }
527 powerpress_page_message_add_notice( __('PowerPress Roles and Capabilities removed from WordPress Blog', 'powerpress') );
528 } else if (!empty($General['use_caps']) && empty($GeneralPrev['use_caps'])) { // turning user role management on
529 $users = array('administrator','editor', 'author'); // , 'contributor', 'subscriber');
530 foreach( $users as $null => $user )
531 {
532 $role = get_role($user);
533 if( !empty($role) )
534 {
535 if( !$role->has_cap('edit_podcast') )
536 $role->add_cap('edit_podcast');
537 if( $user == 'administrator' && !$role->has_cap('view_podcast_stats') )
538 $role->add_cap('view_podcast_stats');
539 }
540 }
541 powerpress_page_message_add_notice( __('PowerPress Roles and Capabilities added to WordPress Blog.', 'powerpress') );
542 }
543
544 // TO DEPRECATE: Can still be enabled via wp-config defines
545 // taxonomy/posttype podcasting: only allow disabling, not enabling (deprecated features)
546 if (!isset($General['taxonomy_podcasting'])) {
547 $General['taxonomy_podcasting'] = 0;
548 } else if (!$taxonomy_podcasting_enabled && !empty($General['taxonomy_podcasting'])) {
549 // block enabling
550 $General['taxonomy_podcasting'] = 0;
551 }
552 if (!isset($General['posttype_podcasting'])) {
553 $General['posttype_podcasting'] = 0;
554 } else if (!$posttype_podcasting_enabled && !empty($General['posttype_podcasting'])) {
555 // block enabling
556 $General['posttype_podcasting'] = 0;
557 }
558 }
559 else if( !empty($_POST['action']) && $_POST['action'] == 'powerpress-save-defaults' )
560 {
561 if( !isset($General['display_player_excerpt']) ) // If we are modifying appearance settings but this option was not checked...
562 $General['display_player_excerpt'] = 0; // Set it to zero.
563 $General['disable_dashboard_stats'] = 0;
564 if( !empty($_POST['DisableStatsInDashboard'] ) )
565 $General['disable_dashboard_stats'] = 1;
566
567 // Advanced Mode options
568 if( !isset($General['cat_casting'] ) )
569 $General['cat_casting'] = 0;
570 if( !isset($General['channels'] ) )
571 $General['channels'] = 0;
572 if( !isset($General['playlist_player'] ) )
573 $General['playlist_player'] = 0;
574 if(!isset($General['powerpress_network']))
575 $General['powerpress_network'] = 0;
576 if(!isset($General['powerpress_accept_json']))
577 $General['powerpress_accept_json'] = 0;
578 if(!isset($General['pp_show_block_errors']))
579 $General['pp_show_block_errors'] = 0;
580 if(!isset($General['powerpress_self_hosted_media']))
581 $General['powerpress_self_hosted_media'] = 0;
582
583 // TO DEPRECATE: Can still be enabled via wp-config defines
584 // taxonomy/posttype podcasting: only allow disabling, not enabling (deprecated)
585 if (!isset($General['taxonomy_podcasting'])) {
586 $General['taxonomy_podcasting'] = 0;
587 } else if (!$taxonomy_podcasting_enabled && !empty($General['taxonomy_podcasting'])) {
588 // block enabling
589 $General['taxonomy_podcasting'] = 0;
590 }
591 if (!isset($General['posttype_podcasting'])) {
592 $General['posttype_podcasting'] = 0;
593 } else if (!$posttype_podcasting_enabled && !empty($General['posttype_podcasting'])) {
594 // block enabling
595 $General['posttype_podcasting'] = 0;
596 }
597 }
598
599 // seo settings
600 if( !empty($_POST['action']) && $_POST['action'] == 'powerpress-save-settings' )
601 {
602 //$PowerPressSearch = $_POST['PowerPressSearch'];
603 $PowerPressSearchToggle = $_POST['PowerPressSearchToggle'];
604 if( empty($PowerPressSearchToggle['seo_feed_title']) )
605 $General['seo_feed_title'] = 0;
606 }
607
608 // tags settings
609 if( !empty($_POST['action']) && $_POST['action'] == 'powerpress-save-settings' )
610 {
611 if( !isset($General['write_tags']) ) // If we are modifying appearance settings but this option was not checked...
612 $General['write_tags'] = 0; // Set it to zero.
613
614 $TagValues = $_POST['TagValues'];
615 $GeneralPosted = $_POST['General'];
616
617 if( !empty($_POST['PowerPressTrackNumber']) ) {
618 update_option('powerpress_track_number', $_POST['PowerPressTrackNumber']);
619 }
620 // Set all the tag values...
621 foreach( $GeneralPosted as $key => $value )
622 {
623 if( substr($key, 0, 4) == 'tag_' )
624 {
625 // Special case, we are uploading new coverart image
626 if( !empty($_POST['coverart_image_checkbox']) && $key == 'tag_coverart' )
627 continue;
628
629 // Special case, the track is saved in a separate column in the database.
630 if( $key == 'tag_track' )
631 continue;
632
633 // Special case, tag_chapters is a boolean radio, no TagValues[]
634 if( $key == 'tag_chapters' )
635 continue;
636
637 if( !empty($value) )
638 $General[$key] = $TagValues[$key];
639 else
640 $General[$key] = '';
641 }
642 }
643
644 if( !empty($General['tag_coverart']) ) // $TagValues['tag_coverart'] != '' )
645 {
646 $GeneralSettingsTemp = powerpress_get_settings('powerpress_general', false);
647 if( !empty($GeneralSettingsTemp['blubrry_hosting']) && $GeneralSettingsTemp['blubrry_hosting'] !== 'false' )
648 {
649 require_once(POWERPRESS_ABSPATH .'/powerpressadmin-auth.class.php');
650 $auth = new PowerPressAuth();
651 $json_data = false;
652 $api_url_array = powerpress_get_api_array();
653 $creds = get_option('powerpress_creds');
654 if ($creds) {
655 $accessToken = powerpress_getAccessToken();
656 $req_url = sprintf('/2/media/%s/coverart.json?url=%s', $GeneralSettingsTemp['blubrry_program_keyword'], urlencode($TagValues['tag_coverart']));
657 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA')?'?'. POWERPRESS_BLUBRRY_API_QSA:'');
658 $results = $auth->api($accessToken, $req_url, false, 'DELETE');
659 } else {
660 foreach ($api_url_array as $index => $api_url) {
661 $req_url = sprintf('%s/media/%s/coverart.json?url=%s', rtrim($api_url, '/'), $GeneralSettingsTemp['blubrry_program_keyword'], urlencode($TagValues['tag_coverart']));
662 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA') ? '&' . POWERPRESS_BLUBRRY_API_QSA : '');
663 $json_data = powerpress_remote_fopen($req_url, $GeneralSettingsTemp['blubrry_auth']);
664 if (!$json_data && $api_url == 'https://api.blubrry.com/') { // Lets force cURL and see if that helps...
665 $json_data = powerpress_remote_fopen($req_url, $GeneralSettingsTemp['blubrry_auth'], array(), 15, false, true);
666 }
667 if ($json_data != false)
668 break;
669 }
670 // Lets try to cache the image onto Blubrry's Server...
671 $results = powerpress_json_decode($json_data);
672 }
673
674 if( is_array($results) && !isset($results['error']) )
675 {
676 // Good!
677 powerpress_page_message_add_notice( __('Coverart image updated successfully.', 'powerpress') );
678 }
679 else if( isset($results['error']) )
680 {
681 $error = __('Blubrry Hosting Error (updating coverart)', 'powerpress') .': '. $results['error'];
682 powerpress_page_message_add_error($error);
683 }
684 else
685 {
686 $error = __('An error occurred updating the coverart with your Blubrry Services Account.', 'powerpress');
687 powerpress_page_message_add_error($error);
688 }
689 }
690 else
691 {
692 powerpress_page_message_add_error( __('Coverart Image was not uploaded to your Blubrry Services Account. It will NOT be added to your mp3s.', 'powerpress') );
693 }
694 }
695 }
696
697 if( !empty($_POST['action']) && $_POST['action'] == 'powerpress-save-videocommon' )
698 {
699 if( !isset($General['poster_play_image'] ) )
700 $General['poster_play_image'] = 0;
701 if( !isset($General['poster_image_audio'] ) )
702 $General['poster_image_audio'] = 0;
703 }
704
705 // Wordpress adds slashes to everything, but since we're storing everything serialized, lets remove them...
706 $General = powerpress_stripslashes($General);
707 powerpress_save_settings($General);
708 }
709
710 if( $Feed )
711 {
712 // CREDITS
713 // nested
714 if (isset($Feed['credits']) && is_array($Feed['credits'])) {
715 $credit_data = [];
716 foreach($Feed['credits'] as $credit) {
717 if (empty($credit['name'])) continue;
718 $credit_name = powerpress_trim_value($credit['name'], 'credit_name');
719
720 $credit_data[] = [
721 'name' => sanitize_text_field($credit_name),
722 'role' => sanitize_text_field($credit['role']),
723 'person_url' => esc_url_raw(sanitize_text_field($credit['person_url'])),
724 'link_url' => esc_url_raw(sanitize_text_field($credit['link_url']))
725 ];
726 }
727
728 // replace intaken Feed values with only validated data
729 $Feed['credits'] = $credit_data;
730 } else {
731 $Feed['credits'] = [];
732 }
733
734 // VALUE RECIPIENTS (V4V)
735 if (isset($Feed['value_recipients']) && is_array($Feed['value_recipients'])) {
736 $fee_split_total = 0;
737 $split_total = 0;
738 $valid_recipients = [];
739
740 foreach ($Feed['value_recipients'] as $recipient_data) {
741 if (empty($recipient_data['pubkey'])) continue;
742 $pubkey = trim($recipient_data['pubkey']);
743
744 // filter 0 split
745 $split = isset($recipient_data['split']) ? (float) sanitize_text_field($recipient_data['split']) : 0.0;
746 if ($split <= 0) continue;
747
748 $is_fee = ($recipient_data['fee'] ?? 'false') === 'true';
749
750 if ($is_fee) {
751 $fee_split_total += $split;
752 } else {
753 $split_total += $split;
754 }
755
756 $valid_recipients[] = [
757 // accepts emails (fountain.fm, alby) or lnurl, sanitize_email can break lnurl format
758 'lightning' => sanitize_text_field($recipient_data['lightning'] ?? ''),
759 'pubkey' => sanitize_text_field($recipient_data['pubkey']),
760 'custom_key' => sanitize_text_field($recipient_data['custom_key']),
761 'custom_value' => sanitize_text_field($recipient_data['custom_value']),
762 'split' => $split,
763 'fee' => $is_fee ? 'true' : 'false'
764 ];
765 }
766
767 if ($split_total > 100)
768 powerpress_page_message_add_error(__('Regular recipient splits exceed 100%. Please adjust split percentages.', 'powerpress'));
769
770 if ($fee_split_total > 100)
771 powerpress_page_message_add_error(__('Fee recipient splits exceed 100%. Please adjust fee percentages.', 'powerpress'));
772
773 // replace intaken Feed values with only validated data
774 $Feed['value_recipients'] = $valid_recipients;
775 } else {
776 $Feed['value_recipients'] = [];
777 }
778
779 // LOCATION
780 if (isset($Feed['location']) && is_array($Feed['location'])) {
781 $valid_locations = [];
782
783 foreach ($Feed['location'] as $location_data) {
784 if (empty($location_data['address'])) continue;
785 $address = powerpress_trim_value($location_data['address'], 'address');
786
787 $valid_locations[] = [
788 'address' => sanitize_text_field($address),
789 'geo' => sanitize_text_field($location_data['pci_geo'] ?? ''),
790 'osm' => sanitize_text_field($location_data['pci_osm'] ?? ''),
791 'country' => sanitize_text_field($location_data['pci_country'] ?? ''),
792 'rel' => sanitize_text_field($location_data['pci_rel'] ?? '')
793 ];
794 }
795
796 // replace intaken Feed values with only validated data
797 $Feed['location'] = $valid_locations;
798 } else {
799 $Feed['location'] = [];
800 }
801
802 // TXT TAG
803 if (isset($Feed['txt_tag']) && is_array($Feed['txt_tag'])) {
804 $txt_tag_data = [];
805
806 foreach($Feed['txt_tag'] as $tag) {
807 // Sanitize
808 $tag_content = isset($tag['tag']) ? sanitize_textarea_field($tag['tag']) : '';
809 $tag_purpose = isset($tag['purpose']) ? sanitize_text_field($tag['purpose']) : '';
810
811 $tag_content = powerpress_trim_value($tag_content, 'tag_content');
812 $tag_purpose = powerpress_trim_value($tag_purpose, 'tag_purpose');
813
814 if (empty($tag_content)) continue;
815 if ($tag_purpose === 'applepodcastsverify') continue;
816
817 $txt_tag_data[] = [
818 'tag' => $tag_content,
819 'purpose' => $tag_purpose
820 ];
821 }
822
823 // replace intaken Feed values with only validated data
824 $Feed['txt_tag'] = $txt_tag_data;
825 } else {
826 $Feed['txt_tag'] = [];
827 }
828
829 $feed_url = "";
830 if ($Category) {
831 if( !empty($General['cat_casting_podcast_feeds']) )
832 $feed_url = get_category_feed_link($Category, 'podcast');
833 else // Use the old link
834 $feed_url = get_category_feed_link($Category);
835 } else if ($term_taxonomy_id) {
836 global $wpdb;
837 $term_info = $wpdb->get_results("SELECT term_id, taxonomy FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = $term_taxonomy_id", ARRAY_A);
838 $taxonomy_type = $term_info[0]['taxonomy'];
839 $feed_url = get_term_feed_link($term_taxonomy_id, $taxonomy_type, 'rss2');
840 } else if ($podcast_post_type) {
841 $feed_url = get_post_type_archive_feed_link($podcast_post_type, $FeedSlug);
842 } else // otherwise treat as a podcast channel
843 {
844 $feed_url = get_feed_link($FeedSlug);
845 }
846
847 require_once('uuid5.class.php');
848 if (!UUID::is_valid($Feed['live_item']['guid']) || $Feed['live_item']['status'] == 'Pending') {
849 $Feed['live_item']['guid'] = UUID::v5('ead4c236-bf58-58c6-a2c6-a6b28d128cb6', $Feed['live_item']['title'] . ' ' .rand(0, 1000000));
850 $Feed['live_item']['podping_status'] = -1;
851 }
852
853 $litEerror = false;
854 update_option('lit_error', false);
855 update_option('lit_error_msg', '');
856
857 if (($Feed['live_item']['enabled'] ?? '0') == '1') {
858 if ($Feed['live_item']['start_date_time'] == "" || $Feed['live_item']['end_date_time'] == "" || $Feed['live_item']['title'] == "" || $Feed['live_item']['stream_link'] == "" || $Feed['live_item']['fallback_link'] == "") {
859 update_option('lit_error', true);
860 update_option('lit_error_msg', "Please fill out all required fields before enabling your live item.");
861 $litEerror = true;
862 }
863
864 // Ensure end date is after start date
865 $startDate = explode('T', $Feed['live_item']['start_date_time']);
866 $endDate = explode('T', $Feed['live_item']['end_date_time']);
867
868 $startUnix = strtotime(($startDate[0] ?? '') . ' ' . ($startDate[1] ?? '') . ' ' . htmlspecialchars($Feed['live_item']['timezone']));
869 $endUnix = strtotime(($endDate[0] ?? '') . ' ' . ($endDate[1] ?? '') . ' ' . htmlspecialchars($Feed['live_item']['timezone']));
870
871 if ($endUnix <= $startUnix) {
872 update_option('lit_error', true);
873 update_option('lit_error_msg', "Please choose an ending date and time which is after your starting date.");
874 $litEerror = true;
875 }
876
877 if ($startUnix <= time() && $Feed['live_item']['status'] == "Pending") {
878 update_option('lit_error', true);
879 update_option('lit_error_msg', 'Please choose a starting date and time in the future.');
880 $litEerror = true;
881 }
882
883 if ($litEerror) {
884 $Feed['live_item']['enabled'] = '0';
885 } else {
886 $Feed['live_item']['podping_status'] = intval($Feed['live_item']['podping_status']);
887 $reason = false;
888
889 if ($Feed['live_item']['status'] == 'Ended')
890 $reason = 'liveEnd';
891 elseif ($Feed['live_item']['status'] == 'Live')
892 $reason = 'live';
893
894 $creds = get_option('powerpress_creds');
895 $GeneralSettingsTemp = powerpress_get_settings('powerpress_general', false);
896 $pending = !$reason && $Feed['live_item']['podping_status'] != 0;
897 $live = $reason == 'live' && $Feed['live_item']['podping_status'] != 1;
898 $ended = $reason == 'liveEnd' && $Feed['live_item']['podping_status'] != 2;
899
900 if (($pending || $live || $ended) && (!empty($creds) || !empty($GeneralSettingsTemp['blubrry_auth']))) {
901 if (!(defined('POWERPRESS_DISABLE_PODPING') && POWERPRESS_DISABLE_PODPING)) {
902 require_once('powerpresspodping.class.php');
903 $Podping = new PowerPressPodping();
904 try {
905 // because auth key is the same across the whole site and each feed url is being passed, it doesn't matter what program keyword we use to call the api
906 $Podping->publish($feed_url, $GeneralSettingsTemp['blubrry_program_keyword'], $reason);
907 } catch (Exception $e) {
908 if (defined('WP_DEBUG') && WP_DEBUG) {
909 powerpress_page_message_add_error($e->getMessage());
910 }
911 }
912
913 if ($reason == 'live')
914 $Feed['live_item']['podping_status'] = 1;
915 else if ($reason == 'liveEnd')
916 $Feed['live_item']['podping_status'] = 2;
917 else
918 $Feed['live_item']['podping_status'] = 0;
919 }
920 }
921 }
922 }
923
924 // ====================
925 // PCI UPDATE FREQUENCY
926 // ====================
927
928 $cadence_preset = '';
929 $valid_presets = ['daily', 'weekly', 'semiweekly', 'biweekly', 'monthly', 'semimonthly', 'bimonthly', 'custom', 'complete'];
930 if (isset($Feed['cadence_preset']) && in_array($Feed['cadence_preset'], $valid_presets, true)) {
931 $cadence_preset = $Feed['cadence_preset'];
932 }
933 $Feed['cadence_preset'] = $cadence_preset;
934
935 if ($cadence_preset === 'complete') {
936 $Feed['itunes_complete'] = '1';
937 unset($Feed['update_frequency']);
938 } else {
939 if (isset($Feed['itunes_complete']) && $Feed['itunes_complete'] !== '1') {
940 unset($Feed['itunes_complete']);
941 }
942
943 $cadence_rrule_map = [
944 'daily' => ['freq' => 'DAILY', 'interval' => 1],
945 'weekly' => ['freq' => 'WEEKLY', 'interval' => 1],
946 'semiweekly' => ['freq' => 'WEEKLY', 'interval' => 1, 'byday' => 'MO,TH'],
947 'biweekly' => ['freq' => 'WEEKLY', 'interval' => 2],
948 'monthly' => ['freq' => 'MONTHLY', 'interval' => 1],
949 'semimonthly' => ['freq' => 'MONTHLY', 'interval' => 1, 'bymonthday' => '1,15'],
950 'bimonthly' => ['freq' => 'MONTHLY', 'interval' => 2],
951 ];
952
953 if (isset($cadence_rrule_map[$cadence_preset])) {
954 $Feed['update_frequency'] = $cadence_rrule_map[$cadence_preset];
955 } elseif ($cadence_preset === 'custom' && isset($Feed['update_frequency']) && is_array($Feed['update_frequency'])) {
956 $uf = $Feed['update_frequency'];
957 $assoc = [];
958
959 $valid_freq = ['DAILY', 'WEEKLY', 'MONTHLY', 'YEARLY'];
960 $freq = strtoupper(trim($uf['freq'] ?? ''));
961 if (in_array($freq, $valid_freq, true)) {
962 $assoc['freq'] = $freq;
963 }
964
965 $byday_parts = [];
966 $common_codes = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
967 if (!empty($uf['byday']) && is_array($uf['byday'])) {
968 foreach ($uf['byday'] as $code) {
969 $code = strtoupper(trim($code));
970 if (in_array($code, $common_codes, true)) $byday_parts[] = $code;
971 }
972 }
973
974 $monthly_pattern = $uf['monthly_pattern'] ?? 'bymonthday';
975 if (($freq === 'MONTHLY' || $freq === 'YEARLY') && $monthly_pattern === 'ordinal') {
976 $valid_pos = ['+1', '+2', '+3', '+4', '-1'];
977 $pos = trim($uf['ordinal_pos'] ?? '');
978 $day = strtoupper(trim($uf['ordinal_day'] ?? ''));
979 if (in_array($pos, $valid_pos, true) && in_array($day, $common_codes, true)) {
980 $byday_parts[] = $pos . $day;
981 }
982 }
983 if (!empty($byday_parts)) $assoc['byday'] = implode(',', $byday_parts);
984
985 if (($freq === 'MONTHLY' || $freq === 'YEARLY') && $monthly_pattern === 'bymonthday') {
986 $days = [];
987 if (!empty($uf['bymonthday']) && is_array($uf['bymonthday'])) {
988 foreach ($uf['bymonthday'] as $d) {
989 $d = (int) $d;
990 if ($d >= 1 && $d <= 31) $days[] = $d;
991 }
992 }
993 if (!empty($days)) $assoc['bymonthday'] = implode(',', array_unique($days));
994 }
995
996 if ($freq === 'YEARLY') {
997 $months = [];
998 if (!empty($uf['bymonth']) && is_array($uf['bymonth'])) {
999 foreach ($uf['bymonth'] as $m) {
1000 $m = (int) $m;
1001 if ($m >= 1 && $m <= 12) $months[] = $m;
1002 }
1003 }
1004 if (!empty($months)) $assoc['bymonth'] = implode(',', array_unique($months));
1005 }
1006
1007 if (isset($uf['interval']) && is_numeric($uf['interval']) && $uf['interval'] > 0) {
1008 $assoc['interval'] = (int) $uf['interval'];
1009 }
1010
1011 $ends_mode = $uf['ends_mode'] ?? 'never';
1012 if ($ends_mode === 'count' && isset($uf['count']) && is_numeric($uf['count']) && $uf['count'] > 0) {
1013 $assoc['count'] = (int) $uf['count'];
1014 } elseif ($ends_mode === 'until' && !empty($uf['until'])) {
1015 $assoc['until'] = trim($uf['until']);
1016 }
1017
1018 if (!empty($assoc['freq'])) {
1019 $Feed['update_frequency'] = $assoc;
1020 } else {
1021 unset($Feed['update_frequency']);
1022 }
1023 } else {
1024 unset($Feed['update_frequency']);
1025 }
1026
1027 // CLEAR LEGACY STORAGE KEY
1028 unset($Feed['update_frequency_week'], $Feed['update_frequency_month']);
1029 for ($i = 0; $i < 7; $i++) {
1030 unset($Feed['freq-day-' . $i]);
1031 }
1032 }
1033
1034 // =====
1035 // BLOCK
1036 // =====
1037
1038 $blockAgree = $Feed['block'] ?? false;
1039
1040 if (!isset($Feed['block_all']))
1041 $Feed['block_all'] = 0;
1042
1043 if ($blockAgree)
1044 $Feed['block_list'] = implode(';', $Feed['block_list'] ?? []);
1045
1046 // ==============================================
1047 // REMOTE ITEMS PROCESSING (PODROLL & FEED ITEMS)
1048 // ==============================================
1049
1050 $remoteItems = $Feed['remoteItems'] ?? [];
1051 if (!empty($remoteItems)) {
1052 $newRemoteItems = [];
1053 $podrollItems = $remoteItems['podroll'] ?? [];
1054 $feedItems = $remoteItems['feed'] ?? [];
1055
1056 // process podroll items
1057 foreach ($podrollItems as $podcastGuid => $itemData) {
1058 // validate required fields exist before adding
1059 if (isset($itemData['item_title']) && isset($itemData['link'])) {
1060 $newRemoteItems[] = [
1061 'feed_guid' => $podcastGuid,
1062 'item_guid' => '',
1063 'item_title' => $itemData['item_title'],
1064 'item_link' => $itemData['link'],
1065 'medium' => $itemData['medium'] ?? 'podcast',
1066 'podroll' => 1
1067 ];
1068 }
1069 }
1070
1071 // process feed items
1072 foreach ($feedItems as $podcastGuid => $itemData) {
1073 // validate required fields exist before adding
1074 if (isset($itemData['item_title']) && isset($itemData['link'])) {
1075 $newRemoteItems[] = [
1076 'feed_guid' => $podcastGuid,
1077 'item_guid' => $itemData['item_guid'] ?? '',
1078 'item_title' => $itemData['item_title'],
1079 'item_link' => $itemData['link'],
1080 'medium' => $itemData['medium'] ?? 'podcast',
1081 'podroll' => 0
1082 ];
1083 }
1084 }
1085
1086 $Feed['remote_items'] = $newRemoteItems;
1087 } else {
1088 $Feed['remote_items'] = [];
1089 }
1090
1091 // cleanup: remove the leftover preprocessed data
1092 unset($Feed['remoteItems']);
1093
1094 if( !isset($_POST['ProtectContent']) && isset($Feed['premium']) )
1095 $Feed['premium'] = false;
1096 if( !isset($Feed['itunes_author_post']) )
1097 $Feed['itunes_author_post'] = false;
1098 if( !isset($Feed['pp_enable_feed_lock']) )
1099 $Feed['pp_enable_feed_lock'] = false;
1100 if( !isset($Feed['pp_enable_email']) )
1101 $Feed['pp_enable_email'] = false;
1102 if( !isset($Feed['guid_override_check']) )
1103 $Feed['guid_override_check'] = false;
1104
1105 if( !isset($Feed['itunes_block']) )
1106 $Feed['itunes_block'] = false;
1107 if( !isset($Feed['itunes_complete']) )
1108 $Feed['itunes_complete'] = false;
1109 if( !isset($Feed['maximize_feed']) )
1110 $Feed['maximize_feed'] = false;
1111 if( !isset($Feed['unlock_podcast']) )
1112 $Feed['unlock_podcast'] = false;
1113 if( !isset($Feed['donate_link']) )
1114 $Feed['donate_link'] = false;
1115 if( !isset($Feed['episode_itunes_image']) )
1116 $Feed['episode_itunes_image'] = false;
1117
1118
1119 $Feed = powerpress_stripslashes($Feed);
1120 if( $Category )
1121 {
1122 powerpress_save_settings($Feed, 'powerpress_cat_feed_'.$Category);
1123 }
1124 else if ( $term_taxonomy_id )
1125 {
1126 powerpress_save_settings($Feed, 'powerpress_taxonomy_'.$term_taxonomy_id);
1127 }
1128 else if( $podcast_post_type )
1129 {
1130 $PostTypeSettings = array();
1131 $PostTypeSettings[ $FeedSlug ] = $Feed;
1132 powerpress_save_settings($PostTypeSettings, 'powerpress_posttype_'.$podcast_post_type);
1133 powerpress_rebuild_posttype_podcasting();
1134 }
1135 else // otherwise treat as a podcast channel
1136 {
1137 // If the settings were moved to the podcast channels feature...
1138 if( $FeedSlug == false && get_option('powerpress_feed_podcast') ) {
1139 powerpress_save_settings($Feed, 'powerpress_feed_podcast' ); // save a copy here if that is the case.
1140 }
1141
1142 $field = 'powerpress_feed'.($FeedSlug?'_'.$FeedSlug:'');
1143 $prev_feed_settings = get_option($field);
1144 $prev_itunes_image = isset($prev_feed_settings['itunes_image']) ? $prev_feed_settings['itunes_image'] : '';
1145 powerpress_save_settings($Feed, $field);
1146 }
1147
1148 // make api call to update destinations in generator
1149 $GeneralSettingsTemp = powerpress_get_settings('powerpress_general', false);
1150 if (!empty($GeneralSettingsTemp['blubrry_hosting']) && $GeneralSettingsTemp['blubrry_hosting'] !== 'false') {
1151 $creds = get_option('powerpress_creds');
1152 require_once(POWERPRESS_ABSPATH .'/powerpressadmin-auth.class.php');
1153 $auth = new PowerPressAuth();
1154
1155 $api_url_array = powerpress_get_api_array();
1156 $creds = get_option('powerpress_creds');
1157
1158 $json_data = [
1159 'itunes' => $Feed['itunes_url'] ?? '',
1160 'spotify' => $Feed['spotify_url'] ?? '',
1161 'amazon' => $Feed['amazon_url'] ?? '',
1162 'pandora' => $Feed['pandora_url'] ?? '',
1163 'iheart' => $Feed['iheart_url'] ?? '',
1164 'jiosaavn' => $Feed['jiosaavn_url'] ?? '',
1165 'podchaser' => $Feed['podchaser_url'] ?? '',
1166 'gaana' => $Feed['gaana_url'] ?? '',
1167 'pcindex' => $Feed['pcindex_url'] ?? '',
1168 'tunein' => $Feed['tunein_url'] ?? '',
1169 'deezer' => $Feed['deezer_url'] ?? '',
1170 'anghami' => $Feed['anghami_url'] ?? '',
1171 'youtube' => $Feed['youtube'] ?? '',
1172 ];
1173 if ($creds) {
1174 $accessToken = powerpress_getAccessToken();
1175 $req_url = sprintf('/2/program/%s/update/destinations', $GeneralSettingsTemp['blubrry_program_keyword']);
1176 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA')?'?'. POWERPRESS_BLUBRRY_API_QSA:'');
1177 $results = $auth->api($accessToken, $req_url, $json_data);
1178 } else {
1179 // $json_data contains destinations data, $response_data holds API response
1180 $post_data = $json_data;
1181 $response_data = false;
1182 foreach ($api_url_array as $index => $api_url) {
1183 $req_url = sprintf('%s/program/%s/update/destinations', rtrim($api_url, '/'), $GeneralSettingsTemp['blubrry_program_keyword']);
1184 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA') ? '&' . POWERPRESS_BLUBRRY_API_QSA : '');
1185 $response_data = powerpress_remote_fopen($req_url, $GeneralSettingsTemp['blubrry_auth'], $post_data, 15);
1186 if (!$response_data && $api_url == 'https://api.blubrry.com/') {
1187 // force cURL if first attempt failed
1188 $response_data = powerpress_remote_fopen($req_url, $GeneralSettingsTemp['blubrry_auth'], $post_data, 15, false, true);
1189 }
1190 if ($response_data != false) {
1191 break;
1192 }
1193 }
1194 $results = powerpress_json_decode($response_data);
1195 }
1196
1197 // SYNC FEED ARTWORK URL TO BLUBRRY DB
1198 if (isset($field, $prev_itunes_image) && !empty($Feed['itunes_image']) && $Feed['itunes_image'] !== $prev_itunes_image) {
1199 $artwork_results = powerpress_api_request(
1200 '/2/media/%s/coverart.json',
1201 [urlencode($GeneralSettingsTemp['blubrry_program_keyword'])],
1202 ['url' => $Feed['itunes_image']],
1203 $GeneralSettingsTemp,
1204 $creds,
1205 $auth,
1206 $api_url_array,
1207 30
1208 );
1209 if (is_array($artwork_results) && isset($artwork_results['error'])) {
1210 powerpress_page_message_add_error(__('Blubrry Hosting Error (updating Podcast Artwork)', 'powerpress') . ': ' . $artwork_results['error']);
1211 } else if (is_array($artwork_results) && isset($artwork_results['success'])) {
1212 powerpress_page_message_add_notice(__('Podcast Artwork synced to Blubrry.', 'powerpress'));
1213 // save Blubrry program image URL into Feed[itunes_image]
1214 if (!empty($artwork_results['image_url']) && $artwork_results['image_url'] !== $Feed['itunes_image']) {
1215 $Feed['itunes_image'] = $artwork_results['image_url'];
1216 powerpress_save_settings($Feed, $field);
1217 }
1218 }
1219 }
1220 }
1221
1222 // clear variables
1223 unset($GeneralSettingsTemp, $results);
1224 }
1225
1226 if( isset($_POST['EpisodeBoxBGColor']) )
1227 {
1228 $GeneralSettingsTemp = get_option('powerpress_general', array());
1229 $SaveEpisdoeBoxBGColor['episode_box_background_color'] = array();
1230 if( isset($GeneralSettingsTemp['episode_box_background_color']) )
1231 $SaveEpisdoeBoxBGColor['episode_box_background_color'] = $GeneralSettingsTemp['episode_box_background_color']; // copy previous settings
1232
1233 foreach( $_POST['EpisodeBoxBGColor'] as $feed_slug_temp => $background_color ) {
1234 break;
1235 }
1236 $SaveEpisdoeBoxBGColor['episode_box_background_color'][ $feed_slug_temp ] = $background_color;
1237 powerpress_save_settings($SaveEpisdoeBoxBGColor);
1238 }
1239
1240 if (isset($_POST['blubrry-login'])) {
1241 check_admin_referer('powerpress-edit');
1242 $pp_nonce = powerpress_login_create_nonce();
1243 $tab_string = isset($_POST['tab']) ? "&tab={$_POST['tab']}" : "";
1244 $sidenav_tab_string = isset($_POST['sidenav-tab']) ? "&sidenav-tab={$_POST['sidenav-tab']}" : "";
1245 header("Location: " . add_query_arg( '_wpnonce', $pp_nonce, admin_url("admin.php?page=powerpressadmin_onboarding.php&step=blubrrySignin&from=powerpressadmin_basic{$tab_string}{$sidenav_tab_string}")));
1246 }
1247
1248 // Anytime settings are saved lets flush the rewrite rules
1249 $wp_rewrite->flush_rules();
1250 // Settings saved successfully
1251 if( !empty($_POST['action']) )
1252 {
1253 switch( $_POST['action'] )
1254 {
1255 case 'powerpress-save-settings':
1256 case 'powerpress-save-defaults': {
1257 powerpress_page_message_add_notice( __('Blubrry PowerPress settings saved.', 'powerpress') );
1258 }; break;
1259 case 'powerpress-save-channel': {
1260 powerpress_page_message_add_notice( __('Blubrry PowerPress Channel settings saved.', 'powerpress') );
1261 $_GET['action'] = 'powerpress-editfeed';
1262 $_GET['feed_slug'] = $FeedSlug;
1263 }; break;
1264 case 'powerpress-save-category': {
1265 powerpress_page_message_add_notice( __('Blubrry PowerPress Category Podcasting settings saved.', 'powerpress') );
1266 $_GET['action'] = 'powerpress-editcategoryfeed';
1267 $_GET['cat'] = $Category;
1268 }; break;
1269 case 'powerpress-save-ttid': {
1270 powerpress_page_message_add_notice( __('Blubrry PowerPress Taxonomy Podcasting settings saved.', 'powerpress') );
1271 $_GET['action'] = 'powerpress-edittaxonomyfeed';
1272 if (empty($_GET['term'])) {
1273 $_GET['term'] = false;
1274 }
1275 $term_ID = intval( isset($_POST['term'])? $_POST['term'] : $_GET['term'] );
1276 $_GET['term'] = $term_ID;
1277 $_GET['ttid'] = $term_taxonomy_id;
1278 }; break;
1279 case 'powerpress-save-post_type': {
1280 powerpress_page_message_add_notice( __('Blubrry PowerPress Post Type Podcasting settings saved.', 'powerpress') );
1281 $_GET['action'] = 'powerpress-editposttypefeed';
1282 $_GET['feed_slug'] = $FeedSlug;
1283 $_GET['podcast_post_type'] = $podcast_post_type;
1284 }; break;
1285 default: {
1286 powerpress_page_message_add_notice( __('Blubrry PowerPress settings saved.', 'powerpress') );
1287 }; break;
1288 }
1289 }
1290 }
1291
1292 // Handle POST actions...
1293 if( isset($_POST['action'] ) )
1294 {
1295 switch($_POST['action'])
1296 {
1297 case 'powerpress-addfeed': {
1298 check_admin_referer('powerpress-add-feed');
1299
1300 $Settings = get_option('powerpress_general', array());
1301 $key = sanitize_title($_POST['feed_slug']);
1302 $value = $_POST['feed_name'];
1303 $value = powerpress_stripslashes($value);
1304
1305 /*
1306 if( isset($Settings['custom_feeds'][ $key ]) && empty($_POST['overwrite']) )
1307 {
1308 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" already exists.'), $key) );
1309 } else */
1310 if( $key == '' )
1311 {
1312 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" is not valid.', 'powerpress'), esc_html($_POST['feed_slug']) ) );
1313 }
1314 else if( in_array($key, $wp_rewrite->feeds) && !isset($Settings['custom_feeds'][ $key ]) ) // If it is a system feed or feed created by something else
1315 {
1316 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" is not available.', 'powerpress'), esc_html($key) ) );
1317 }
1318 else
1319 {
1320 $Settings['custom_feeds'][ $key ] = $value;
1321 powerpress_save_settings($Settings);
1322
1323 add_feed($key, 'powerpress_do_podcast_feed'); // Before we flush the rewrite rules we need to add the new custom feed...
1324 $wp_rewrite->flush_rules();
1325
1326 powerpress_page_message_add_notice( sprintf(__('Podcast Feed "%s" added, please configure your new feed now.', 'powerpress'), esc_html($value) ) );
1327 $_GET['action'] = 'powerpress-editfeed';
1328 $_GET['feed_slug'] = $key;
1329 }
1330 }; break;
1331 case 'powerpress-addtaxonomyfeed': {
1332 if( !empty($_POST['cancel']) )
1333 unset($_POST['taxonomy']);
1334
1335 if( empty($_POST['add_podcasting']) )
1336 break; // We do not handle this situation
1337 }
1338 case 'powerpress-addcategoryfeed': {
1339
1340 check_admin_referer('powerpress-add-taxonomy-feed');
1341
1342
1343
1344
1345 $taxonomy_type = ( isset($_POST['taxonomy'])? $_POST['taxonomy'] : $_GET['taxonomy'] );
1346 $term_ID = intval( isset($_POST['term'])? $_POST['term'] : $_GET['term'] );
1347
1348
1349 $term_object = get_term( $term_ID, $taxonomy_type, OBJECT, 'edit');
1350
1351 if( empty($term_ID) )
1352 {
1353 if( $taxonomy_type == 'category' )
1354 powerpress_page_message_add_error( __('You must select a category to continue.', 'powerpress') );
1355 else
1356 powerpress_page_message_add_error( __('You must select a term to continue.', 'powerpress') );
1357 }
1358 else if( $term_object == false )
1359 {
1360 powerpress_page_message_add_error( __('Error obtaining term information.', 'powerpress') );
1361 }
1362 else if( $taxonomy_type == 'category' )
1363 {
1364 $Settings = get_option('powerpress_general', array());
1365 if( empty($Settings['custom_cat_feeds']) )
1366 $Settings['custom_cat_feeds'] = array();
1367
1368 if( !in_array($term_ID, $Settings['custom_cat_feeds']) )
1369 {
1370 $Settings['custom_cat_feeds'][] = $term_ID;
1371 powerpress_save_settings($Settings);
1372 }
1373
1374 powerpress_page_message_add_notice( __('Please configure your category podcast feed now.', 'powerpress') );
1375
1376 $_GET['action'] = 'powerpress-editcategoryfeed';
1377 $_GET['cat'] = $term_ID;
1378 }
1379 else
1380 {
1381
1382
1383 //$term_info = term_exists($term_ID, $taxonomy_type);
1384 $tt_id = $term_object->term_taxonomy_id;
1385
1386 if( !$tt_id )
1387 {
1388
1389 }
1390 else
1391 {
1392 $Settings = get_option('powerpress_taxonomy_podcasting', array());
1393
1394 if( !isset($Settings[ $tt_id ]) )
1395 {
1396 $Settings[ $tt_id ] = true;
1397 powerpress_save_settings($Settings, 'powerpress_taxonomy_podcasting'); // add the feed to the taxonomy podcasting list
1398 }
1399
1400 powerpress_page_message_add_notice( __('Please configure your taxonomy podcast now.', 'powerpress') );
1401
1402 $_GET['action'] = 'powerpress-edittaxonomyfeed';
1403 $_GET['term'] = $term_ID;
1404 $_GET['ttid'] = $tt_id;
1405 }
1406 }
1407 }; break;
1408 case 'powerpress-addposttypefeed': {
1409
1410
1411 check_admin_referer('powerpress-add-posttype-feed');
1412 //die('ok 2');
1413
1414 $Settings = get_option('powerpress_general', array());
1415 $feed_slug = sanitize_title($_POST['feed_slug']);
1416 $post_type = $_POST['podcast_post_type'];
1417 $post_type = powerpress_stripslashes($post_type);
1418 $feed_title = $_POST['feed_title'];
1419 $feed_title = powerpress_stripslashes($feed_title);
1420
1421
1422
1423 /*
1424 if( isset($Settings['custom_feeds'][ $key ]) && empty($_POST['overwrite']) )
1425 {
1426 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" already exists.'), $key) );
1427 } else */
1428 if( empty($feed_slug) )
1429 {
1430 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" is not valid.', 'powerpress'), esc_html($_POST['feed_slug']) ) );
1431 }
1432 else if( empty($post_type) )
1433 {
1434 powerpress_page_message_add_error( __('Post Type is invalid.', 'powerpress') );
1435 }
1436 // TODO:
1437 //else if( in_array($feed_slug, $wp_rewrite->feeds) && !isset($Settings['custom_feeds'][ $key ]) ) // If it is a system feed or feed created by something else
1438 //{
1439 // powerpress_page_message_add_error( sprintf(__('Feed slug "%s" is not available.', 'powerpress'), $key) );
1440 //}
1441 else
1442 {
1443 $ExistingSettings = powerpress_get_settings('powerpress_posttype_'. $post_type);
1444 if( !empty($ExistingSettings[ $feed_slug ]) )
1445 {
1446 powerpress_page_message_add_error( sprintf(__('Feed slug "%s" already exists.', 'powerpress'), $_POST['feed_slug']) );
1447 }
1448 else
1449 {
1450 $NewSettings = array();
1451 $NewSettings[ $feed_slug ] = array();
1452 $NewSettings[ $feed_slug ]['title'] = $feed_title;
1453 powerpress_save_settings($NewSettings, 'powerpress_posttype_'. $post_type);
1454 powerpress_rebuild_posttype_podcasting();
1455
1456
1457 add_feed($feed_slug, 'powerpress_do_podcast_feed'); // Before we flush the rewrite rules we need to add the new custom feed...
1458 $wp_rewrite->flush_rules();
1459
1460 powerpress_page_message_add_notice( sprintf(__('Podcast "%s" added, please configure your new podcast.', 'powerpress'), $feed_title) );
1461 $_GET['action'] = 'powerpress-editposttypefeed';
1462 $_GET['feed_slug'] = $feed_slug;
1463 $_GET['podcast_post_type'] = $post_type;
1464 }
1465 }
1466 }; break;
1467 case 'powerpress-ping-sites': {
1468 check_admin_referer('powerpress-ping-sites');
1469
1470 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-ping-sites.php');
1471 powerpressadmin_ping_sites_process();
1472
1473 $_GET['action'] = 'powerpress-ping-sites';
1474 }; break;
1475 case 'powerpress-find-replace': {
1476 check_admin_referer('powerpress-find-replace');
1477
1478 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-find-replace.php');
1479 powerpressadmin_find_replace_process();
1480
1481 $_GET['action'] = 'powerpress-find-replace';
1482 }; break;
1483 case 'powerpress-importpodpress': {
1484 check_admin_referer('powerpress-import-podpress');
1485
1486 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-podpress.php');
1487 powerpressadmin_podpress_do_import();
1488
1489 $_GET['action'] = 'powerpress-podpress-epiosdes';
1490 }; break;
1491 case 'powerpress-importmt': {
1492 check_admin_referer('powerpress-import-mt');
1493
1494 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-mt.php');
1495 powerpressadmin_mt_do_import();
1496
1497 $_GET['action'] = 'powerpress-mt-epiosdes';
1498 }; break;
1499 case 'deletepodpressdata': {
1500 check_admin_referer('powerpress-delete-podpress-data');
1501
1502 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-podpress.php');
1503 powerpressadmin_podpress_delete_data();
1504
1505 }; break;
1506 case 'powerpress-category-settings': {
1507 // Save here!
1508 check_admin_referer('powerpress-category-settings');
1509
1510 if( isset($_POST['cat_casting_podcast_feeds']) && isset($_POST['cat_casting_strict']) )
1511 {
1512 $Save = array('cat_casting_podcast_feeds'=>$_POST['cat_casting_podcast_feeds'], 'cat_casting_strict'=>$_POST['cat_casting_strict']);
1513 powerpress_save_settings($Save);
1514 powerpress_page_message_add_notice( __('Settings saved successfully.', 'powerpress') );
1515 }
1516
1517 }; break;
1518 }
1519 }
1520
1521 // Handle GET actions...
1522 if( isset($_GET['action'] ) )
1523 {
1524 switch( $_GET['action'] )
1525 {
1526 case 'powerpress-sync-progad': {
1527 $blubrry_nonce = $_GET['blubrry_nonce'];
1528 $hostname = parse_url(home_url(), PHP_URL_HOST);
1529 require_once('powerpressadmin-auth.class.php');
1530 $auth = new PowerPressAuth();
1531 $accessToken = powerpress_getAccessToken();
1532 $req_url = sprintf('/2/media/prog_ad_nonce_check.json?cache=' . md5(rand(0, 999) . time()));
1533 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA') ? '?' . POWERPRESS_BLUBRRY_API_QSA : '');
1534 $req_url .= (defined('POWERPRESS_PUBLISH_PROTECTED') ? '&protected=true' : '');
1535 $postvars = array('hostname' => $hostname, 'nonce' => $blubrry_nonce);
1536 $result = $auth->api($accessToken, $req_url, $postvars, false, 15, true, true);
1537
1538 if (!empty($result['nonce_passed'])) {
1539 // schedule this check to happen in the background then refresh to get rid of query string
1540 if (!wp_next_scheduled('powerpress_sync_progad_hook')) {
1541 $scheduled = wp_schedule_single_event(time(), 'powerpress_sync_progad_hook');
1542 }
1543 wp_redirect(admin_url() . "admin.php?page=powerpressadmin_basic");
1544 } else {
1545 powerpress_page_message_add_error("Unable to verify nonce");
1546 }
1547
1548 }; break;
1549 case 'powerpress_dismiss': {
1550 update_option('powerpress_' . $_GET['notice'] . '_notice_dismissed', 'true');
1551 header('Location: ' . admin_url('admin.php?page=powerpressadmin_basic'));
1552 } break;
1553 case 'powerpress-enable-categorypodcasting': {
1554 check_admin_referer('powerpress-enable-categorypodcasting');
1555
1556 $Settings = get_option('powerpress_general', array());
1557 $Settings['cat_casting'] = 1;
1558 powerpress_save_settings($Settings);
1559
1560 wp_redirect('edit-tags.php?taxonomy=category&message=3');
1561 exit;
1562
1563 }; break;
1564 case 'powerpress-addcategoryfeed': {
1565 check_admin_referer('powerpress-add-taxonomy-feed');
1566 $cat_ID = intval($_GET['cat']);
1567
1568 $Settings = get_option('powerpress_general', array());
1569 $category = get_category($cat_ID);
1570 if( $category == false )
1571 {
1572 powerpress_page_message_add_error( __('Error obtaining category information.', 'powerpress') );
1573 }
1574 else
1575 {
1576 if( empty($Settings['custom_cat_feeds']) || !is_array($Settings['custom_cat_feeds']) )
1577 $Settings['custom_cat_feeds'] = array();
1578
1579 if( !in_array($cat_ID, $Settings['custom_cat_feeds']) )
1580 {
1581 $Settings['custom_cat_feeds'][] = $cat_ID;
1582 powerpress_save_settings($Settings);
1583 }
1584
1585 powerpress_page_message_add_notice( __('Please configure your category podcast feed now.', 'powerpress') );
1586
1587 $_GET['action'] = 'powerpress-editcategoryfeed';
1588 $_GET['cat'] = $cat_ID;
1589 }
1590 }; break;
1591 case 'powerpress-delete-feed': {
1592 $delete_slug = $_GET['feed_slug'];
1593 $force_deletion = !empty($_GET['force']);
1594 check_admin_referer('powerpress-delete-feed-'.$delete_slug);
1595
1596 $Episodes = powerpress_admin_episodes_per_feed($delete_slug);
1597
1598 if( false && $delete_slug == 'podcast' && $force_deletion == false ) // Feature disabled, you can now delete podcast specific settings
1599 {
1600 powerpress_page_message_add_error( __('Cannot delete default podcast feed.', 'powerpress') );
1601 }
1602 else if( $delete_slug != 'podcast' && $Episodes > 0 && $force_deletion == false )
1603 {
1604 powerpress_page_message_add_error( sprintf(__('Cannot delete feed. Feed contains %d episode(s).', 'powerpress'), $Episodes) );
1605 }
1606 else
1607 {
1608 $Settings = get_option('powerpress_general', array());
1609 unset($Settings['custom_feeds'][ $delete_slug ]);
1610 powerpress_save_settings($Settings); // Delete the feed from the general settings
1611 delete_option('powerpress_feed_'.$delete_slug); // Delete the actual feed settings
1612
1613 // Now we need to update the rewrite cso the cached rules are up to date
1614 if ( in_array($delete_slug, $wp_rewrite->feeds))
1615 {
1616 $index = array_search($delete_slug, $wp_rewrite->feeds);
1617 if( $index !== false )
1618 unset($wp_rewrite->feeds[$index]); // Remove the old feed
1619 }
1620
1621 // Remove feed function hook
1622 $hook = 'do_feed_' . $delete_slug;
1623 remove_action($hook, $hook, 10, 1); // This may not be necessary
1624 $wp_rewrite->flush_rules(); // This is definitely necessary
1625
1626 powerpress_page_message_add_notice( __('Feed deleted successfully.', 'powerpress') );
1627 }
1628 }; break;
1629 case 'powerpress-delete-category-feed': {
1630 $cat_ID = intval($_GET['cat']);
1631 check_admin_referer('powerpress-delete-category-feed-'.$cat_ID);
1632
1633 $Settings = get_option('powerpress_general', array());
1634 $key = array_search($cat_ID, $Settings['custom_cat_feeds']);
1635 if( $key !== false )
1636 {
1637 unset( $Settings['custom_cat_feeds'][$key] );
1638 powerpress_save_settings($Settings); // Delete the feed from the general settings
1639 }
1640 delete_option('powerpress_cat_feed_'.$cat_ID); // Delete the actual feed settings
1641
1642 powerpress_page_message_add_notice( __('Removed podcast settings for category feed successfully.', 'powerpress') );
1643 }; break;
1644 case 'powerpress-delete-taxonomy-feed': {
1645 $tt_ID = intval($_GET['ttid']);
1646 check_admin_referer('powerpress-delete-taxonomy-feed-'.$tt_ID);
1647
1648 $Settings = get_option('powerpress_taxonomy_podcasting', array());
1649 if( !empty($Settings[ $tt_ID ]) )
1650 {
1651 unset( $Settings[ $tt_ID ] );
1652 powerpress_save_settings($Settings, 'powerpress_taxonomy_podcasting'); // Delete the feed from the general settings
1653 }
1654 delete_option('powerpress_taxonomy_'.$tt_ID); // Delete the actual feed settings
1655
1656 powerpress_page_message_add_notice( __('Removed podcast settings for term successfully.', 'powerpress') );
1657 }; break;
1658 case 'powerpress-delete-posttype-feed': {
1659
1660 // check admin referer prevents xss
1661 $feed_slug = esc_attr($_GET['feed_slug']);
1662 $post_type = esc_attr($_GET['podcast_post_type']);
1663 check_admin_referer('powerpress-delete-posttype-feed-'.$post_type .'_'.$feed_slug);
1664
1665 $Settings = get_option('powerpress_posttype_'.$post_type, array());
1666 if( !empty($Settings[ $feed_slug ]) )
1667 {
1668 unset( $Settings[ $feed_slug ] );
1669 update_option('powerpress_posttype_'.$post_type, $Settings);
1670 //powerpress_save_settings($Settings, 'powerpress_posttype_'.$post_type); // Delete the feed from the general settings
1671 }
1672
1673 powerpress_page_message_add_notice( __('Removed podcast settings for post type successfully.', 'powerpress') );
1674 }; break;
1675 case 'powerpress-podpress-settings': {
1676 check_admin_referer('powerpress-podpress-settings');
1677
1678 // Import settings here..
1679 if( powerpress_admin_import_podpress_settings() )
1680 powerpress_page_message_add_notice( __('Podpress settings imported successfully.', 'powerpress') );
1681 else
1682 powerpress_page_message_add_error( __('No Podpress settings found.', 'powerpress') );
1683
1684 }; break;
1685 case 'powerpress-podcasting-settings': {
1686 check_admin_referer('powerpress-podcasting-settings');
1687
1688 // Import settings here..
1689 if( powerpress_admin_import_podcasting_settings() )
1690 powerpress_page_message_add_notice( __('Settings imported from the plugin "Podcasting" successfully.', 'powerpress') );
1691 else
1692 powerpress_page_message_add_error( __('No settings found for the plugin "Podcasting".', 'powerpress') );
1693
1694 }; break;
1695 case 'powerpress-add-feed-caps': {
1696 check_admin_referer('powerpress-add-feed-caps');
1697
1698 $ps_role = get_role('premium_subscriber');
1699 if( empty($ps_role) )
1700 {
1701 add_role('premium_subscriber', __('Premium Subscriber', 'powerpress'));
1702 $ps_role = get_role('premium_subscriber');
1703 $ps_role->add_cap('read');
1704 $ps_role->add_cap('premium_content');
1705 }
1706
1707 $users = array('administrator','editor', 'author'); // , 'contributor', 'subscriber');
1708 foreach( $users as $null => $user )
1709 {
1710 $role = get_role($user);
1711 if( !empty($role) )
1712 {
1713 if( !$role->has_cap('premium_content') )
1714 $role->add_cap('premium_content');
1715 }
1716 }
1717
1718 $General = array('premium_caps'=>true);
1719 powerpress_save_settings($General);
1720 powerpress_page_message_add_notice( __('Podcast Password Protection Capabilities for Custom Channel Feeds added successfully.', 'powerpress') );
1721
1722 }; break;
1723 case 'powerpress-remove-feed-caps': {
1724 check_admin_referer('powerpress-remove-feed-caps');
1725
1726 $users = array('administrator','editor', 'author', 'contributor', 'subscriber', 'premium_subscriber', 'powerpress');
1727 foreach( $users as $null => $user )
1728 {
1729 $role = get_role($user);
1730 if( !empty($role) )
1731 {
1732 if( $role->has_cap('premium_content') )
1733 $role->remove_cap('premium_content');
1734 }
1735 }
1736
1737 remove_role('premium_subscriber');
1738
1739 $General = array('premium_caps'=>false);
1740 powerpress_save_settings($General);
1741 powerpress_page_message_add_notice( __('Podcast Password Protection Capabilities for Custom Channel Feeds removed successfully.', 'powerpress') );
1742
1743 }; break;
1744 case 'powerpress-clear-update_plugins': {
1745 check_admin_referer('powerpress-clear-update_plugins');
1746
1747 delete_option('update_plugins'); // OLD method
1748 delete_option('_site_transient_update_plugins'); // New method
1749 powerpress_page_message_add_notice( sprintf( __('Plugins Update Cache cleared successfully. You may now to go the %s page to see the latest plugin versions.', 'powerpress'), '<a href="'. admin_url() .'plugins.php" title="'. __('Manage Plugins', 'powerpress') .'">'. __('Manage Plugins', 'powerpress') .'</a>'), 'inline');
1750
1751 }; break;
1752 case 'powerpress-reset-blubrry-connection': {
1753 check_admin_referer('powerpress-reset-blubrry-connection');
1754
1755 delete_option('powerpress_creds');
1756 powerpress_clear_blubrry_caches();
1757 $general = get_option('powerpress_general', array());
1758 unset(
1759 $general['blubrry_username'],
1760 $general['blubrry_auth'],
1761 $general['blubrry_program_keyword'],
1762 $general['blubrry_hosting']
1763 );
1764 update_option('powerpress_general', $general);
1765
1766 $signin_nonce = wp_create_nonce('powerpress-link-blubrry');
1767 $signin_url = add_query_arg(
1768 '_wpnonce',
1769 $signin_nonce,
1770 admin_url('admin.php?page=powerpressadmin_onboarding.php&step=blubrrySignin&from=tools')
1771 );
1772 wp_safe_redirect($signin_url);
1773 exit;
1774
1775 }; break;
1776 case 'powerpress-ios11-fields': {
1777 check_admin_referer('powerpress-ios11-fields');
1778
1779 $General = array('ios11_fields'=> (!empty($_REQUEST['variation'])? $_REQUEST['variation'] : '0') );
1780 powerpress_save_settings($General);
1781 powerpress_page_message_add_notice( 'iOS 11 program level fields changed.' );
1782 }; break;
1783 }
1784 }
1785
1786 if( isset($_REQUEST['action']) )
1787 {
1788 switch( $_REQUEST['action'] )
1789 {
1790 case 'powerpress-migrate-media': {
1791
1792 require_once( POWERPRESS_ABSPATH . '/powerpressadmin-migrate.php');
1793 powerpress_admin_migrate_request();
1794
1795 }; break;
1796 }
1797 }
1798
1799 // check for ongoing migration, if one exisits, call the function to display
1800 $migrationInprogress = get_option('powerpress_migrate_queued', array());
1801 $migrationComplete = get_option('powerpress_migrate_completed', array());
1802 $migrationStatus = get_option('powerpress_migrate_status', array());
1803 $migrationResults = get_option('powerpress_migrate_results', array());
1804 $oneMonthAgo = strtotime('-1 month', current_time('timestamp'));
1805
1806 // disable the cron task if:
1807 // - have have the wp-option 'powerpress_migrate_completed', they have completed all three migration steps
1808 // - the migration is over a month old
1809 // - they do not have the migration complete option but have the results option (older migrations)
1810 if (!empty($migrationComplete) || (!empty($migrationStatus) && $migrationStatus['updated_timestamp'] < $oneMonthAgo) || (empty($migrationComplete) && !empty($migrationResults))) {
1811 // unregister cron task if it still exists
1812 $timestamp = wp_next_scheduled( 'powerpress_admin_migration_hook' );
1813 wp_unschedule_event( $timestamp, 'powerpress_admin_migration_hook' );
1814 } elseif (!empty($migrationInprogress) && $_GET['page'] != 'powerpress/powerpressadmin_migrate.php') {
1815 // handles in progress, and update episode directive
1816 powerpress_admin_migration_notice();
1817 }
1818 }
1819
1820 // Handle edit from category page
1821 if( isset($_POST['from_categories']) )
1822 {
1823 wp_redirect('edit-tags.php?taxonomy=category&message=3');
1824 exit;
1825 }
1826
1827 add_filter( 'plugin_row_meta', 'powerpress_plugin_row_meta', 10, 2);
1828
1829 // Hnadle player settings
1830 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-player.php');
1831 powerpress_admin_players_init();
1832 }
1833
1834 function delete_post_refresh_player($postId) {
1835 $post_status = get_post_status($postId);
1836 $post_meta = get_post_meta($postId);
1837
1838 if ($post_status == 'publish') {
1839 foreach ($post_meta as $key => $value) {
1840 if (preg_match('/enclosure/i', $key) && count($value) > 0) {
1841 $EnclosureData = explode("\n", $value[0], 4);
1842 $mediaURL = $EnclosureData[0];
1843 $GeneralSettingsTemp = powerpress_get_settings('powerpress_general', false);
1844 if( !empty($mediaURL) && !empty($GeneralSettingsTemp['blubrry_hosting']) && $GeneralSettingsTemp['blubrry_hosting'] !== 'false' ) {
1845 require_once(POWERPRESS_ABSPATH . '/powerpressadmin-auth.class.php');
1846 $auth = new PowerPressAuth();
1847 $json_data = false;
1848 $creds = get_option('powerpress_creds');
1849 if ($creds) {
1850 $post_array = array('media_url' => urlencode($mediaURL));
1851 $accessToken = powerpress_getAccessToken();
1852 $req_url = sprintf('/2/episode/%s/delete/', $GeneralSettingsTemp['blubrry_program_keyword']);
1853 $req_url .= (defined('POWERPRESS_BLUBRRY_API_QSA') ? '?' . POWERPRESS_BLUBRRY_API_QSA : '');
1854 $results = $auth->api($accessToken, $req_url, $post_array, false, 60 * 30);
1855 }
1856 }
1857 }
1858 }
1859 }
1860 }
1861
1862 add_action('admin_init', 'powerpress_admin_init');
1863 add_action('wp_trash_post', 'delete_post_refresh_player');
1864
1865 // wp 7.1 sends document-isolation-policy on post.php/post-new.php for chromium + https,
1866 // editor becomes cross-origin isolated and the thickbox media picker cant reach self.parent,
1867 // opt the post screens out so the picker, upload + artwork pages keep working
1868 function powerpress_client_side_media_processing_enabled($enabled) {
1869 global $pagenow;
1870
1871 if (in_array($pagenow, ['post.php', 'post-new.php'], true)) {
1872 return false;
1873 }
1874
1875 return $enabled;
1876 }
1877 add_filter('wp_client_side_media_processing_enabled', 'powerpress_client_side_media_processing_enabled');
1878
1879 function powerpress_admin_notices()
1880 {
1881 $errors = get_option('powerpress_errors');
1882 if( !empty($errors) )
1883 {
1884 if( !delete_option('powerpress_errors') ) {
1885 // If for some reason we cannot delete this record, maybe we can at least update it with a blank value...
1886
1887 // wp pulls every autoload row in one query on every request, frontend + feeds included
1888 // nothing outside wp-admin reads or renders this option so we can safely set autoload to false so its called on demand in the admin only
1889 update_option('powerpress_errors', '', false);
1890 }
1891
1892 // Clear the SG cachepress plugin:
1893 if (function_exists('sg_cachepress_purge_cache')) { sg_cachepress_purge_cache(); }
1894
1895 foreach( $errors as $null => $error )
1896 echo $error;
1897 }
1898 }
1899
1900 add_action( 'admin_notices', 'powerpress_admin_notices' );
1901
1902 if (!function_exists('powerpress_save_settings')) {
1903 function powerpress_save_settings($SettingsNew=false, $field = 'powerpress_general' )
1904 {
1905 if( $field == 'powerpress_taxonomy_podcasting' || $field == 'powerpress_itunes_featured' ) { // No merging settings for these fields...
1906 update_option($field, $SettingsNew);
1907 return;
1908 }
1909 // Save general settings
1910 if( $SettingsNew )
1911 {
1912 $Settings = get_option($field);
1913 if( !is_array($Settings) )
1914 $Settings = array();
1915 foreach( $SettingsNew as $key => $value ) {
1916 $Settings[$key] = $value;
1917 }
1918 if( $field == 'powerpress_general' && !isset($Settings['timestamp']) )
1919 $Settings['timestamp'] = time();
1920
1921 if (isset($Settings['value_recipients'])) {
1922 unset(
1923 $Settings['value_pubkey'],
1924 $Settings['value_split'],
1925 $Settings['value_lightning'],
1926 $Settings['value_custom_key'],
1927 $Settings['value_custom_value'],
1928 $Settings['value_is_fee'],
1929 $Settings['value_fee']
1930 );
1931 }
1932
1933 // Special case fields, if they are empty, we can delete them., this will keep the Settings array uncluttered
1934 if( isset($Settings['feed_links']) && $Settings['feed_links'] == 0 ) // If set to default value, no need to save it in the database
1935 unset($Settings['feed_links']);
1936 // We can unset settings that are set to their defaults to save database size...
1937 if( $field == 'powerpress_general' )
1938 {
1939 if( isset($SettingsNew['new_episode_box_flag'])) {
1940 /* Switch the settings over to the actual field name (to fix FCGI mode problem with older versions of PHP.
1941 if (isset($SettingsNew['ebititle'])) {
1942 if ($SettingsNew['ebititle'] == 'false') {
1943 $Settings['new_episode_box_itunes_title'] = 2;
1944 } else {
1945 $Settings['new_episode_box_itunes_title'] = 1;
1946 $SettingsNew['new_episode_box_itunes_title'] = 1;
1947 }
1948 unset($Settings['ebititle']);
1949 }
1950
1951 if (isset($SettingsNew['ebinst'])) {
1952 if ($SettingsNew['ebinst'] == 'false') {
1953 $Settings['new_episode_box_itunes_nst'] = 2;
1954 } else {
1955 $Settings['new_episode_box_itunes_nst'] = 1;
1956 $SettingsNew['new_episode_box_itunes_nst'] = 1;
1957 }
1958 unset($Settings['ebinst']);
1959 }*/
1960
1961 if (!isset($SettingsNew['new_episode_box_embed']))
1962 $Settings['new_episode_box_embed'] = 2;
1963 if (!isset($SettingsNew['new_embed_replace_player']))
1964 $Settings['new_embed_replace_player'] = 2;
1965 if (!isset($SettingsNew['new_episode_box_no_player']))
1966 $Settings['new_episode_box_no_player'] = 2;
1967 if (!isset($SettingsNew['new_episode_box_no_links']))
1968 $Settings['new_episode_box_no_links'] = 2;
1969 if (!isset($SettingsNew['new_episode_box_no_player_and_links']))
1970 $Settings['new_episode_box_no_player_and_links'] = 2;
1971 if (!isset($SettingsNew['new_episode_box_cover_image']))
1972 $Settings['new_episode_box_cover_image'] = 2;
1973 if (!isset($SettingsNew['new_episode_box_player_size']))
1974 $Settings['new_episode_box_player_size'] = 2;
1975 if (!isset($SettingsNew['new_episode_box_subtitle']))
1976 $Settings['new_episode_box_subtitle'] = 2;
1977 if (!isset($SettingsNew['new_episode_box_summary']))
1978 $Settings['new_episode_box_summary'] = 2;
1979 if (!isset($SettingsNew['new_episode_box_author']))
1980 $Settings['new_episode_box_author'] = 2;
1981 if (!isset($SettingsNew['new_episode_box_explicit']))
1982 $Settings['new_episode_box_explicit'] = 2;
1983 if (!isset($SettingsNew['new_episode_box_pci']))
1984 $Settings['new_episode_box_pci'] = 2;
1985 if (!isset($SettingsNew['new_episode_box_block']))
1986 $Settings['new_episode_box_block'] = 2;
1987 if (!isset($SettingsNew['new_episode_box_itunes_image']))
1988 $Settings['new_episode_box_itunes_image'] = 2;
1989 if (!isset($SettingsNew['new_episode_box_order']))
1990 $Settings['new_episode_box_order'] = 2;
1991 if (!isset($SettingsNew['new_episode_box_itunes_title']))
1992 $Settings['new_episode_box_itunes_title'] = 2;
1993 if (!isset($SettingsNew['new_episode_box_itunes_nst']))
1994 $Settings['new_episode_box_itunes_nst'] = 2;
1995 if (!isset($SettingsNew['new_episode_box_gp_explicit']))
1996 $Settings['new_episode_box_gp_explicit'] = 2;
1997 if (!isset($SettingsNew['new_episode_box_feature_in_itunes']))
1998 $Settings['new_episode_box_feature_in_itunes'] = 2;
1999 } elseif(isset($SettingsNew['pp-gen-settings-tabs'])) {
2000 if (!isset($SettingsNew['skip_to_episode_settings']) || empty($SettingsNew['skip_to_episode_settings']))
2001 unset($Settings['skip_to_episode_settings']);
2002 if (!isset($SettingsNew['display_player_excerpt']) || empty($SettingsNew['display_player_excerpt']))
2003 unset($Settings['display_player_excerpt']);
2004 if (!isset($SettingsNew['hide_player_more']) || empty($SettingsNew['hide_player_more']))
2005 unset($Settings['hide_player_more']);
2006 if (!isset($SettingsNew['podcast_embed']) || empty($SettingsNew['podcast_embed']))
2007 unset($Settings['podcast_embed']);
2008 if (!isset($SettingsNew['subscribe_links']) || empty($SettingsNew['subscribe_links']))
2009 unset($Settings['subscribe_links']);
2010 if (!isset($SettingsNew['new_window_no_factor']) || empty($SettingsNew['new_window_no_factor']))
2011 unset($Settings['new_window_no_factor']);
2012 } elseif( isset($SettingsNew['powerpress_bplayer_settings'])) {
2013 unset($Settings['powerpress_bplayer_settings']);
2014 if (!isset($SettingsNew['new_episode_box_itunes_image']) || empty($SettingsNew['new_episode_box_itunes_image']))
2015 $Settings['new_episode_box_itunes_image'] = 2;
2016 if (isset($SettingsNew['bp_episode_image']) && empty($SettingsNew['bp_episode_image']))
2017 unset($Settings['bp_episode_image']);
2018 }
2019
2020
2021 if( isset($Settings['videojs_css_class']) && empty($Settings['videojs_css_class']) )
2022 unset($Settings['videojs_css_class']);
2023 if( isset($Settings['cat_casting']) && empty($Settings['cat_casting']) )
2024 unset($Settings['cat_casting']);
2025 if( isset($Settings['posttype_podcasting']) && empty($Settings['posttype_podcasting']) )
2026 unset($Settings['posttype_podcasting']);
2027 if( isset($Settings['taxonomy_podcasting']) && empty($Settings['taxonomy_podcasting']) )
2028 unset($Settings['taxonomy_podcasting']);
2029 if( isset($Settings['playlist_player']) && empty($Settings['playlist_player']) )
2030 unset($Settings['playlist_player']);
2031 if( isset($Settings['seo_feed_title']) && empty($Settings['seo_feed_title']) )
2032 unset($Settings['seo_feed_title']);
2033 if( isset($Settings['subscribe_feature_email']) && empty($Settings['subscribe_feature_email']) )
2034 unset($Settings['subscribe_feature_email']);
2035 if( isset($Settings['poster_image_video']) && empty($Settings['poster_image_video']) )
2036 unset($Settings['poster_image_video']);
2037 if( isset($Settings['poster_image_audio']) && empty($Settings['poster_image_audio']) )
2038 unset($Settings['poster_image_audio']);
2039 if( isset($Settings['itunes_image_audio']) && empty($Settings['itunes_image_audio']) )
2040 unset($Settings['itunes_image_audio']);
2041 if( isset($Settings['network_mode']) && empty($Settings['network_mode']) )
2042 unset($Settings['network_mode']);
2043 if( isset($Settings['use_caps']) && empty($Settings['use_caps']) )
2044 unset($Settings['use_caps']);
2045 }
2046 else // Feed or player settings...
2047 {
2048 if( isset($Settings['itunes_block'] ) && $Settings['itunes_block'] == 0 )
2049 unset($Settings['itunes_block']);
2050 if( isset($Settings['itunes_complete'] ) && $Settings['itunes_complete'] == 0 )
2051 unset($Settings['itunes_complete']);
2052 if( isset($Settings['maximize_feed'] ) && $Settings['maximize_feed'] == 0 )
2053 unset($Settings['maximize_feed']);
2054 if( isset($Settings['unlock_podcast'] ) && $Settings['unlock_podcast'] == 0 )
2055 unset($Settings['unlock_podcast']);
2056 if( isset($Settings['donate_link'] ) && $Settings['donate_link'] == 0 )
2057 unset($Settings['donate_link']);
2058 if( empty($Settings['donate_url']) )
2059 unset($Settings['donate_url']);
2060 if( empty($Settings['donate_label']) )
2061 unset($Settings['donate_label']);
2062 if( isset($Settings['allow_feed_comments'] ) && $Settings['allow_feed_comments'] == 0 )
2063 unset($Settings['allow_feed_comments']);
2064 if( empty($Settings['episode_itunes_image']) )
2065 unset($Settings['episode_itunes_image']);
2066 }
2067
2068 if(!empty($Settings)){
2069 if(isset($Settings['player'])){
2070 if($Settings['player'] == 'blubrrymodern'){
2071 if(!empty($_POST)){
2072 if(isset($_POST['ModernPlayer']['progress']) && isset($_POST['ModernPlayer']['border']) && isset($_POST['mode'])){
2073 if($_POST['mode'] == 'Light' || $_POST['mode'] == 'Dark'){
2074 if(preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i', $_POST['ModernPlayer']['progress']) && preg_match('/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i', $_POST['ModernPlayer']['border'])){
2075 $updatedPlayerSettings = array('mode' => $_POST['mode'], 'border' => $_POST['ModernPlayer']['border'], 'progress' => $_POST['ModernPlayer']['progress']);
2076 update_option('powerpress_bplayer', json_encode($updatedPlayerSettings));
2077 }
2078 }
2079 }
2080 }
2081 }
2082 }
2083 }
2084
2085 update_option($field, $Settings);
2086 }
2087 }
2088 }
2089
2090 function powerpress_get_settings($field, $for_editing=true)
2091 {
2092 $Settings = get_option($field, array());
2093 if( $for_editing )
2094 $Settings = powerpress_htmlspecialchars($Settings);
2095 return $Settings;
2096 }
2097
2098 function powerpress_htmlspecialchars($data)
2099 {
2100 if( !$data )
2101 return $data;
2102 if( is_array($data) )
2103 {
2104 foreach( $data as $key => $value )
2105 {
2106 if( is_array($value) )
2107 $data[$key] = powerpress_htmlspecialchars($value);
2108 else
2109 $data[$key] = htmlspecialchars($value);
2110 }
2111 reset($data);
2112 }
2113 return $data;
2114 }
2115
2116 function powerpress_stripslashes($data)
2117 {
2118 if( !$data )
2119 return $data;
2120
2121 if( !is_array($data) )
2122 return stripslashes($data);
2123
2124 foreach( $data as $key => $value )
2125 {
2126 if( is_array($value) )
2127 $data[$key] = powerpress_stripslashes($value);
2128 else
2129 $data[$key] = stripslashes($value);
2130 }
2131 reset($data);
2132 return $data;
2133 }
2134
2135 function powerpress_admin_get_post_types($capability_type = 'post')
2136 {
2137 if( !function_exists('get_post_types') || !function_exists('get_post_type_object') )
2138 return array($capability_type);
2139
2140 $return = array();
2141 $post_types = get_post_types();
2142 foreach( $post_types as $index => $post_type )
2143 {
2144 if( $post_type == 'redirect_rule' || $post_type == 'attachment' || $post_type == 'nav_menu_item' || $post_type == 'revision' || $post_type == 'action' )
2145 continue;
2146 if( $capability_type !== false )
2147 {
2148 $object = get_post_type_object($post_type);
2149 if( $object && $object->capability_type == $capability_type )
2150 $return[] = $post_type;
2151 }
2152 else
2153 {
2154 $return[] = $post_type;
2155 }
2156 }
2157 return $return;
2158 }
2159
2160 /* Rebuild powerpress_posttype_podcasting field*/
2161 function powerpress_rebuild_posttype_podcasting()
2162 {
2163 // Loop through all the posttype podcasting settings, save them into a field
2164 // array( feed-slugs => array('posttype1'=>'post type 1 title', 'posttype2'=>post type 2 title', ...) );
2165 $post_types = get_post_types();
2166 $FeedSlugPostTypeArray = array();
2167 foreach( $post_types as $index => $post_type )
2168 {
2169 $PostTypeSettingsArray = get_option('powerpress_posttype_'. $post_type, array() );
2170 if( empty($PostTypeSettingsArray ))
2171 continue;
2172
2173 foreach( $PostTypeSettingsArray as $feed_slug => $PostTypeSettings )
2174 {
2175 $FeedSlugPostTypeArray[ $feed_slug ][ $post_type ] = ( empty($PostTypeSettings['title'])? $feed_slug : $PostTypeSettings['title'] );
2176 }
2177 }
2178 update_option('powerpress_posttype-podcasting', $FeedSlugPostTypeArray);
2179 }
2180
2181 function powerpress_admin_menu()
2182 {
2183 $Powerpress = get_option('powerpress_general', array());
2184
2185 if( defined('PODPRESS_VERSION') || isset($GLOBALS['podcasting_player_id']) || isset($GLOBALS['podcast_channel_active']) || defined('PODCASTING_VERSION') )
2186 {
2187 // CRAP
2188 }
2189 else if( empty($Powerpress['use_caps']) || current_user_can('edit_podcast') )
2190 { // Otherwise we're using a version of wordpress that is not supported.
2191
2192 require_once( POWERPRESS_ABSPATH .'/views/episode-box.php');
2193 $FeedSlugPostTypesArray = array();
2194 if( !empty($Powerpress['posttype_podcasting']) )
2195 {
2196 $FeedSlugPostTypesArray = get_option('powerpress_posttype-podcasting');
2197 if( empty($FeedSlugPostTypesArray) )
2198 $FeedSlugPostTypesArray = array();
2199 }
2200
2201 if( !defined('POWERPRESS_POST_TYPES') )
2202 {
2203 $post_types = array('post'); // Only apply to default posts if post type podcasting is disabled
2204 if( empty($Powerpress['posttype_podcasting']) )
2205 $post_types = powerpress_admin_get_post_types('post'); // Get pages by capability type
2206 }
2207 else
2208 {
2209 $post_type_string = str_replace(' ', '',POWERPRESS_POST_TYPES); // Get all the spaces out
2210 $post_types = explode(',', $post_type_string);
2211 }
2212
2213 if( !empty($Powerpress['posttype_podcasting']) )
2214 {
2215 add_meta_box('powerpress-podcast', __('Podcast Episode (default)', 'powerpress'), 'powerpress_meta_box', 'post', 'normal'); // Default podcast box for post type 'post'
2216
2217 $FeedSlugPostTypesArray = get_option('powerpress_posttype-podcasting');
2218 if( empty($FeedSlugPostTypesArray) )
2219 $FeedSlugPostTypesArray = array();
2220
2221 foreach( $FeedSlugPostTypesArray as $feed_slug => $FeedSlugPostTypes )
2222 {
2223 foreach( $FeedSlugPostTypes as $post_type => $type_title )
2224 {
2225 if ( $feed_slug != 'podcast' || $post_type != 'post' ) // No the default podcast feed
2226 {
2227 $feed_title = $type_title;
2228 if( empty($feed_title) )
2229 $feed_title = $feed_slug;
2230 //echo (" $feed_slug ");
2231 add_meta_box('powerpress-'.$feed_slug, __('Podcast Episode', 'powerpress') .': '.$feed_title, 'powerpress_meta_box', $post_type, 'normal');
2232 }
2233 }
2234 }
2235 }
2236
2237 if( isset($Powerpress['custom_feeds']) )
2238 {
2239 $FeedDefaultPodcast = get_option('powerpress_feed_podcast', array());
2240
2241 foreach( $post_types as $null => $post_type )
2242 {
2243 // Make sure this post type can edit the default podcast channel...
2244 if( !empty($FeedDefaultPodcast['custom_post_type']) && $FeedDefaultPodcast['custom_post_type'] != $post_type )
2245 continue;
2246
2247 if( empty($FeedSlugPostTypesArray[ 'podcast' ][ $post_type ]) )
2248 add_meta_box('powerpress-podcast', __('Podcast Episode (default)', 'powerpress'), 'powerpress_meta_box', $post_type, 'normal');
2249 }
2250
2251 foreach( $Powerpress['custom_feeds'] as $feed_slug => $feed_title )
2252 {
2253 if( $feed_slug == 'podcast' )
2254 continue;
2255
2256 $FeedCustom = get_option('powerpress_feed_'.$feed_slug, array());
2257 $feed_slug = esc_attr($feed_slug);
2258
2259
2260 reset($post_types);
2261 foreach( $post_types as $null => $post_type )
2262 {
2263 // Make sure this post type can edit the default podcast channel...
2264 if( !empty($FeedCustom['custom_post_type']) && $FeedCustom['custom_post_type'] != $post_type )
2265 continue;
2266
2267 if( empty($FeedSlugPostTypesArray[ $feed_slug ][ $post_type ]) )
2268 add_meta_box('powerpress-'.$feed_slug, __('Podcast Episode for Custom Channel', 'powerpress') .': '. esc_attr($feed_title), 'powerpress_meta_box', $post_type, 'normal');
2269 }
2270 }
2271 reset($Powerpress['custom_feeds']);
2272 }
2273 else // This handles all podcast post types and default 'post'. if post type podcasting enabled.
2274 {
2275 reset($post_types);
2276 foreach( $post_types as $null => $post_type )
2277 {
2278 if( empty($FeedSlugPostTypesArray[ 'podcast' ][ $post_type ]) )
2279 add_meta_box('powerpress-podcast', __('Podcast Episode', 'powerpress'), 'powerpress_meta_box', $post_type, 'normal');
2280 }
2281 }
2282
2283 // For custom compatibility type set:
2284 if( isset($Powerpress['custom_feeds']) && defined('POWERPRESS_CUSTOM_CAPABILITY_TYPE') )
2285 {
2286 $post_types = powerpress_admin_get_post_types( POWERPRESS_CUSTOM_CAPABILITY_TYPE );
2287 if( !empty($post_types) )
2288 {
2289 foreach( $Powerpress['custom_feeds'] as $feed_slug => $feed_title )
2290 {
2291 if( $feed_slug == 'podcast' )
2292 continue;
2293
2294 $FeedCustom = get_option('powerpress_feed_'.$feed_slug, array());
2295
2296 reset($post_types);
2297 foreach( $post_types as $null => $post_type )
2298 {
2299 if( !empty($FeedCustom['custom_post_type']) && $FeedCustom['custom_post_type'] != $post_type )
2300 continue;
2301
2302 if( empty($FeedSlugPostTypesArray[ $feed_slug ][ $post_type ]) )
2303 add_meta_box('powerpress-'.$feed_slug, __('Podcast Episode for Custom Channel', 'powerpress') .': '.$feed_title, 'powerpress_meta_box', $post_type, 'normal');
2304 }
2305 }
2306 reset($Powerpress['custom_feeds']);
2307 }
2308 }
2309 }
2310
2311 if( current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS) ) {
2312 $Powerpress = powerpress_default_settings($Powerpress, 'basic');
2313
2314 if (isset($_GET['page']) && strstr($_GET['page'], 'powerpress') !== false && isset($_POST['General'])) {
2315 $ToBeSaved = $_POST['General'];
2316
2317 if (isset($ToBeSaved['channels']))
2318 $Powerpress['channels'] = $ToBeSaved['channels'];
2319 if (isset($ToBeSaved['cat_casting']))
2320 $Powerpress['cat_casting'] = $ToBeSaved['cat_casting'];
2321 if (isset($ToBeSaved['taxonomy_podcasting']))
2322 $Powerpress['taxonomy_podcasting'] = $ToBeSaved['taxonomy_podcasting'];
2323 if (isset($ToBeSaved['posttype_podcasting']))
2324 $Powerpress['posttype_podcasting'] = $ToBeSaved['posttype_podcasting'];
2325 if (isset($ToBeSaved['podpress_stats']))
2326 $Powerpress['podpress_stats'] = $ToBeSaved['podpress_stats'];
2327 if (isset($ToBeSaved['blubrry_hosting']))
2328 $Powerpress['blubrry_hosting'] = $ToBeSaved['blubrry_hosting'];
2329 }
2330 $Settings = get_option('powerpress_general', array());
2331 if (!empty($_GET['skip_onboarding'])) {
2332 $Settings['pp_onboarding_incomplete'] = 0;
2333 powerpress_save_settings($Settings);
2334 }
2335 if ((isset($Settings['pp_onboarding_incomplete']) && $Settings['pp_onboarding_incomplete'] == 1) && (isset($Settings['timestamp']) && $Settings['timestamp'] > 1576972800)) {
2336 $parent_slug = 'powerpressadmin_onboarding.php';
2337 $parent_slug = apply_filters('powerpress_submenu_parent_slug', $parent_slug);
2338 add_menu_page(__('PowerPress', 'powerpress'), __('PowerPress', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_onboarding.php', 'powerpress_admin_page_onboarding', powerpress_get_root_url() . 'images/PowerPress_white.png');
2339 add_submenu_page($parent_slug, __('Get Started', 'powerpress'), __('Get Started', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_onboarding.php', 'powerpress_admin_page_onboarding');
2340 add_submenu_page($parent_slug, __('PowerPress Settings', 'powerpress'), __('Settings', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_basic', 'powerpress_admin_page_basic');
2341 } else {
2342 $parent_slug = 'powerpressadmin_basic';
2343 $parent_slug = apply_filters('powerpress_submenu_parent_slug', $parent_slug);
2344 add_menu_page(__('PowerPress', 'powerpress'), __('PowerPress', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_basic', 'powerpress_admin_page_basic', powerpress_get_root_url() . 'images/PowerPress_white.png');
2345 add_submenu_page($parent_slug, __('PowerPress Settings', 'powerpress'), __('Settings', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_basic', 'powerpress_admin_page_basic');
2346 add_submenu_page($parent_slug, __('Get Started', 'powerpress'), __('Get Started', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_onboarding.php', 'powerpress_admin_page_onboarding');
2347
2348 }
2349 add_options_page(__('PowerPress', 'powerpress'), __('PowerPress', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpressadmin_basic', 'powerpress_admin_page_basic');
2350
2351 add_submenu_page($parent_slug, __('Live Item Tag.', 'powerpress'), __('Live Item', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_live_item.php', 'powerpress_admin_page_live_item');
2352
2353 add_submenu_page($parent_slug, __('Import podcast feed from SoundCloud, LibSyn, PodBean or other podcast service.', 'powerpress'), __('Import Podcast', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_import_feed.php', 'powerpress_admin_page_import_feed');
2354 add_submenu_page($parent_slug, __('Migrate media files to Blubrry Podcast Media Hosting with only a few clicks.', 'powerpress'), __('Migrate Media', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_migrate.php', 'powerpress_admin_page_migrate');
2355
2356 add_submenu_page($parent_slug, __('PowerPress Audio Player Options', 'powerpress'), __('Audio Player', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_player.php', 'powerpress_admin_page_players');
2357 add_submenu_page($parent_slug, __('PowerPress Video Player Options', 'powerpress'), __('Video Player', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_videoplayer.php', 'powerpress_admin_page_videoplayers');
2358 if (!empty($Powerpress['channels']))
2359 add_submenu_page($parent_slug, __('PowerPress Custom Podcast Channels', 'powerpress'), __('Podcast Channels', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_customfeeds.php', 'powerpress_admin_page_customfeeds');
2360 if (!empty($Powerpress['cat_casting']))
2361 add_submenu_page($parent_slug, __('PowerPress Category Podcasting', 'powerpress'), __('Category Podcasting', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_categoryfeeds.php', 'powerpress_admin_page_categoryfeeds');
2362 if (defined('POWERPRESS_TAXONOMY_PODCASTING') || !empty($Powerpress['taxonomy_podcasting']))
2363 add_submenu_page($parent_slug, __('PowerPress Taxonomy Podcasting', 'powerpress'), __('Taxonomy Podcasting', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_taxonomyfeeds.php', 'powerpress_admin_page_taxonomyfeeds');
2364 if (defined('POWERPRESS_POSTTYPE_PODCASTING') || !empty($Powerpress['posttype_podcasting']))
2365 add_submenu_page($parent_slug, __('PowerPress Post Type Podcasting', 'powerpress'), __('Post Type Podcasting', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_posttypefeeds.php', 'powerpress_admin_page_posttypefeeds');
2366 if (!empty($Powerpress['podpress_stats']))
2367 add_submenu_page($parent_slug, __('PodPress Stats', 'powerpress'), __('PodPress Stats', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_podpress-stats.php', 'powerpress_admin_page_podpress_stats');
2368 if (!empty($Powerpress['powerpress_network'])) {
2369 add_submenu_page( $parent_slug, __('PowerPress Network', 'powerpress'), __('PowerPress Network', 'powerpress'), 'manage_options', 'network-plugin', 'network_plugin' );
2370 }
2371 //if( !empty($Powerpress['blubrry_hosting']) && $Powerpress['blubrry_hosting'] !== 'false' )
2372
2373 add_submenu_page($parent_slug, __('PowerPress Tools', 'powerpress'), __('Tools', 'powerpress'), POWERPRESS_CAPABILITY_EDIT_PAGES, 'powerpress/powerpressadmin_tools.php', 'powerpress_admin_page_tools');
2374 }
2375 }
2376
2377
2378 add_action('admin_menu', 'powerpress_admin_menu');
2379
2380
2381 function network_plugin() {
2382 if (isset($GLOBALS['ppn_object'])) {
2383 $GLOBALS['ppn_object']->display_plugin();
2384 }
2385 }
2386
2387 // Save episode information
2388 function powerpress_edit_post($post_ID, $post)
2389 {
2390 if ( !current_user_can('edit_post', $post_ID) )
2391 return $post_ID;
2392
2393 $GeneralSettings = get_option('powerpress_general', array());
2394
2395 if( isset($GeneralSettings['auto_enclose']) && $GeneralSettings['auto_enclose'] )
2396 {
2397 powerpress_do_enclose($post->post_content, $post_ID, ($GeneralSettings['auto_enclose']==2) );
2398 }
2399
2400 // If the field limit is exceeded, WordPress won't send an error so we need to, as this prevents publishing
2401 // phpstan: ini_get returns string|false, cast to int and check > 0 before arithmetic
2402 $max_input_vars = (int) ini_get('max_input_vars');
2403 if( $max_input_vars > 0 && count($_POST, COUNT_RECURSIVE) > ($max_input_vars - 100) ) {
2404 // we want to display the warning message
2405 $error = "PowerPress Warning: you may be exceeding your fields limit, a server setting that limits how many fields your pages can contain. Your current limit is ";
2406 $error .= ini_get('max_input_vars') . " <a href='https://blubrry.com/support/powerpress-documentation/warning-messages-explained/'>Learn more</a>";
2407 powerpress_page_message_add_error($error);
2408 }
2409
2410 $Episodes = ( isset($_POST['Powerpress'])? $_POST['Powerpress'] : false);
2411 if( $Episodes )
2412 {
2413 $success_array = array();
2414 foreach( $Episodes as $feed_slug => $Powerpress )
2415 {
2416 $feed_slug = sanitize_title($feed_slug);
2417 $error = '';
2418 $field = 'enclosure';
2419 if (!preg_match('/^[a-z0-9]+(?:(?:-|_)+[a-z0-9]+)*$/', $feed_slug)) {
2420 powerpress_page_message_add_error('Invalid feed slug ' . htmlspecialchars($feed_slug));
2421 continue;
2422 }
2423 $chapterURL = '';
2424 if( $feed_slug != 'podcast' )
2425 $field = '_'.$feed_slug.':enclosure';
2426
2427 if( !empty($Powerpress['remove_podcast']) )
2428 {
2429 delete_post_meta( $post_ID, $field);
2430
2431 if( $feed_slug == 'podcast' ) // Clean up the old data
2432 delete_post_meta( $post_ID, 'itunes:duration');
2433 }
2434 else if( !empty($Powerpress['change_podcast']) || !empty($Powerpress['new_podcast']) )
2435 {
2436 // No URL specified, then it's not really a podcast--display a warning
2437 // check some basic episode data and save if it's there
2438 if( empty($Powerpress['url']) && ( !empty($Powerpress['itunes_image']) || !empty($Powerpress['episode_title']) || !empty($Powerpress['feed_title']) || !empty($Powerpress['summary']) || !empty($Powerpress['subtitle']) || !empty(trim($Powerpress['show_notes'] ?? ''))) ) {
2439 $Powerpress['url'] = '';
2440 $error = __('WARNING: This post contains podcast data but no podcast sound file. ', 'powerpress');
2441 if ($feed_slug != 'podcast') {
2442 $error .= __('Episode published in feed ', 'powerpress') . $feed_slug . ' ';
2443 } else {
2444 $error .= __('This episode ', 'powerpress');
2445 }
2446 $error .= __('will not be included in any podcast feed.', 'powerpress');
2447 powerpress_page_message_add_error($error);
2448
2449 } else if( empty($Powerpress['url']) && empty($Powerpress['itunes_image']) && empty($Powerpress['episode_title']) && empty($Powerpress['feed_title']) && empty($Powerpress['summary']) && empty($Powerpress['subtitle']) && empty(trim($Powerpress['show_notes'] ?? '')) ) {
2450 continue;
2451 }
2452
2453 // Initialize the important variables:
2454 $MediaURL = $Powerpress['url'];
2455
2456 // skip youtube urls from when used as enclosures
2457 if( !empty($MediaURL) && isYoutubeURL($MediaURL) ) {
2458 $error = __('Error', 'powerpress') . ": " . __('YouTube links are not allowed as podcast media files. YouTube links should be used in the Embed field or as Content Links only.', 'powerpress');
2459 powerpress_page_message_add_error($error);
2460 continue; // Skip this enclosure entirely
2461 }
2462
2463 if( !empty($GeneralSettings['default_url']) && strpos($MediaURL, 'http://') !== 0 && strpos($MediaURL, 'https://') !== 0 && empty($Powerpress['hosting']) ) // If the url entered does not start with a http:// or https://
2464 {
2465 if( !empty($MediaURL) )
2466 $MediaURL = rtrim($GeneralSettings['default_url'], '/') .'/'. ltrim($MediaURL, '/');
2467 }
2468
2469
2470
2471 // INIT
2472 $FileSize = '';
2473 $ContentType = '';
2474 $Duration = '';
2475 $set_size = $Powerpress['set_size'] ?? 0;
2476 $set_duration = $Powerpress['set_duration'] ?? 0;
2477
2478 // CONTENT TYPE
2479 $UrlParts = parse_url($Powerpress['url']);
2480 if( !empty($UrlParts['path']) )
2481 $ContentType = powerpress_get_contenttype($UrlParts['path']);
2482
2483 if( !$ContentType && !empty($Powerpress['url']) )
2484 {
2485 $error = __('Error', 'powerpress') ." [" . htmlspecialchars($Powerpress['url']) . "]: " .__('Unable to determine content type of media (e.g. audio/mpeg). Verify file extension is correct and try again.', 'powerpress');
2486 powerpress_page_message_add_error($error);
2487 continue;
2488 }
2489
2490 // MANUAL SIZE
2491 if( $set_size == 1 )
2492 $FileSize = $Powerpress['size'] ?? '';
2493
2494 // MANUAL DURATION
2495 if( $set_duration == 1 )
2496 $Duration = sprintf('%02d:%02d:%02d', $Powerpress['duration_hh'] ?? 0, $Powerpress['duration_mm'] ?? 0, $Powerpress['duration_ss'] ?? 0);
2497
2498 // AUTO-DETECT SIZE AND DURATION
2499 if( $set_size == 0 || $set_duration == 0 )
2500 {
2501 $MediaInfo = null;
2502
2503 if( !empty($Powerpress['hosting']) && !empty($Powerpress['url']) )
2504 {
2505 // blubrry hosting
2506 $MediaInfo = powerpress_get_media_info($Powerpress['url'], $Powerpress['program_keyword'] ?? '');
2507 if( isset($MediaInfo['error']) )
2508 {
2509 $error = __('Blubrry Hosting Error (media info)', 'powerpress') . ': ' . $MediaInfo['error'];
2510 powerpress_page_message_add_error($error, 'inline', ['feed_slug' => $feed_slug, 'media_file' => $Powerpress['url']]);
2511 $MediaInfo = null;
2512 }
2513 }
2514 else if( !empty($Powerpress['url']) && SSRFCheck($Powerpress['url'], $feed_slug) )
2515 {
2516 // local/external media
2517 $MediaInfo = powerpress_get_media_info_local($MediaURL, $ContentType, 0, ($set_duration == 0) ? '' : $Duration);
2518 if( isset($MediaInfo['error']) )
2519 {
2520 $error = __('Error', 'powerpress') . " (<a href=\"" . htmlspecialchars($MediaURL) . "\" target=\"_blank\">" . htmlspecialchars($MediaURL) . "</a>): {$MediaInfo['error']}";
2521 powerpress_page_message_add_error($error);
2522 $MediaInfo = null;
2523 }
2524 else if( empty($MediaInfo['length']) )
2525 {
2526 $error = __('Error', 'powerpress') . " (<a href=\"" . htmlspecialchars($MediaURL) . "\" target=\"_blank\">" . htmlspecialchars($MediaURL) . "</a>): " . __('Unable to obtain size of media.', 'powerpress');
2527 powerpress_page_message_add_error($error);
2528 $MediaInfo = null;
2529 }
2530 }
2531
2532 // apply detected values
2533 if( $MediaInfo )
2534 {
2535 if( $set_size == 0 && !empty($MediaInfo['length']) )
2536 $FileSize = $MediaInfo['length'];
2537 if( $set_duration == 0 && !empty($MediaInfo['duration']) )
2538 $Duration = powerpress_readable_duration($MediaInfo['duration'], true);
2539 }
2540 }
2541
2542 // Init
2543 $ToSerialize = array();
2544
2545 // If we made if this far, we have the content type and file size...
2546 if (!empty($MediaURL)) {
2547 $MediaURL = str_replace(array('<', '>', '"', '\''), array('', '', '', ''), $MediaURL);
2548 $EnclosureData = $MediaURL . "\n" . $FileSize . "\n" . $ContentType;
2549 } else {
2550 $EnclosureData = "no\n0\n0";
2551 }
2552
2553
2554 // Content Link
2555 $ContentLinkData = [];
2556 if (!empty($Powerpress['content_link'])) {
2557 foreach ($Powerpress['content_link'] as $i => $content_link_data) {
2558 $MediaURL = $content_link_data['url'];
2559 if (esc_url_raw(sanitize_text_field($MediaURL))) {
2560 $contentLink = ['url' => $MediaURL, 'label' => ''];
2561 if (!empty($content_link_data['label'])) {
2562 $contentLink['label'] = sanitize_text_field(stripslashes($content_link_data['label']));
2563 }
2564
2565 $ContentLinkData[] = $contentLink;
2566 unset($contentLink);
2567 }
2568 }
2569
2570 if (!empty($ContentLinkData)) {
2571 $ToSerialize['content_link'] = $ContentLinkData;
2572 }
2573 }
2574
2575 // Alternate Enclosure
2576 $AltEnclosureData = [];
2577 if (!empty($Powerpress['alternate_enclosure'])) {
2578 foreach ($Powerpress['alternate_enclosure'] as $alt_enclosure_data) {
2579 $MediaURL = str_replace(['<', '>', '"', '\''], ['', '', '', ''], $alt_enclosure_data['url']);
2580 // Check alternate enclosure hosting flag
2581 if( !empty($GeneralSettings['default_url']) && strpos($MediaURL, 'http://') !== 0 && strpos($MediaURL, 'https://') !== 0 && empty($alt_enclosure_data['hosting']) ) {
2582 if( !empty($MediaURL) ) {
2583 $MediaURL = rtrim($GeneralSettings['default_url'], '/') .'/'. ltrim($MediaURL, '/');
2584 }
2585 }
2586
2587 if (!empty($MediaURL)) {
2588 $alt_hosting = $alt_enclosure_data['hosting'] ?? 0;
2589 if ($alt_hosting == 0) { // entered a full URL, ssrf check
2590 if (!SSRFCheck($MediaURL, $feed_slug, false, "alternate enclosure url")) {
2591 continue;
2592 }
2593 }
2594 // if hosting == 1, we have an unpublished media filename, otherwise well have a URL to validate
2595 if ($alt_hosting == 1 || filter_var($MediaURL, FILTER_VALIDATE_URL)) {
2596 if (!isYoutubeURL($MediaURL)) {
2597 $FileSize = '';
2598 $ContentType = '';
2599 $Duration_alt = false;
2600 if( $set_duration == 0 )
2601 $Duration_alt = ''; // allow the duration to be detected
2602
2603 // Get the content type based on the file extension, first we have to remove query string if it exists
2604 $ContentType = false;
2605 $UrlParts = parse_url($alt_enclosure_data['url'] ?? '');
2606
2607 if (!empty($UrlParts['path'])) $ContentType = powerpress_get_contenttype($UrlParts['path']);
2608
2609 //Set the file size specified by the user
2610 $FileSize = false;
2611 if (!empty($alt_enclosure_data['length'])) { // Current Variable handling
2612 $FileSize = $alt_enclosure_data['length'];
2613 } else if (!empty($alt_enclosure_data['size'])) {
2614 $FileSize = $alt_enclosure_data['size']; // Legacy Variable handling
2615 } else if (!empty($alt_enclosure_data['hosting']) && !empty($MediaURL)) {
2616 $MediaInfo = powerpress_get_media_info($MediaURL, $Powerpress['program_keyword']);
2617 if (!isset($MediaInfo['error']) ) {
2618 $FileSize = $MediaInfo['length'];
2619 } else {
2620 $error = __('Blubrry Hosting Error (alternate enclosure media info)', 'powerpress') . ': ' . $MediaInfo['error'];
2621 powerpress_page_message_add_error($error, 'inline', ['feed_slug' => $feed_slug, 'media_file' => $MediaURL]);
2622 }
2623 }
2624 // try if all else fails (skips unpublished)
2625 if ($FileSize === false && !empty($MediaURL) && empty($alt_enclosure_data['hosting'])) {
2626 $length = getRemoteFileSize($MediaURL);
2627 if (!empty($length) && $length > 0) {
2628 $FileSize = intval(htmlspecialchars($length));
2629 }
2630 }
2631
2632
2633 $processedUris = [];
2634 if (!empty($alt_enclosure_data['uris']) && is_array($alt_enclosure_data['uris'])) {
2635 foreach ($alt_enclosure_data['uris'] as $uri_data) {
2636 $uri_value = '';
2637 $uri_hosting = '';
2638 $uri_contentType = '';
2639
2640 if (is_array($uri_data) && !empty($uri_data['uri'])) {
2641 $uri_value = $uri_data['uri'];
2642 $uri_hosting = $uri_data['hosting'] ?? '';
2643 $uri_contentType = $uri_data['contentType'] ?? '';
2644 }
2645
2646 $cleanUri = esc_url_raw(sanitize_text_field($uri_value));
2647 if (!empty($cleanUri)) {
2648 $cleanContentType = sanitize_text_field($uri_contentType);
2649 if (empty($cleanContentType)) {
2650 $cleanContentType = powerpress_get_contenttype($cleanUri);
2651 }
2652 $processedUris[] = [
2653 'uri' => $cleanUri,
2654 'hosting' => $uri_hosting,
2655 'contentType' => $cleanContentType ?: null,
2656 ];
2657 }
2658 }
2659 }
2660
2661 if (!empty($MediaURL)) {
2662 $AltEnclosureData[] = [
2663 'url' => esc_url_raw(sanitize_text_field($MediaURL)),
2664 'length' => $FileSize,
2665 'type' => $ContentType,
2666 'hosting' => $alt_enclosure_data['hosting'],
2667
2668 'title' => sanitize_text_field(stripslashes($alt_enclosure_data['title'])),
2669 'bitrate' => absint($alt_enclosure_data['bitrate']),
2670 'height' => absint($alt_enclosure_data['height'] ?? ''),
2671 'rel' => sanitize_text_field($alt_enclosure_data['rel']),
2672 'lang' => sanitize_text_field($alt_enclosure_data['lang']),
2673 'codecs' => sanitize_text_field($alt_enclosure_data['codecs']),
2674 'is_default' => isset($alt_enclosure_data['default']) ? true : false,
2675 'uris' => $processedUris,
2676 ];
2677 }
2678
2679 } else {
2680 $error = __('Error', 'powerpress') . " (<a href=\"" . htmlspecialchars($MediaURL) . "\" target=\"_blank\">" . htmlspecialchars($MediaURL) . "</a>): Youtube links not allowed for alternate enclosure. Please use a content link for this URL.";
2681 powerpress_page_message_add_error($error);
2682 }
2683 } else {
2684 $error = __('Error', 'powerpress') . " (<a href=\"" . htmlspecialchars($MediaURL) . "\" target=\"_blank\">" . htmlspecialchars($MediaURL) . "</a>): Invalid alternate enclosure URL.";
2685 powerpress_page_message_add_error($error);
2686 }
2687 }
2688 }
2689 if (!empty($AltEnclosureData)) {
2690 $ToSerialize['alternate_enclosure'] = $AltEnclosureData;
2691 }
2692 }
2693
2694 // Value Recipient
2695 if (isset($Powerpress['inherit_channel_recipients']))
2696 $ToSerialize['inherit_channel_recipient'] = $Powerpress['inherit_channel_recipients'];
2697 if (isset($Powerpress['value_recipients']) && is_array($Powerpress['value_recipients'])) {
2698 $fee_split_total = 0;
2699 $split_total = 0;
2700 $valid_recipients = [];
2701
2702 foreach ($Powerpress['value_recipients'] as $recipient_data) {
2703 if (empty($recipient_data['pubkey'])) continue;
2704 $pubkey = trim($recipient_data['pubkey']);
2705
2706 // filter 0 split
2707 $split = isset($recipient_data['split']) ? (float) sanitize_text_field($recipient_data['split']) : 0.0;
2708 if ($split <= 0) continue;
2709
2710 $is_fee = ($recipient_data['fee'] ?? 'false') === 'true';
2711
2712 if ($is_fee) {
2713 $fee_split_total += $split;
2714 } else {
2715 $split_total += $split;
2716 }
2717
2718 $valid_recipients[] = [
2719 // accepts emails (fountain.fm, alby) or lnurls, sanitize_email can break lnurl format
2720 'lightning' => sanitize_text_field($recipient_data['lightning'] ?? ''),
2721 'pubkey' => sanitize_text_field($recipient_data['pubkey']),
2722 'custom_key' => sanitize_text_field($recipient_data['custom_key']),
2723 'custom_value' => sanitize_text_field($recipient_data['custom_value']),
2724 'split' => $split,
2725 'fee' => $is_fee ? 'true' : 'false'
2726 ];
2727 }
2728
2729 if ($split_total > 100)
2730 powerpress_page_message_add_error(__('Regular recipient splits exceed 100%. Please adjust split percentages.', 'powerpress'));
2731
2732 if ($fee_split_total > 100)
2733 powerpress_page_message_add_error(__('Fee recipient splits exceed 100%. Please adjust fee percentages.', 'powerpress'));
2734
2735 $ToSerialize['value_recipients'] = $valid_recipients;
2736 }
2737
2738 // Location
2739 $location_data = [];
2740 if (!empty($Powerpress['location']) && is_array($Powerpress['location'])) {
2741
2742 foreach ($Powerpress['location'] as $location_info) {
2743 $address = '';
2744 if (!empty($location_info['location'])) {
2745 $address = $location_info['location'];
2746 } elseif (!empty($location_info['address'])) {
2747 $address = $location_info['address'];
2748 }
2749 // requires address
2750 if (empty($address)) continue;
2751 $address = powerpress_trim_value(stripslashes($address), 'address');
2752
2753 $location_data[] = [
2754 'address' => sanitize_text_field($address),
2755 'geo' => sanitize_text_field($location_info['pci_geo']),
2756 'osm' => sanitize_text_field($location_info['pci_osm']),
2757 'rel' => sanitize_text_field($location_info['pci_rel'] ?? '') ?: '1',
2758 'country' => sanitize_text_field($location_info['pci_country'])
2759 ];
2760 }
2761
2762 if (!empty($location_data)) {
2763 $ToSerialize['location'] = $location_data;
2764 }
2765 }
2766
2767 if( !empty($Powerpress['hosting']) && $Powerpress['hosting'] != '0' )
2768 $ToSerialize['hosting'] = 1;
2769
2770 // Credits
2771 $credit_data = [];
2772 if (!empty($Powerpress['inherit_channel_credits']))
2773 $ToSerialize['inherit_channel_credits'] = 1;
2774 if (!empty($Powerpress['credits'])) {
2775 foreach ($Powerpress['credits'] as $credit) {
2776 if (empty($credit['name'])) continue;
2777 $credit_name = powerpress_trim_value(stripslashes($credit['name']), 'credit_name');
2778
2779 $credit_data[] = [
2780 'name' => sanitize_text_field($credit_name),
2781 'role' => sanitize_text_field($credit['role']),
2782 'person_url' => esc_url_raw(sanitize_text_field($credit['person_url'])),
2783 'link_url' => esc_url_raw(sanitize_text_field($credit['link_url'])),
2784 ];
2785 }
2786
2787 $ToSerialize['credits'] = $credit_data;
2788 }
2789
2790 // Soundbite
2791 $soundbites_data = [];
2792 if (!empty($Powerpress['soundbites']) && is_array($Powerpress['soundbites'])) {
2793 foreach ($Powerpress['soundbites'] as $soundbite) {
2794 $startParsed = explode(':', $soundbite['start']);
2795 $startSecs = intval($startParsed[0]) * 60 * 60 + intval($startParsed[1]) * 60 + intval($startParsed[2]);
2796
2797 // parse duration
2798 $durParsed = explode(':', $soundbite['duration']);
2799 $durSecs = intval($durParsed[0]) * 60 * 60 + intval($durParsed[1]) * 60 + intval($durParsed[2]);
2800
2801 if ($startSecs === 0 || $durSecs === 0) continue;
2802
2803 $soundbite_title = powerpress_trim_value(stripslashes($soundbite['title']), 'soundbite_title');
2804
2805 $soundbites_data[] = [
2806 'start' => $startSecs,
2807 'duration' => $durSecs,
2808 'title' => sanitize_text_field($soundbite_title)
2809 ];
2810 }
2811
2812 if (!empty($soundbites_data)) {
2813 $ToSerialize['soundbites'] = $soundbites_data;
2814 }
2815 }
2816
2817
2818 if (isset($Powerpress['vts'])) {
2819 $existingVtsInfo = get_option('vts_'.$feed_slug.'_'.$post_ID, array());
2820 $newVtsInfo = [];
2821
2822 foreach ($Powerpress['vts'] as $vts_id => $vts_info) {
2823 $startParsed = explode(':', $vts_info['start_time']);
2824 $startSecs = intval($startParsed[0]) * 60 * 60 + intval($startParsed[1]) * 60 + intval($startParsed[2]);
2825
2826 $durationParsed = explode(':', $vts_info['duration']);
2827 $durationSeconds = intval($durationParsed[0]) * 60 * 60 + intval($durationParsed[1]) * 60 + intval($durationParsed[2]);
2828
2829 // use existing vts info if available, otherwise create new
2830 $newVtsInfo[$vts_id] = $existingVtsInfo[$vts_id] ?? [];
2831 $newVtsInfo[$vts_id]['start_time'] = $startSecs;
2832 $newVtsInfo[$vts_id]['duration'] = $durationSeconds;
2833 $newVtsInfo[$vts_id]['vts_id'] = $vts_id;
2834
2835 if (!empty($newVtsInfo[$vts_id]['recipient']) && $newVtsInfo[$vts_id]['recipient'] == 1) {
2836 $valueRecipients = $newVtsInfo[$vts_id]['value_recipients'] ?? [];
2837 $splitSum = 0;
2838
2839 foreach ($valueRecipients as $valueRecipient) {
2840 $splitSum += intval($valueRecipient['split']);
2841 }
2842
2843 $newValueRecipients = [];
2844
2845 foreach ($valueRecipients as $valueRecipient) {
2846 $newSplit = $valueRecipient['split'] / $splitSum * 100;
2847 $newValueRecipient = $valueRecipient;
2848 $newValueRecipient['split'] = $newSplit;
2849 $newValueRecipients[] = $newValueRecipient;
2850 }
2851 }
2852 }
2853
2854 foreach ($newVtsInfo as $vts_key => $vts_info) {
2855 if (!isset($vts_info['recipient']))
2856 unset($newVtsInfo[$vts_key]);
2857
2858 if (!isset($vts_info['start_time']))
2859 unset($newVtsInfo[$vts_key]);
2860
2861 if (!isset($vts_info['duration']))
2862 unset($newVtsInfo[$vts_key]);
2863 }
2864
2865 update_option('vts_'.$feed_slug.'_'.$post_ID, $newVtsInfo);
2866
2867 usort($newVtsInfo, function($a, $b) {
2868 return $a['start_time'] < $b['start_time'] ? -1 : 1;
2869 });
2870
2871 $vtsOrder = array();
2872 foreach ($newVtsInfo as $vts_key => $vts_info) {
2873 $vtsOrder[] = $vts_info['vts_id'];
2874 }
2875
2876 $ToSerialize['vts_order'] = $vtsOrder;
2877 }
2878
2879 // Social Interact
2880 $social_interact_data = [];
2881 // Skip processing social interact for this episode if disabled
2882 if (!empty($Powerpress['disable_episode_comments'])) {
2883 $ToSerialize['disable_episode_comments'] = 1;
2884 } else if (!empty($Powerpress['social_interact']) && is_array($Powerpress['social_interact'])) {
2885 foreach ($Powerpress['social_interact'] as $social_interact) {
2886 if (empty($social_interact['uri']) || empty($social_interact['protocol'])) continue;
2887
2888 // Clean input before saving
2889 $social_interact_data[] = [
2890 'uri' => esc_url_raw(sanitize_text_field($social_interact['uri'])),
2891 'protocol' => sanitize_text_field($social_interact['protocol']),
2892 'account_id' => sanitize_text_field($social_interact['account_id']),
2893 'accountUrl' => esc_url_raw(sanitize_text_field($social_interact['accountUrl']))
2894 ];
2895 }
2896 // Serialize the remaining array members
2897 if (!empty($social_interact_data)) {
2898 $ToSerialize['social_interact'] = $social_interact_data;
2899 }
2900 }
2901
2902 // podcast:funding
2903 $donate_url = '';
2904 $donate_label = '';
2905 // Clean input
2906 if (!empty($Powerpress['donate_url'])) {
2907 $donate_url = esc_url_raw(sanitize_text_field($Powerpress['donate_url']));
2908 }
2909 if (!empty($Powerpress['donate_label'])) {
2910 $donate_label = powerpress_trim_value(stripslashes($Powerpress['donate_label']), 'donate_label');
2911 $donate_label = sanitize_text_field($donate_label);
2912 }
2913
2914 if ($donate_url !== '') {
2915 $ToSerialize['donate_url'] = $donate_url;
2916 $ToSerialize['donate_label'] = ($donate_label !== '') ? $donate_label : '';
2917 }
2918
2919 // podcast:license
2920 if (!empty($Powerpress['copyright'])) {
2921 $copyright = powerpress_trim_value(stripslashes($Powerpress['copyright']), 'copyright');
2922 $copyright = sanitize_text_field($copyright);
2923
2924 $copyright_url = '';
2925 if (!empty($Powerpress['copyright_url'])) {
2926 $copyright_url = esc_url_raw(sanitize_text_field($Powerpress['copyright_url']));
2927 }
2928 // Serialize
2929 $ToSerialize['copyright'] = $copyright;
2930 $ToSerialize['copyright_url'] = $copyright_url;
2931 }
2932
2933 // iTunes duration
2934 if( $Duration && ltrim($Duration, '0:') != '' ) // If all the zeroz and : are trimmed from the front and you're left with an empty value then don't save it.
2935 $ToSerialize['duration'] = $Duration; // regular expression '/^(\d{1,2}\:)?\d{1,2}\:\d\d$/i' (examples: 1:23, 12:34, 1:23:45, 12:34:56)
2936
2937 if (isset($Powerpress['set_duration'])) {
2938 $ToSerialize['set_duration'] = $Powerpress['set_duration'];
2939 }
2940 if (isset($Powerpress['set_size'])) {
2941 $ToSerialize['set_size'] = $Powerpress['set_size'];
2942 }
2943
2944 // // iTunes keywords
2945 // if( isset($Powerpress['keywords']) && trim($Powerpress['keywords']) != '' )
2946 // $ToSerialize['keywords'] = stripslashes($Powerpress['keywords']);
2947
2948 // Google Play Description
2949 if( isset($Powerpress['gp_desc']) && trim($Powerpress['gp_desc']) != '' )
2950 $ToSerialize['gp_desc'] = stripslashes($Powerpress['gp_desc']);
2951 // iTunes Author
2952 if( isset($Powerpress['author']) && trim($Powerpress['author']) != '' )
2953 $ToSerialize['author'] = stripslashes($Powerpress['author']);
2954 // iTunes Explicit
2955 if( isset($Powerpress['explicit']) && trim($Powerpress['explicit']) != '' )
2956 $ToSerialize['explicit'] = stripslashes($Powerpress['explicit']);
2957 // Google Play Explicit
2958 if( isset($Powerpress['gp_explicit']) && trim($Powerpress['gp_explicit']) == '1' )
2959 $ToSerialize['gp_explicit'] = stripslashes($Powerpress['gp_explicit']);
2960 // iTunes Episode image
2961 if( isset($Powerpress['itunes_image']) && trim($Powerpress['itunes_image']) != '' )
2962 $ToSerialize['itunes_image'] = stripslashes($Powerpress['itunes_image']);
2963
2964 if( isset($Powerpress['episode_title']) && trim($Powerpress['episode_title']) != '' )
2965 $ToSerialize['episode_title'] = stripslashes($Powerpress['episode_title']);
2966 if( isset($Powerpress['episode_no']) && trim($Powerpress['episode_no']) != '' ) {
2967 if (intval($Powerpress['episode_no']) < 0) {
2968 $Powerpress['episode_no'] = -1 * intval($Powerpress['episode_no']);
2969 }
2970 $ToSerialize['episode_no'] = (int)floor($Powerpress['episode_no']);
2971 }
2972 if ( isset($Powerpress['episode_no_display']) && $Powerpress['episode_no_display'] != '' ) {
2973 $ep_no_display = powerpress_trim_value(stripslashes($Powerpress['episode_no_display']), 'episode_no_display');
2974 $ToSerialize['episode_no_display'] = sanitize_text_field($ep_no_display);
2975 }
2976
2977 // Show Notes
2978 if ( isset($Powerpress['show_notes']) && trim($Powerpress['show_notes']) != '' ) {
2979 $show_notes = powerpress_trim_value(stripslashes($Powerpress['show_notes']), 'description');
2980 $ToSerialize['show_notes'] = wp_kses_post($show_notes);
2981 }
2982
2983 // Txt Tag
2984 if (!empty($Powerpress['txt_tag']) && is_array($Powerpress['txt_tag'])) {
2985 $txt_tag_data = [];
2986
2987 foreach($Powerpress['txt_tag'] as $tag) {
2988 // Sanitize
2989 $tag_content = isset($tag['tag']) ? sanitize_textarea_field(stripslashes($tag['tag'])) : '';
2990 $tag_purpose = isset($tag['purpose']) ? sanitize_text_field(stripslashes($tag['purpose'])) : '';
2991
2992 $tag_content = powerpress_trim_value($tag_content, 'tag_content');
2993 $tag_purpose = powerpress_trim_value($tag_purpose, 'tag_purpose');
2994
2995 if (empty($tag_content)) continue;
2996 if ($tag_purpose === 'applepodcastsverify') continue;
2997
2998 $txt_tag_data[] = [
2999 'tag' => $tag_content,
3000 'purpose' => $tag_purpose
3001 ];
3002 }
3003 if (!empty($txt_tag_data)) {
3004 $ToSerialize['txt_tag'] = $txt_tag_data;
3005 }
3006 }
3007
3008 if( isset($Powerpress['season']) && trim($Powerpress['season']) != '' ) {
3009 if (intval($Powerpress['season']) < 0) {
3010 $Powerpress['season'] = -1 * intval($Powerpress['season']);
3011 }
3012 $ToSerialize['season'] = stripslashes($Powerpress['season']);
3013 }
3014 if( isset($Powerpress['episode_type']) && trim($Powerpress['episode_type']) != '' )
3015 $ToSerialize['episode_type'] = stripslashes($Powerpress['episode_type']);
3016 else
3017 $ToSerialize['episode_type'] = 'full';
3018
3019 // always
3020 if( isset($Powerpress['always']) && trim($Powerpress['always']) != '' )
3021 $ToSerialize['always'] = stripslashes($Powerpress['always']);
3022 // iTunes Block
3023 if( isset($Powerpress['block']) && $Powerpress['block'] == '1' )
3024 $ToSerialize['block'] = 1;
3025 // Google Play Block
3026 if( isset($Powerpress['gp_block']) && $Powerpress['gp_block'] == '1' )
3027 $ToSerialize['gp_block'] = 1;
3028 // Player Embed
3029 if( isset($Powerpress['embed']) && trim($Powerpress['embed']) != '' )
3030 $ToSerialize['embed'] = SanitizeEmbed(stripslashes($Powerpress['embed'])); // we have to strip slahes if they are present befure we serialize the data
3031 if( isset($Powerpress['image']) && trim($Powerpress['image']) != '' )
3032 $ToSerialize['image'] = stripslashes($Powerpress['image']);
3033 if( isset($Powerpress['no_player']) && $Powerpress['no_player'] )
3034 $ToSerialize['no_player'] = 1;
3035 if( isset($Powerpress['no_links']) && $Powerpress['no_links'] )
3036 $ToSerialize['no_links'] = 1;
3037 if( isset($Powerpress['ishd']) && $Powerpress['ishd'] )
3038 $ToSerialize['ishd'] = 1;
3039 if( isset($Powerpress['program_keyword']) && !empty($Powerpress['program_keyword']) )
3040 $ToSerialize['program_keyword'] = $Powerpress['program_keyword'];
3041 if( isset($Powerpress['width']) && trim($Powerpress['width']) )
3042 $ToSerialize['width'] =stripslashes( trim($Powerpress['width']));
3043 if( isset($Powerpress['height']) && trim($Powerpress['height']) )
3044 $ToSerialize['height'] = stripslashes(trim($Powerpress['height']));
3045 if( !empty($Powerpress['feed_title']) && trim($Powerpress['feed_title']) )
3046 $ToSerialize['feed_title'] = stripslashes(trim($Powerpress['feed_title']));
3047 if( !empty($Powerpress['category']) )
3048 $ToSerialize['category'] = stripslashes($Powerpress['category']);
3049 if( isset($Powerpress['transcript']['upload']) && $Powerpress['transcript']['upload'] ) {
3050 $ToSerialize['pci_transcript'] = 1;
3051 if (isset($Powerpress['pci_transcript_url']) && trim($Powerpress['pci_transcript_url']) != '') {
3052 if (strpos($Powerpress['pci_transcript_url'], 'http') !== 0) {
3053 powerpress_page_message_add_error(__('Transcript Error: Transcript should be a link, starting with http.', 'powerpress'));
3054 } else {
3055 $ToSerialize['pci_transcript_url'] = str_replace(array('<', '>', '"', '\''), array('', '', '', ''), stripslashes($Powerpress['pci_transcript_url']));
3056 }
3057 }
3058 if (isset($Powerpress['pci_transcript_language']) && trim($Powerpress['pci_transcript_language']) != '') {
3059 $ToSerialize['pci_transcript_language'] = powerpress_valid_language(stripslashes($Powerpress['pci_transcript_language']));
3060 }
3061 }
3062 if( isset($Powerpress['transcript']['generate']) && $Powerpress['transcript']['generate'] ) {
3063 $ToSerialize['pci_transcript'] = 1;
3064 if (isset($Powerpress['pci_transcript_language']) && trim($Powerpress['pci_transcript_language']) != '') {
3065 $ToSerialize['pci_transcript_language'] = powerpress_valid_language(stripslashes($Powerpress['pci_transcript_language']));
3066 }
3067 }
3068 if (!empty($Powerpress['chapters']['edit'])) {
3069 if (!empty($Powerpress['chapters']['upload'])) {
3070 if (isset($Powerpress['pci_chapters_url']) && trim($Powerpress['pci_chapters_url']) != '') {
3071 if (strpos($Powerpress['pci_chapters_url'], 'http') !== 0 || !SSRFCheck($Powerpress['pci_chapters_url'], $feed_slug, false, "chapters URL")) {
3072 powerpress_page_message_add_error(__('Chapters Error: Invalid URL.', 'powerpress'));
3073 } else {
3074 $ToSerialize['pci_chapters'] = 1;
3075 $ToSerialize['pci_chapters_url'] = stripslashes($Powerpress['pci_chapters_url']);
3076 $chapterURL = $ToSerialize['pci_chapters_url'];
3077 }
3078 }
3079 }
3080 if (!empty($Powerpress['chapters']['manual'])) {
3081 $ToSerialize['pci_chapters'] = 1;
3082 $jsonChapters = array(
3083 'version' => '1.2.0',
3084 'chapters' => []
3085 );
3086
3087 $uploadPath = wp_upload_dir()['basedir'] . '/' . $feed_slug . '/' . intval($_POST['post_ID']);
3088 $uploadURL = wp_upload_dir()['baseurl'] . '/' . $feed_slug . '/' . intval($_POST['post_ID']);
3089 if (!is_dir($uploadPath)) {
3090 wp_mkdir_p($uploadPath);
3091 wp_mkdir_p($uploadPath . "/images");
3092 }
3093
3094
3095 $ToSerialize['pci_chapters_manual'] = 1;
3096
3097
3098 $chapterStarts = $_POST[$feed_slug."-starts"];
3099 $chapterTitles = $_POST[$feed_slug."-titles"];
3100 $chapterURLs = $_POST[$feed_slug."-urls"];
3101 $chapterIms = $_POST[$feed_slug."-images"] ?? [];
3102 $existingIms = $_POST[$feed_slug."-existingIms"];
3103 $removeIms = $_POST[$feed_slug."-removeExisting"];
3104
3105 $numChapters = 0;
3106 if (!empty($chapterStarts)) {
3107 $numChapters = count($chapterStarts);
3108 }
3109 $tempChapters = array();
3110
3111 for ($i = 0; $i < $numChapters; $i++) {
3112 if ($chapterStarts[$i] == "" || $chapterTitles[$i] == "") {
3113 continue;
3114 }
3115
3116 $startParsed = explode(':', $chapterStarts[$i]);
3117 $title = $chapterTitles[$i];
3118 $url = $chapterURLs[$i];
3119 $fileName = basename($chapterIms[$i] ?? '');
3120 // only check filename ext when value is set
3121 if (!empty($fileName)) {
3122 $ext = substr($fileName, strrpos($fileName, '.') + 1);
3123 $acceptable_extensions = ['jpg', 'jpeg', 'png'];
3124 if (!in_array(strtolower($ext), $acceptable_extensions)) {
3125 $error = __('Error: invalid chapter image filetype ' . $ext . ' ' . $fileName . ' ' . print_r($existingIms, true), 'powerpress');
3126 powerpress_page_message_add_error($error);
3127 continue; // skip chapter when unacceptable type
3128 }
3129 }
3130 $fileURL = $chapterIms[$i] ?? '';
3131 $existingIm = $existingIms[$i];
3132 $removeIm = $removeIms[$i];
3133
3134 $startSecs = intval($startParsed[0]) * 60 * 60 + intval($startParsed[1]) * 60 + intval($startParsed[2]);
3135 $tempChapters["$startSecs"] = array(
3136 'title' => $title,
3137 'url' => $url,
3138 'img' => array(
3139 'existing_file' => $existingIm,
3140 'existing_file_name' => basename($existingIm),
3141 'remove_existing' => $removeIm == '1',
3142 'new_file_name' => $fileName,
3143 'new_file' => $fileURL
3144 )
3145 );
3146 }
3147
3148 ksort($tempChapters);
3149
3150 $uploadPath = wp_upload_dir()['basedir'] . '/' . $feed_slug . '/' . intval($_POST['post_ID']);
3151 $uploadURL = wp_upload_dir()['baseurl'] . '/' . $feed_slug . '/' . intval($_POST['post_ID']);
3152 if (!is_dir($uploadPath)) {
3153 wp_mkdir_p($uploadPath);
3154 wp_mkdir_p($uploadPath . "/images");
3155 }
3156
3157 foreach ($tempChapters as $startTime => $chapterInfo) {
3158 $chapter = array(
3159 'startTime' => intval($startTime),
3160 'title' => $chapterInfo['title'],
3161 );
3162
3163 if (!empty($chapterInfo['url'])) {
3164 $chapter['url'] = $chapterInfo['url'];
3165 }
3166
3167 $img = $chapterInfo['img'];
3168
3169 if ($img['existing_file'] != '' && $img['new_file_name'] == '') {
3170 $chapter['img'] = $img['existing_file'];
3171 } elseif ($img['new_file_name'] != '') {
3172 // first, check if the image is hosted on this site and if so, access it directly rather than over http
3173 if (strpos($img['new_file'], wp_upload_dir()['baseurl']) !== false) {
3174 $image_req_url = str_replace(wp_upload_dir()['baseurl'], wp_upload_dir()['basedir'], $img['new_file']);
3175 } else {
3176 $image_req_url = $img['new_file'];
3177 if (!SSRFCheck($image_req_url, $feed_slug, false, "chapter image url")) {
3178 continue;
3179 }
3180 }
3181 file_put_contents($uploadPath . "/images/" . $img['new_file_name'], file_get_contents($image_req_url));
3182 $chapter['img'] = $uploadURL . "/images/" . $img['new_file_name'];
3183 }
3184
3185 if ($img['existing_file'] != '' && $img['remove_existing']) {
3186 if ($img['new_file_name'] == '') {
3187 unset($chapter['img']);
3188 }
3189 unlink($uploadPath . "/images/" . $img['existing_file_name']);
3190 }
3191
3192 $jsonChapters['chapters'][] = $chapter;
3193 }
3194
3195 $json = json_encode($jsonChapters);
3196
3197 $fname = "temp_chapters.json";
3198 $tempFile = tempnam(sys_get_temp_dir(), $fname);
3199 // phpstan: tempnam, json_encode, fopen can return false, check before file operations
3200 if ($tempFile !== false && $json !== false) {
3201 $file = fopen($tempFile, 'w');
3202 if ($file !== false) {
3203 fwrite($file, $json);
3204 fclose($file);
3205 file_put_contents($uploadPath . "/chapters.json", file_get_contents($tempFile));
3206 unlink($tempFile);
3207 }
3208 }
3209
3210 $chapterURL = $uploadURL . "/chapters.json";
3211
3212 $ToSerialize['pci_chapters_url'] = $chapterURL;
3213
3214 }
3215 } else if (!empty($Powerpress['pci_chapters_url'])) {
3216 // if the transcript has not been changed, carry it through
3217 if (strpos($Powerpress['pci_chapters_url'], 'http') !== 0 || !SSRFCheck($Powerpress['pci_chapters_url'], $feed_slug, false, "chapters URL")) {
3218 powerpress_page_message_add_error(__('Chapters Error: Invalid URL.', 'powerpress'));
3219 } else {
3220 $ToSerialize['pci_chapters'] = 1;
3221 $ToSerialize['pci_chapters_manual'] = !empty($Powerpress['chapters']['manual']) ? 1 : 0;
3222 $ToSerialize['pci_chapters_url'] = stripslashes($Powerpress['pci_chapters_url']);
3223 $ToSerialize['write_chapters_to_id3'] = !empty($Powerpress['write_chapters_to_id3']) ? 1 : 0;
3224 $chapterURL = $ToSerialize['pci_chapters_url'];
3225 }
3226 } else {
3227 $chapterURL = '';
3228 }
3229 if( isset($Powerpress['pci_soundbites']) && $Powerpress['pci_soundbites'] )
3230 $ToSerialize['pci_soundbites'] = 1;
3231
3232 if( isset($Powerpress['no_player_and_links']) && $Powerpress['no_player_and_links'] )
3233 {
3234 $ToSerialize['no_player'] = 1;
3235 $ToSerialize['no_links'] = 1;
3236 }
3237
3238 if (isset($Powerpress['podcast_id'])) {
3239 $ToSerialize['podcast_id'] = $Powerpress['podcast_id'];
3240 }
3241
3242 // WebM Support:
3243 if( !empty($Powerpress['webm_src']) )
3244 {
3245 $WebMSrc = $Powerpress['webm_src'];
3246 if( !empty($GeneralSettings['default_url']) && strpos($WebMSrc, 'http://') !== 0 ) // && $Powerpress['hosting'] != 1 ) // If the url entered does not start with a http://
3247 {
3248 $WebMSrc = rtrim($GeneralSettings['default_url'], '/') .'/'. ltrim($WebMSrc, '/');
3249 }
3250 $ToSerialize['webm_src'] = $WebMSrc;
3251
3252 $MediaInfo = powerpress_get_media_info_local($WebMSrc, 'video/webm', 0, '');
3253 if( isset($MediaInfo['error']) )
3254 {
3255 $error = __('Error', 'powerpress') ." (" . htmlspecialchars($WebMSrc) . "): {$MediaInfo['error']}";
3256 powerpress_page_message_add_error($error);
3257 }
3258 else if( empty($MediaInfo['length']) )
3259 {
3260 $error = __('Error', 'powerpress') ." (" . htmlspecialchars($WebMSrc) . "): ". __('Unable to obtain size of media.', 'powerpress');
3261 powerpress_page_message_add_error($error);
3262 }
3263 else
3264 {
3265 $ToSerialize['webm_length'] = $MediaInfo['length'];
3266 }
3267 }
3268
3269 if( ($Powerpress['set_duration'] ?? 0) == -1 )
3270 unset($ToSerialize['duration']);
3271 if( count($ToSerialize) > 0 ) // Lets add the serialized data
3272 $EnclosureData .= "\n".serialize( $ToSerialize );
3273
3274 if( !empty($Powerpress['new_podcast']) )
3275 {
3276 add_post_meta($post_ID, $field, $EnclosureData, true);
3277 }
3278 else
3279 {
3280 update_post_meta($post_ID, $field, $EnclosureData);
3281 }
3282
3283 if( !empty($ToSerialize['category']) )
3284 {
3285 $Categories = wp_get_post_categories($post_ID);
3286 $default_cat = (int) get_option('default_category');
3287
3288 // REPLACE W/ SELECTED CAT IF ONLY THE DEFAULT CAT IS SET
3289 if(count($Categories) === 1 && in_array($default_cat, $Categories)) {
3290 wp_set_post_categories($post_ID, array($ToSerialize['category']), false);
3291 } else if(!in_array($ToSerialize['category'], $Categories)) {
3292 $AddCategories = array($ToSerialize['category']);
3293 wp_set_post_categories($post_ID, $AddCategories, true);
3294 }
3295 }
3296
3297 if (!empty($error)) {
3298 $success_array[$feed_slug] = $error;
3299 } else {
3300 $success_array[$feed_slug] = true;
3301 }
3302 }
3303 } // Loop through posted episodes...
3304
3305 // Check for PowerpressFeature for each channel...
3306 //
3307 // Can likely be deprecated due to itunes changes ----------------------------------------------
3308 //
3309
3310 if( isset($_POST['PowerpressFeature']) )
3311 {
3312 $FeatureEpisodes = powerpress_get_settings('powerpress_itunes_featured');
3313 if( empty($FeatureEpisodes) && !is_array($FeatureEpisodes) )
3314 $FeatureEpisodes = array();
3315
3316 $PowerpressFeature = $_POST['PowerpressFeature'];
3317 foreach( $PowerpressFeature as $feed_slug => $set_featured )
3318 {
3319 if( !empty($set_featured) )
3320 $FeatureEpisodes[ $feed_slug ] = $post_ID;
3321 else
3322 unset($FeatureEpisodes[ $feed_slug ]);
3323 }
3324
3325 powerpress_save_settings( $FeatureEpisodes, 'powerpress_itunes_featured');
3326 }
3327
3328 //
3329 //
3330 //
3331
3332 require_once(POWERPRESS_ABSPATH .'/powerpress-metamarks.php');
3333 powerpress_metabox_save($post_ID);
3334 }
3335 // Anytime the post is marked published, private or scheduled for the future we need to make sure we're making the media available for hosting
3336 if( $post->post_status == 'publish' || $post->post_status == 'private' || $post->post_status == 'future' )
3337 {
3338 if( !empty($GeneralSettings['blubrry_hosting']) && $GeneralSettings['blubrry_hosting'] !== 'false' )
3339 powerpress_process_hosting($post_ID, $post->post_title); // Call anytime blog post is in the published state
3340 }
3341 //WebSub and podping implementation
3342 if($post->post_status == 'publish') {
3343 $feedUrls = array(); //feed urls that have been updated by this post and that the hub should be notified about.
3344 $postType = get_post_type($post_ID);
3345
3346 if (!empty($GeneralSettings['cat_casting'])) {
3347 foreach (wp_get_post_categories($post_ID) as $id) {
3348 if (!empty($GeneralSettings['cat_casting_podcast_feeds'])) {
3349 array_push($feedUrls, get_category_feed_link($id, 'podcast'));
3350 } else {
3351 array_push($feedUrls, get_category_feed_link($id));
3352 }
3353 }
3354 }
3355 foreach (get_post_meta($post_ID) as $key => $value) {
3356 if ($key === 'enclosure') {
3357 //main feed updated
3358 array_push($feedUrls, get_feed_link('podcast'));
3359 }
3360 else if (!empty($GeneralSettings['channels']) && $postType == 'post' && preg_match("/_(\w{1,}):enclosure/i", $key, $matches) == 1) {
3361 array_push($feedUrls, get_feed_link($matches[1]));
3362 }
3363 }
3364 if (!empty($GeneralSettings['posttype_podcasting'])) {
3365 if ($postType != "page" || $postType != "post") {
3366 $PostTypeSettings = get_option('powerpress_posttype_' . $postType);
3367 if (!empty($PostTypeSettings)) {
3368 foreach ($PostTypeSettings as $feed_slug => $setting) {
3369 array_push($feedUrls, get_post_type_archive_feed_link($postType, $feed_slug));
3370 }
3371 }
3372 }
3373 }
3374 if (!(defined('POWERPRESS_DISABLE_WEBSUB') && POWERPRESS_DISABLE_WEBSUB )) {
3375 require_once( 'class.powerpresswebsub.php' );
3376 $Websub = new PowerPressWebSub();
3377 foreach ($feedUrls as $url) {
3378 try {
3379 $Websub->publish($url);
3380 } catch (Exception $e) {
3381 if (defined('WP_DEBUG') && WP_DEBUG) {
3382 powerpress_page_message_add_error($e->getMessage());
3383 }
3384 }
3385 }
3386 }
3387
3388 // podping uses the Blubrry API, so an account needs to be linked
3389 $creds = get_option('powerpress_creds');
3390 if (!empty($MediaURL) && (!empty($creds) || !empty($GeneralSettings['blubrry_auth']))) {
3391 if (!(defined('POWERPRESS_DISABLE_PODPING') && POWERPRESS_DISABLE_PODPING )) {
3392 require_once( 'powerpresspodping.class.php' );
3393 $Podping = new PowerPressPodping();
3394 foreach ($feedUrls as $url) {
3395 try {
3396 // because auth key is the same across the whole site and each feed url is being passed, it doesn't matter what program keyword we use to call the api
3397 $Podping->publish($url, $GeneralSettings['blubrry_program_keyword']);
3398 } catch (Exception $e) {
3399 if (defined('WP_DEBUG') && WP_DEBUG) {
3400 powerpress_page_message_add_error($e->getMessage());
3401 }
3402 }
3403 }
3404 }
3405
3406 }
3407 }
3408
3409 // cookies to either reload the block on success, or display an error on error
3410 if (!empty($success_array) && (!isset($GeneralSettings['pp_show_block_errors']) || $GeneralSettings['pp_show_block_errors'])) {
3411 // if successful, success = true. otherwise, success = a string that contains the error
3412 foreach($success_array as $feed_slug => $success) {
3413 if ($success === true) {
3414 setcookie('pp_event_' . $feed_slug . '_' . $post_ID . '_success', "success", 0, '/');
3415 } else {
3416 setcookie( 'pp_event_' . $feed_slug . '_' . $post_ID . '_add_notice', $success, 0, '/' );
3417 }
3418 }
3419 }
3420
3421 // And we're done!
3422 return $post_ID;
3423 }
3424
3425 add_action('save_post', 'powerpress_edit_post', 10, 2);
3426
3427 if (!function_exists('buildRedirect')) {
3428 function buildRedirect($Redirects)
3429 {
3430 $redirect_result = '';
3431 for ($x = 3; $x >= 0; $x--) {
3432 $key = sprintf('redirect%d', $x);
3433 if (!empty($Redirects[$key])) {
3434 if (preg_match('/^https?:\/\/(.*)$/', trim($Redirects[$key]), $matches) == 0)
3435 continue;
3436
3437 if (is_chartable_url($Redirects[$key])) {
3438 continue;
3439 }
3440
3441 $RedirectClean = $matches[1];
3442 if (substr($RedirectClean, -1, 1) != '/') // Rediercts need to end with a slash /.
3443 $RedirectClean .= '/';
3444
3445 if (!empty($RedirectClean)) {
3446 if (strpos($RedirectClean, '/') == 0) // Not a valid redirect URL
3447 continue;
3448
3449 if (!strstr($redirect_result, $RedirectClean)) // If the redirect is not already added...
3450 $redirect_result = $RedirectClean . $redirect_result;
3451 }
3452 }
3453 }
3454 return 'https://' . $redirect_result;
3455 }
3456 }
3457
3458 if (!function_exists('is_chartable_url')) {
3459 function is_chartable_url($redirectUrl)
3460 {
3461 if (strpos($redirectUrl, 'chrt.fm') !== false || strpos($redirectUrl, 'chtbl.com') !== false) {
3462 return true;
3463 } else {
3464 return false;
3465 }
3466 }
3467 }
3468
3469 if( defined('POWERPRESS_DO_ENCLOSE_FIX') )
3470 {
3471 function powerpress_insert_post_data($data, $postarr)
3472 {
3473 // If we added or modified a podcast episode, then we need to re-add/remove the embedded hidden link...
3474 if( isset($_POST['Powerpress']['podcast']) && $postarr['post_type'] == 'post' )
3475 {
3476 // First, remove the previous comment if one exists in the post body.
3477 $data['post_content'] = preg_replace('/\<!--.*added by PowerPress.*-->/im', '', $data['post_content']);
3478
3479 $Powerpress = $_POST['Powerpress']['podcast'];
3480 if( !empty($Powerpress['remove_podcast']) )
3481 {
3482 // Do nothing
3483 }
3484 else if( !empty($Powerpress['change_podcast']) || !empty($Powerpress['new_podcast']) )
3485 {
3486 $MediaURL = $Powerpress['url'];
3487 if( strpos($MediaURL, 'http://') !== 0 && strpos($MediaURL, 'https://') !== 0 && empty($Powerpress['hosting']) ) // If the url entered does not start with a http:// or https://
3488 {
3489 // Only glitch here is if the media url had an error, and if that's the case then there are other issues the user needs to worry about.
3490 $GeneralSettings = get_option('powerpress_general');
3491 if( $GeneralSettings && isset($GeneralSettings['default_url']) )
3492 $MediaURL = rtrim($GeneralSettings['default_url'], '/') .'/'. ltrim($MediaURL, '/');
3493 }
3494
3495 $data['post_content'] .= "<!-- DO NOT DELETE href=\"$MediaURL\" added by PowerPress to fix WordPress 2.8+ bug -->";
3496 }
3497 else
3498 {
3499 $EncloseData = powerpress_get_enclosure_data($postarr['ID']);
3500 if( $EncloseData && $EncloseData['url'] )
3501 $data['post_content'] .= "<!-- DO NOT DELETE href=\"{$EncloseData['url']}\" added by PowerPress to fix WordPress 2.8+ bug -->";
3502 }
3503 }
3504
3505 return $data;
3506 }
3507 add_filter('wp_insert_post_data', 'powerpress_insert_post_data',1,2);
3508 }
3509
3510 // Do the iTunes pinging here...
3511 function powerpress_publish_post($post_id)
3512 {
3513 if( !current_user_can('edit_post', $post_id) )
3514 return;
3515
3516 // Delete scheduled _encloseme request for just this post
3517 delete_post_meta($post_id, '_encloseme');
3518
3519 $GeneralSettings = get_option('powerpress_general');
3520 if( isset($GeneralSettings['auto_enclose']) && $GeneralSettings['auto_enclose'] )
3521 {
3522 $post = get_post($post_id);
3523 powerpress_do_enclose($post->post_content, $post_id, ($GeneralSettings['auto_enclose']==2) );
3524 }
3525 }
3526
3527 add_action('publish_post', 'powerpress_publish_post');
3528
3529 // Admin page, html meta header
3530 function powerpress_admin_head()
3531 {
3532 global $parent_file, $hook_suffix;
3533 $page_name = '';
3534 if ( isset($parent_file) && !empty($parent_file) )
3535 {
3536 $page_name = substr($parent_file, 0, -4);
3537 $page_name = preg_replace('/(\?.*)$/', '', $page_name); // Hack required for WP 3.0
3538 $page_name = str_replace(array('.php', '-new', '-add'), '', $page_name); // Hack required for WP 3.0
3539 }
3540 else
3541 {
3542 if (!is_null($hook_suffix)) {
3543 $page_name = str_replace(array('.php', '-new', '-add'), '', $hook_suffix);
3544 }
3545 }
3546
3547 // Powerpress page
3548 if( isset($_GET['page']) && strstr($_GET['page'], 'powerpress' ) !== false )
3549 {
3550 powerpress_wp_print_styles();
3551 echo "<script type=\"text/javascript\" src=\"". powerpress_get_root_url() ."player.min.js\"></script>\n";
3552 ?>
3553 <script type="text/javascript"><!--
3554 function powerpress_show_field(id, show) {
3555 if( document.getElementById(id).nodeName == "SPAN" )
3556 document.getElementById(id).style.display = (show?"inline":"none");
3557 else
3558 document.getElementById(id).style.display = (show?"block":"none");
3559 }
3560 function powerpress_new_feed_url_prompt() {
3561 var Msg = '<?php echo __('WARNING: Changes made here are permanent. If the New Feed URL entered is incorrect, you will lose subscribers and will no longer be able to update your listing in the iTunes Store.\n\nDO NOT MODIFY THIS SETTING UNLESS YOU ABSOLUTELY KNOW WHAT YOU ARE DOING.\n\nAre you sure you want to continue?', 'powerpress'); ?>';
3562 if( confirm(Msg) ) {
3563 powerpress_show_field('new_feed_url_step_1', false);
3564 powerpress_show_field('new_feed_url_step_2', true);
3565 }
3566 return false;
3567 }
3568
3569
3570 function powerpress_create_subscribe_page()
3571 {
3572 // This function is only called once!
3573 jQuery.ajax( {
3574 type: 'POST',
3575 url: '<?php echo admin_url(); ?>admin-ajax.php',
3576 data: { action: 'powerpress_create_subscribe_page', nonce: '<?php echo wp_create_nonce('powerpress-create-subscribe-page'); ?>' },
3577 timeout: (30 * 1000),
3578 success: function(response) {
3579
3580 response = response.trim();
3581 <?php
3582 if( defined('POWERPRESS_AJAX_DEBUG') )
3583 echo "\t\t\t\talert(response);\n";
3584 ?>
3585 // This logic will parse beyond warning messages generated by the server that we don't know about
3586
3587 var foundAt = response.indexOf('PAGE-OK');
3588 if( foundAt > 0 )
3589 {
3590 response = response.substring( foundAt );
3591 }
3592
3593 var Parts = response.split("\n", 5);
3594
3595 if( Parts[0] == 'PAGE-OK' )
3596 {
3597 jQuery('#subscribe_page_link_id').append('<option value="' + Parts[1] + '" selected>' + Parts[3] + '</option>');
3598 jQuery('#subscribe_page_link_or').hide();
3599 jQuery('#powerpress_create_subscribe_page').hide();
3600 }
3601 else if( Parts[0] == 'PAGE-ERROR' )
3602 {
3603 alert( Parts[1] );
3604 }
3605 else
3606 {
3607 alert( '<?php echo __('Unknown error occurred creating subscribe page.', 'powerpress'); ?>' );
3608 }
3609 },
3610 error: function(objAJAXRequest, strError) {
3611
3612 alert( '<?php echo __('Unknown ajax error occurred creating subscribe page.', 'powerpress'); ?>' );
3613
3614 var errorMsg = "HTTP " +objAJAXRequest.statusText;
3615 if ( objAJAXRequest.responseText ) {
3616 errorMsg += ', '+ objAJAXRequest.responseText.replace( /<.[^<>]*?>/g, '' );
3617 }
3618 }
3619 });
3620 }
3621
3622 /* Save tab position */
3623 jQuery(document).ready(function($) {
3624
3625 if( jQuery("#powerpress_settings_page").length > 0 )
3626 {
3627 <?php if (!empty($_POST['tab'])) { ?>
3628 document.getElementById("<?php echo sanitize_key($_POST['tab']); ?>").click();
3629 <?php } elseif (!empty($_GET['tab'])) { ?>
3630 document.getElementById("<?php echo sanitize_key($_GET['tab']); ?>").click();
3631 <?php }
3632 if (!empty($_POST['sidenav-tab'])) { ?>
3633 document.getElementById("<?php echo sanitize_key($_POST['sidenav-tab']); ?>").click();
3634 <?php } elseif (!empty($_GET['sidenav-tab'])) { ?>
3635 document.getElementById("<?php echo sanitize_key($_GET['sidenav-tab']); ?>").click();
3636 <?php }?>
3637 <?php if (!empty($_GET['tab']) || !empty($_GET['sidenav-tab'])) { ?>
3638 // clear tab params from URL so reload doesn't keep returning to same tab
3639 if (window.history && window.history.replaceState) {
3640 var url = new URL(window.location.href);
3641 url.searchParams.delete('tab');
3642 url.searchParams.delete('sidenav-tab');
3643 window.history.replaceState({}, '', url.toString());
3644 }
3645 <?php } ?>
3646 jQuery('form').submit(function() {
3647 let selectedTemp = jQuery('.tablinks.active:first');
3648 jQuery('#save_tab_pos').val(selectedTemp.attr('id'));
3649 let selectedSide = jQuery('.pp-tabcontent.active .pp-sidenav-tablinks.active:first');
3650 if (selectedSide) {
3651 jQuery("#save_sidenav_pos").val(selectedSide.attr('id'));
3652 }
3653 });
3654 }
3655
3656 jQuery('#powerpress_create_subscribe_page').click( function(e) {
3657 e.preventDefault();
3658 powerpress_create_subscribe_page();
3659 return false;
3660 });
3661 jQuery('#subscribe_page_link_id').change( function(e) {
3662 if( jQuery('#subscribe_page_link_id').val().length > 0 )
3663 jQuery('#subscribe_page_link_or').css('display', 'none');
3664 else
3665 jQuery('#subscribe_page_link_or').css('display', 'inline-block');
3666 });
3667
3668 jQuery('.powerpress-parental-rating-tip').click( function(event) {
3669 event.preventDefault();
3670 jQuery('.powerpress-parental-rating-tip-p').css('display', 'none');
3671 jQuery('#'+this.id +'_p').css('display', 'block');
3672 });
3673 jQuery('.activate-player').click( function(event) {
3674 event.preventDefault();
3675 var PlayerName = this.id.replace(/(activate_)(.*)$/, "$2");
3676 if( !PlayerName )
3677 return;
3678
3679 if(typeof jQuery.prop === 'function') {
3680 jQuery('.player-type-input').prop('disabled', true);
3681 jQuery('#player_'+PlayerName).prop('disabled', false);
3682 jQuery('#player_'+PlayerName).removeAttr('disabled');
3683 } else {
3684 jQuery('.player-type-input').attr('disabled', true);
3685 jQuery('#player_'+PlayerName).removeAttr('disabled');
3686 }
3687 jQuery(this).closest("form").submit();
3688 });
3689 jQuery('.goto-artwork-tab').click( function(event) {
3690 event.preventDefault();
3691 // TODO:
3692
3693 });
3694 });
3695
3696
3697 //-->
3698 </script>
3699 <?php
3700 if (defined('WP_DEBUG') && WP_DEBUG) {
3701 if (WP_DEBUG) {
3702 wp_register_style('powerpress-admin-style', powerpress_get_root_url() . 'css/admin.css', array(), POWERPRESS_VERSION);
3703 wp_register_style('powerpress-grid', powerpress_get_root_url() . 'css/bootstrap-grid.css', array(), POWERPRESS_VERSION);
3704 } else {
3705 wp_register_style('powerpress-admin-style', powerpress_get_root_url() . 'css/admin.min.css', array(), POWERPRESS_VERSION);
3706 wp_register_style('powerpress-grid', powerpress_get_root_url() . 'css/bootstrap-grid.min.css', array(), POWERPRESS_VERSION);
3707 }
3708 } else {
3709 wp_register_style('powerpress-admin-style', powerpress_get_root_url() . 'css/admin.min.css', array(), POWERPRESS_VERSION);
3710 wp_register_style('powerpress-grid', powerpress_get_root_url() . 'css/bootstrap-grid.min.css', array(), POWERPRESS_VERSION);
3711 }
3712 wp_enqueue_style( 'powerpress-admin-style' );
3713 wp_enqueue_style( 'powerpress-grid' );
3714 }
3715 else if( $page_name == 'edit' || $page_name == 'edit-pages' ) // || $page_name == '' ) // we don't know the page, we better include our CSS just in case
3716 {
3717 ?>
3718 <style type="text/css">
3719 .powerpress_podcast_box {
3720
3721 }
3722 .powerpress_podcast_box label {
3723 width: 120px;
3724 font-weight: bold;
3725 font-size: 110%;
3726 display: inline;
3727 position: absolute;
3728 top: 0;
3729 left: 0;
3730 }
3731 .powerpress_podcast_box .powerpress_row {
3732 margin-top: 10px;
3733 margin-bottom: 10px;
3734 position: relative;
3735 }
3736 .powerpress_podcast_box .powerpress_row_content {
3737 margin-left: 120px;
3738 }
3739 .powerpress_podcast_box .error,
3740 .powerpress_podcast_box .warning,
3741 .powerpress_podcast_box .success {
3742 margin-top: 10px;
3743 margin-bottom: 10px;
3744 padding: 5px;
3745 font-size: 12px;
3746 border-width: 1px;
3747 border-style: solid;
3748 font-weight: bold;
3749 text-align: center;
3750 -moz-border-radius: 3px;
3751 -khtml-border-radius: 3px;
3752 -webkit-border-radius: 3px;
3753 border-radius: 3px;
3754 position: relative;
3755 }
3756 .powerpress_podcast_box .warning {
3757 color: #8a6d3b;
3758 border-color: #faebcc;
3759 background-color: #fcf8e3;
3760 }
3761 .powerpress_podcast_box .error {
3762 color: #a94442;
3763 border-color: #ebccd1;
3764 background-color: #f2dede;
3765 }
3766 .powerpress_podcast_box .success {
3767 color: #3c763d;
3768 border-color: #d6e9c6;
3769 background-color: #dff0d8;
3770 }
3771 .powerpress_podcast_box .success a.close {
3772 position: absolute;
3773 top: 2px;
3774 right: 2px;
3775 text-align: right;
3776 color: #993366;
3777 text-decoration: none;
3778 }
3779 .powerpress_podcast_box .updated {
3780 margin-top: 10px;
3781 margin-bottom: 10px;
3782 padding: 5px;
3783 font-size: 12px;
3784 border-width: 1px;
3785 border-style: solid;
3786 font-weight: bold;
3787 text-align: center;
3788 }
3789
3790 </style>
3791 <script language="javascript"><!--
3792
3793 g_powerpress_last_selected_channel = '';
3794 g_powerpress_prev_valid_media_url = {};
3795
3796 /**
3797 * Validates the main enclosure media URL for podcast episodes
3798 *
3799 * @param {string} url - media url to validate
3800 * @param {string} DestDiv - the id of the destination div element where validation message is displayed
3801 * @param {string} hosting - optional, when '1' skips URL format validation since value is just a filename
3802 * @returns {boolean} returns true if validation passes, false otherwise
3803 */
3804 function powerpress_check_url(url, DestDiv, hosting)
3805 {
3806 if( powerpress_check_url.arguments.length > 1 )
3807 DestDiv = powerpress_check_url.arguments[1];
3808
3809 const Div = document.getElementById(DestDiv);
3810 if (!Div) return false;
3811
3812 // when hosting flag is set, value is just a filename, skip URL format validation
3813 const isHostedFile = (hosting === '1' || hosting === 1);
3814
3815 Div.classList.add("pp-error");
3816 Div.classList.remove("updated");
3817
3818 const FeedSlug = DestDiv.replace("powerpress_warning_", "");
3819
3820 /**
3821 * Displays validation error message and manages UI state
3822 *
3823 * @param {string} message - The error message to display
3824 * @param {boolean} clearHosting - Whether to reset the hosting flag to '0'
3825 * @param {boolean} revertUrl - Whether to revert the URL input to the last valid URL for existing media
3826 * @returns {boolean} Always returns false to indicate validation failure
3827 */
3828 function showValidationError(message, clearHosting, revertUrl) {
3829 Div.innerHTML = message;
3830 Div.style.display = 'block';
3831
3832 const failElement = document.getElementById('powerpress_fail_' + FeedSlug);
3833 if (failElement) failElement.style.display = 'inline-block';
3834
3835 const urlShowElement = document.getElementById('powerpress_url_show_' + FeedSlug);
3836 if (urlShowElement) urlShowElement.style.backgroundColor = '#FFF3CD';
3837
3838 // hide metadata sections for new episodes by default
3839 const hasMediaElement = document.getElementById('powerpress_has_media_' + FeedSlug);
3840 const skipVerificationElement = document.getElementById('powerpress_skip_verification_' + FeedSlug);
3841 const hasExistingMedia = hasMediaElement ? hasMediaElement.value : null;
3842 const skipVerification = skipVerificationElement ? skipVerificationElement.value : null;
3843
3844 if (hasExistingMedia === '0' && skipVerification !== '1') {
3845 const mediaDetailsElement = document.getElementById('media-file-details-' + FeedSlug);
3846 if (mediaDetailsElement) mediaDetailsElement.style.display = 'none';
3847
3848 const tabContainerElement = document.getElementById('tab-container-' + FeedSlug);
3849 if (tabContainerElement) tabContainerElement.style.display = 'none';
3850 }
3851
3852 // reset hosting flag
3853 if (clearHosting) {
3854 const hostingElement = document.getElementById('powerpress_hosting_' + FeedSlug);
3855 if (hostingElement) hostingElement.value = '0';
3856 }
3857
3858 // revert to last valid URL if metadata exists
3859 if (revertUrl && hasExistingMedia === '1' && g_powerpress_prev_valid_media_url[FeedSlug]) {
3860 const urlDisplayElement = document.getElementById('powerpress_url_display_' + FeedSlug);
3861 if (urlDisplayElement) {
3862 urlDisplayElement.value = g_powerpress_prev_valid_media_url[FeedSlug];
3863 }
3864 }
3865
3866 return false;
3867 }
3868
3869 // early failure with URL validation test
3870 if (!isHostedFile) {
3871 try {
3872 const urlObj = new URL(url);
3873 // only allow http/https protocols
3874 if (!['http:', 'https:'].includes(urlObj.protocol)) {
3875 return showValidationError(
3876 "<?php echo esc_js( __('Media URL must use HTTP or HTTPS protocol.', 'powerpress')); ?>",
3877 false,
3878 false
3879 );
3880 }
3881 } catch (e) {
3882 return showValidationError(
3883 "<?php echo esc_js( __('Invalid URL format. Please enter a valid media URL.', 'powerpress')); ?>",
3884 false,
3885 false
3886 );
3887 }
3888 }
3889
3890 // check for chartable urls
3891 if (url.includes('chrt.fm') || url.includes('chtbl.com')) {
3892 return showValidationError(
3893 '<?php echo esc_js( __("Previous Chartable Users: If you're publishing a new episode please ensure that you have removed the Chartable stats redirect on your RSS feed. Chartable: Remove. Blubrry Prefix: Include.", 'powerpress')); ?>',
3894 false,
3895 false
3896 );
3897 }
3898
3899 // check for youtube urls
3900 if (url.includes('youtube.com') || url.includes('youtu.be')) {
3901 return showValidationError(
3902 '<?php echo esc_js( __('YouTube links are not accepted as podcast media files. YouTube links should be used in the Embed field or as Content Links only.', 'powerpress')); ?>',
3903 true,
3904 true
3905 );
3906 }
3907 // validate url characters based on hosting provider, only allow query strings from trusted hosts
3908 <?php
3909 $blubrry_prefixes = ['mc.', 'media.'];
3910 $blubrry_js_hosts = [];
3911 $domains_for_js = defined('POWERPRESS_TRUSTED_DOMAINS') ? POWERPRESS_TRUSTED_DOMAINS : ['blubrry.com'];
3912 foreach( $domains_for_js as $domain ) {
3913 foreach( $blubrry_prefixes as $prefix ) {
3914 $blubrry_js_hosts[] = $prefix . $domain;
3915 }
3916 }
3917 ?>
3918 const hostingPatterns = [
3919 {
3920 hosts: ['traffic.libsyn.com', 'cdn.simplecast.com', 'buzzsprout.com', 'audioboom.com'],
3921 pattern: /^[a-zA-Z0-9:\/\-_\.\?=&]+$/
3922 },
3923 {
3924 hosts: ['art19.com'],
3925 pattern: /^[a-zA-Z0-9:\/\-_\.\?=&,%]+$/
3926 },
3927 {
3928 hosts: <?php echo json_encode($blubrry_js_hosts); ?>,
3929 pattern: /^[a-zA-Z0-9:\/\-_\.\?=&%;+]+$/
3930 }
3931 ];
3932
3933 // find matching hosting provider pattern
3934 const matchedHost = hostingPatterns.find(item => item.hosts.some(host => url.includes(host)));
3935
3936 // if trusted host, validate against its specific pattern, otherwise strict default pattern
3937 const urlPattern = matchedHost ? matchedHost.pattern : /^[a-zA-Z0-9:\/\-_\.]+$/;
3938 if (!urlPattern.test(url)) {
3939 return showValidationError(
3940 "<?php echo esc_js( __('Media URL contains characters that may cause problems for some clients. For maximum compatibility, only use letters, numbers, dash - and underscore _ characters only.', 'powerpress')); ?>",
3941 false,
3942 false
3943 );
3944 }
3945
3946 // all validation passed, store this as the last valid URL
3947 g_powerpress_prev_valid_media_url[FeedSlug] = url;
3948 Div.style.display = 'none';
3949 return true;
3950 }
3951
3952
3953 function powerpress_get_media_info(FeedSlug)
3954 {
3955 if( jQuery('#powerpress_check_'+FeedSlug).css("display") != "none" )
3956 return; // Another process is already running
3957
3958 jQuery('#powerpress_fail_'+FeedSlug).css("display", 'none');
3959 jQuery( '#powerpress_success_'+FeedSlug ).css('display', 'none');
3960 //jQuery( '#powerpress_warning_'+FeedSlug ).text('');
3961 jQuery( '#powerpress_warning_'+FeedSlug ).css('display', 'none');
3962 jQuery( '#powerpress_warning_'+FeedSlug ).addClass("pp-error");
3963 jQuery( '#powerpress_warning_'+FeedSlug ).removeClass("updated");
3964
3965 // use hidden field for verification, fallback to display field to catch manual
3966 var Value = jQuery('#powerpress_url_'+FeedSlug).val();
3967 if (!Value || Value.trim() === '')
3968 Value = jQuery('#powerpress_url_display_'+FeedSlug).val();
3969
3970 var Hosting = jQuery('#powerpress_hosting_'+FeedSlug).val();
3971 var program_keyword = jQuery('#powerpress_program_keyword_'+FeedSlug).val();
3972 if( Value )
3973 {
3974 if( powerpress_check_url(Value, 'powerpress_warning_'+FeedSlug, Hosting ) )
3975 {
3976 jQuery('#powerpress_check_'+FeedSlug).css("display", 'inline-block');
3977 let payload = { action: 'powerpress_media_info', media_url : Value, feed_slug : encodeURIComponent(FeedSlug), hosting: Hosting, program_keyword: program_keyword, nonce: '<?php echo wp_create_nonce('powerpress-media-info'); ?>' };
3978 console.log(payload);
3979 jQuery.ajax( {
3980 type: 'POST',
3981 url: '<?php echo admin_url(); ?>admin-ajax.php',
3982 data: payload,
3983 timeout: (30 * 1000),
3984 success: function(response) {
3985
3986 response = response.trim();
3987 // This logic will parse beyond warning messages generated by the server that we don't know about
3988 var foundAt = response.indexOf('VERIFY-OK');
3989 if( foundAt > 0 )
3990 {
3991 response = response.substring( foundAt );
3992 }
3993 console.log(response);
3994 var Parts = response.split("\n", 5);
3995
3996 var FinishFeedSlug = Parts[1];
3997
3998 jQuery('#powerpress_check_'+FeedSlug).css("display", 'none');
3999
4000 if( FeedSlug == FinishFeedSlug && Parts[0] == 'VERIFY-OK' )
4001 {
4002 // update the display element with the filename from display field
4003 var displayValue = jQuery('#powerpress_url_display_'+FeedSlug).val();
4004 if (displayValue) {
4005 jQuery('#ep-box-filename-'+FeedSlug).text(displayValue);
4006 jQuery('#powerpress_url_show_'+FeedSlug).attr('title', Value);
4007 }
4008
4009 // only set file size if auto detect is selected
4010 var sizeChecked = jQuery('#powerpress_set_size_0_'+FeedSlug).attr('checked');
4011 if(typeof jQuery.prop === 'function') {
4012 sizeChecked = jQuery('#powerpress_set_size_0_'+FeedSlug).prop('checked');
4013 }
4014 if (sizeChecked && Parts[2])
4015 {
4016
4017 jQuery('#powerpress_size_'+FeedSlug).val( Parts[2] );
4018 }
4019
4020 // only set duration if auto detect is selected
4021 var durationChecked = jQuery('#powerpress_set_duration_0_'+FeedSlug).attr('checked');
4022 if(typeof jQuery.prop === 'function') {
4023 durationChecked = jQuery('#powerpress_set_duration_0_'+FeedSlug).prop('checked');
4024 }
4025 if( durationChecked && Parts[3] )
4026 {
4027
4028 var Duration = Parts[3].split(':');
4029 jQuery('#powerpress_duration_hh_'+FeedSlug).val( Duration[0] );
4030 jQuery('#powerpress_duration_mm_'+FeedSlug).val( Duration[1] );
4031 jQuery('#powerpress_duration_ss_'+FeedSlug).val( Duration[2] );
4032 }
4033 else if( durationChecked )
4034 {
4035 jQuery('#powerpress_duration_hh_'+FeedSlug).val( '' );
4036 jQuery('#powerpress_duration_mm_'+FeedSlug).val( '' );
4037 jQuery('#powerpress_duration_ss_'+FeedSlug).val( '' );
4038 }
4039
4040 if (Parts[4]) {
4041 self.parent.document.getElementById('powerpress_url_' + FeedSlug).value = Parts[4];
4042 }
4043
4044 if( Parts.length > 5 && Parts[5] != '' )
4045 {
4046 jQuery( '#powerpress_warning_'+FeedSlug ).html( Parts[5] );
4047 jQuery( '#powerpress_warning_'+FeedSlug ).css('display', 'block');
4048 jQuery( '#powerpress_warning_'+FeedSlug ).addClass("updated");
4049 jQuery( '#powerpress_warning_'+FeedSlug ).removeClass("error");
4050 <?php
4051 if( defined('POWERPRESS_AJAX_DEBUG') )
4052 echo "\t\t\t\tjQuery( '#powerpress_warning_'+FeedSlug ).append( '<br/>Complete Response: '+ response);\n";
4053 ?>
4054 }
4055 else
4056 {
4057 jQuery( '#powerpress_success_'+FeedSlug ).css('display', 'inline-block');
4058 jQuery( '#powerpress_url_show_'+FeedSlug ).css('background-color', '#c1f2b8');
4059 // setTimeout( function() { jQuery( '#powerpress_success_'+FeedSlug ).fadeOut(1000); }, 10000 );
4060 <?php
4061 if( defined('POWERPRESS_AJAX_DEBUG') )
4062 echo "\t\t\t\tjQuery( '#powerpress_warning_'+FeedSlug ).append( '<br/>Complete Response: '+ response);\n";
4063 ?>
4064 }
4065
4066 // verification success, show metadata sections and update UI
4067 jQuery('#pp-url-input-container-'+FeedSlug).css('display', 'none');
4068 jQuery('#powerpress_url_show_'+FeedSlug).css('display', 'inline-block');
4069 jQuery('#edit-media-file-'+FeedSlug).css('display', 'inline-block');
4070 jQuery('#pp-change-media-file-'+FeedSlug).css('display', 'none');
4071 jQuery('#select-media-file-'+FeedSlug).css('display', 'none');
4072 jQuery('#ep-box-blubrry-service-'+FeedSlug).css('display', 'none');
4073 jQuery('#pp-media-blubrry-container-'+FeedSlug).removeAttr('style');
4074 jQuery('#media-file-details-'+FeedSlug).css('display', 'inline-block');
4075 jQuery('#tab-container-'+FeedSlug).css('display', 'block');
4076 var connectInfo = jQuery('#ep-box-blubrry-connect-'+FeedSlug);
4077 var connectInfoSmall = jQuery('#ep-box-min-blubrry-connect-'+FeedSlug);
4078 if (connectInfo.length) {
4079 connectInfo.css('display', 'none');
4080 connectInfoSmall.removeAttr('style');
4081 }
4082 jQuery('#powerpress_has_media_'+FeedSlug).val('1');
4083 }
4084 else
4085 {
4086 var Parts = response.split("\n", 5);
4087 if( Parts.length > 5 )
4088 {
4089 var server_error = response.replace(/\n/g, "<br \/>");
4090 jQuery( '#powerpress_warning_'+FeedSlug ).html( '<div style="text-align: left;">Server Error:</div><div style="text-align: left; font-weight: normal;">' + server_error +'<\/div>' );
4091 }
4092 else if( Parts[1] )
4093 jQuery( '#powerpress_warning_'+FeedSlug ).html( Parts[1] );
4094 else
4095 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('Unknown error occurred while checking Media URL. You can still publish this episode, but will need to enter filesize and duration manually.', 'powerpress'); ?>' );
4096
4097 <?php
4098 if( defined('POWERPRESS_AJAX_DEBUG') )
4099 echo "\t\t\t\tjQuery( '#powerpress_warning_'+FeedSlug ).append( '<br/>Complete Response: '+ response);\n";
4100 ?>
4101 jQuery( '#powerpress_warning_'+FeedSlug ).css('display', 'block');
4102 jQuery('#powerpress_fail_'+FeedSlug).css("display", 'inline-block');
4103 jQuery( '#powerpress_url_show_'+FeedSlug ).css('background-color', '#eba2a2');
4104 }
4105 },
4106 error: function(objAJAXRequest, textStatus, errorThrown) {
4107
4108 var errorCode = objAJAXRequest.status;
4109 var errorMsg = objAJAXRequest.statusText;
4110 var responseClean = '';
4111 if ( objAJAXRequest.responseText ) {
4112 responseClean = objAJAXRequest.responseText.replace( /<.[^<>]*?>/g, '' );
4113 }
4114
4115 jQuery('#powerpress_check_'+FeedSlug).css("display", 'none');
4116 jQuery( '#powerpress_warning_'+FeedSlug ).css('display', 'block');
4117 jQuery('#powerpress_fail_'+FeedSlug).css("display", 'inline-block');
4118 jQuery( '#powerpress_url_show_'+FeedSlug ).css('background-color', '#eba2a2');
4119
4120 if( textStatus == 'timeout' ) {
4121 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('Operation timed out.', 'powerpress'); ?>' );
4122 }
4123 else if( textStatus == 'error' ) {
4124 jQuery( '#powerpress_warning_'+FeedSlug ).html( errorCode +' - '+ errorThrown +'<br />');
4125 }
4126 else if( textStatus == 'abort' ) {
4127 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('Operation aborted.', 'powerpress'); ?>' );
4128 }
4129 else if( textStatus == 'parsererror' ) {
4130 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('Parse error occurred.', 'powerpress'); ?>' );
4131 }
4132 else if( textStatus != null ) {
4133 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('AJAX Error', 'powerpress') .': '; ?>'+textStatus );
4134 }
4135 else if( errorMsg ) {
4136 jQuery( '#powerpress_warning_'+FeedSlug ).text( +errorMsg );
4137 }
4138 else {
4139 jQuery( '#powerpress_warning_'+FeedSlug ).text( '<?php echo __('AJAX Error', 'powerpress') .': '. __('Unknown', 'powerpress'); ?>' );
4140 }
4141
4142 if( textStatus != 'error' && errorThrown ) { // If we have an error thrown, lets append it to the error message
4143 jQuery('#powerpress_warning_'+FeedSlug).append('<br/>'+errorThrown);
4144 }
4145
4146 <?php
4147 if( defined('POWERPRESS_AJAX_DEBUG') ) {
4148 echo "\t\t\tif( objAJAXRequest.responseText ) {\n";
4149 echo "\t\t\t\tjQuery('#powerpress_warning_'+FeedSlug).text( jQuery('#powerpress_warning_'+FeedSlug).text() +' - Response: '+ objAJAXRequest.responseText);\n";
4150 echo "\t\t\t}\n";
4151 }
4152 ?>
4153 }
4154 });
4155 }
4156 }
4157 }
4158
4159 function powerpress_update_for_video(media_url, FeedSlug)
4160 {
4161 if (media_url.search(/\.(mp4|m4v|ogg|ogv|webm)$/) > -1)
4162 {
4163 jQuery('#powerpress_ishd_'+ FeedSlug +'_span').css('display','inline');
4164 }
4165 else
4166 {
4167 jQuery('#powerpress_ishd_'+ FeedSlug +'_span').css('display','none');
4168 jQuery('#powerpress_ishd_'+ FeedSlug +'_span').removeAttr('checked');
4169 if(typeof jQuery.removeProp === 'function') {
4170 jQuery('#powerpress_ishd_'+ FeedSlug +'_span').removeProp('checked');
4171 }
4172 }
4173
4174
4175 if (media_url.search(/\.(mp4|m4v)$/) > -1)
4176 {
4177 jQuery('#powerpress_webm_'+ FeedSlug ).css('display', 'block');
4178 }
4179 else
4180 {
4181 jQuery('#powerpress_webm_'+ FeedSlug ).css('display', 'none');
4182 }
4183 }
4184
4185 function powerpress_remove_hosting(FeedSlug)
4186 {
4187 if( confirm('<?php echo __('Are you sure you want to remove this media file?', 'powerpress'); ?>') )
4188 {
4189 jQuery( '#powerpress_url_display_'+FeedSlug ).attr("readOnly", false);
4190 jQuery( '#powerpress_url_'+FeedSlug ).val('');
4191 jQuery( '#powerpress_hosting_'+FeedSlug ).val(0);
4192 jQuery( '#powerpress_hosting_note_'+FeedSlug ).css('display', 'none');
4193 powerpress_update_for_video('', FeedSlug);
4194 }
4195 }
4196
4197 var pp_upload_image_button_funct = false;
4198
4199 jQuery(document).ready(function($) {
4200
4201 // Initialize g_powerpress_prev_valid_media_url with pre-loaded media URLs
4202 document.querySelectorAll('[id^="powerpress_url_display_"]').forEach(function(element) {
4203 const feedSlug = element.id.replace('powerpress_url_display_', '');
4204 const url = element.value;
4205 const hasMediaElement = document.getElementById('powerpress_has_media_' + feedSlug);
4206
4207 if (url && hasMediaElement && hasMediaElement.value === '1') {
4208 g_powerpress_prev_valid_media_url[feedSlug] = url;
4209 }
4210 });
4211
4212 jQuery('.powerpress-url').change(function() {
4213
4214 var FeedSlug = this.id.replace(/(powerpress_url_)(.*)$/, "$2");
4215 if( !FeedSlug )
4216 return;
4217
4218 var media_url = jQuery(this).val();
4219 var Hosting = jQuery('#powerpress_hosting_'+FeedSlug).val();
4220 powerpress_check_url(media_url,'powerpress_warning_'+FeedSlug, Hosting);
4221 powerpress_update_for_video(media_url, FeedSlug);
4222 });
4223
4224 jQuery('.powerpress-image-browser').click(function(e) {
4225 e.preventDefault();
4226 g_powerpress_last_selected_channel = this.id.replace(/(powerpress_image_browser_)(.*)$/, "$2");
4227 tb_show('', 'media-upload.php?type=image&amp;TB_iframe=true&amp;post_id=0', false);
4228
4229 if( pp_upload_image_button_funct == false )
4230 pp_upload_image_button_funct = window.send_to_editor;
4231
4232 window.send_to_editor = function(html)
4233 {
4234 url = jQuery('img', html).attr('src');
4235 if (url === undefined) {
4236 url = jQuery(html).attr('src');
4237 }
4238 jQuery('#powerpress_image_'+g_powerpress_last_selected_channel).val( url );
4239 g_powerpress_last_selected_channel = '';
4240 tb_remove();
4241 window.send_to_editor = pp_upload_image_button_funct;
4242 pp_upload_image_button_funct = false;
4243 }
4244 return false;
4245 });
4246 jQuery('.powerpress-itunes-image-browser').click(function(e) {
4247 console.log('here');
4248 e.preventDefault();
4249 g_powerpress_last_selected_channel = this.id.replace(/(powerpress_itunes_image_browser_)(.*)$/, "$2");
4250 tb_show('', 'media-upload.php?type=image&amp;TB_iframe=true&amp;post_id=0', false);
4251
4252 if( pp_upload_image_button_funct == false )
4253 pp_upload_image_button_funct = window.send_to_editor;
4254
4255 window.send_to_editor = function(html)
4256 {
4257 url = jQuery('img', html).attr('src');
4258 if (url === undefined) {
4259 url = jQuery(html).attr('src');
4260 }
4261 jQuery('#powerpress_itunes_image_'+g_powerpress_last_selected_channel).val( url );
4262 g_powerpress_last_selected_channel = '';
4263 tb_remove();
4264 window.send_to_editor = pp_upload_image_button_funct;
4265 pp_upload_image_button_funct = false;
4266 }
4267 return false;
4268 });
4269 jQuery('#insert-media-button').click( function(e) {
4270 if( pp_upload_image_button_funct != false )
4271 {
4272 window.send_to_editor = pp_upload_image_button_funct;
4273 pp_upload_image_button_funct = false;
4274 }
4275 });
4276 jQuery('.powerpress-embed').change( function() {
4277 // if there is a value in the embed box, but there is no value in the url box, then we need to display a warning...
4278 var FeedSlug = this.id.replace(/(powerpress_embed_)(.*)$/, "$2");
4279 if( !FeedSlug )
4280 return;
4281
4282 var MediaURL = jQuery('#powerpress_url_'+FeedSlug).val();
4283 if( !MediaURL )
4284 {
4285 jQuery('#powerpress_warning_'+FeedSlug ).text( '<?php echo __('You must enter a Media URL in order to save Media Embed.', 'powerpress'); ?>');
4286 jQuery('#powerpress_warning_'+FeedSlug ).css('display', 'block');
4287 jQuery('#powerpress_url_'+FeedSlug).focus();
4288 }
4289 });
4290 });
4291
4292 function powerpress_send_to_poster_image(url)
4293 {
4294 if( g_powerpress_last_selected_channel )
4295 {
4296 jQuery('#powerpress_image_'+g_powerpress_last_selected_channel).val( url );
4297 g_powerpress_last_selected_channel = '';
4298 }
4299 tb_remove();
4300 }
4301 //-->
4302 </script>
4303 <?php
4304 }
4305 }
4306
4307 add_action('admin_head', 'powerpress_admin_head');
4308
4309 function powerpress_check_account_verified_popup($no_signout_link = false) {
4310 $link_action_url = admin_url('admin.php?action=powerpress-jquery-account-verify');
4311 $link_action = 'powerpress-jquery-account-verify';
4312 $url = wp_nonce_url($link_action_url, $link_action);
4313 $url = str_replace("&amp;", "&", $url);
4314 if ($no_signout_link) {
4315 $no_signout = 'true';
4316 } else {
4317 $no_signout = 'false';
4318 }
4319 $url = $url . '&no_signout_link=' . $no_signout;
4320 echo "<input type='hidden' id='verify-account-url' value='" . $url . "'/>";
4321 }
4322
4323 function powerpress_check_credentials($creds) {
4324 if (isset($creds['client_id'])) {
4325 if (!isset($creds['account_verified']) || !$creds['account_verified']) {
4326 powerpress_check_account_verified_popup($_GET['page'] == 'powerpressadmin_onboarding.php');
4327 }
4328 }
4329 }
4330
4331 function powerpress_media_info_ajax()
4332 {
4333 // Check for nonce security
4334 if (!isset($_POST['nonce'])) {
4335 wp_die();
4336 }
4337 if ( ! wp_verify_nonce( $_POST['nonce'], 'powerpress-media-info' ) ) {
4338 wp_die();
4339 }
4340 $feed_slug = htmlspecialchars($_POST['feed_slug']);
4341 $hosting = $_POST['hosting'];
4342 $size = 0;
4343 $duration = '';
4344 $GeneralSettings = get_option('powerpress_general');
4345 if (empty($GeneralSettings['blubrry_hosting'])) {
4346 $hosting = 0;
4347 }
4348 if (!$hosting && preg_match('#^(.+)://#', $_POST['media_url'])) {
4349 $media_url = filter_var($_POST['media_url'], FILTER_VALIDATE_URL);
4350 } else {
4351 $media_url = $_POST['media_url'];
4352 }
4353 $program_keyword = false;
4354 if( !empty($_POST['program_keyword']) ) {
4355 $program_keyword = $_POST['program_keyword'];
4356 } else if( !empty($GeneralSettings['blubrry_program_keyword']) ) {
4357 $program_keyword = $GeneralSettings['blubrry_program_keyword'];
4358 }
4359
4360 if (!empty($program_keyword) && !preg_match('/[A-Za-z0-9\_]+/', $program_keyword)) {
4361 wp_die();
4362 }
4363 if( strpos($media_url, 'http://') !== 0 && strpos($media_url, 'https://') !== 0 && $hosting != 1 ) // If the url entered does not start with a http:// or https://
4364 {
4365 $media_url = rtrim($GeneralSettings['default_url'], '/') .'/'. $media_url;
4366 }
4367 // for media creek urls, just verify the content.blubrry.com version
4368 $orig_url = false;
4369 if (strpos($media_url, 'mc.blubrry.com') !== false) {
4370 $orig_url = $media_url;
4371 //remove query string
4372 $media_url_array = explode('?', $media_url);
4373 $media_url = $media_url_array[0];
4374 // replace media host
4375 $media_url = str_replace('mc.blubrry.com', 'content.blubrry.com', $media_url);
4376 }
4377
4378 $ContentType = false;
4379 $UrlParts = parse_url($media_url);
4380 if( !empty($UrlParts['path']) )
4381 {
4382 // using functions that already exist in WordPress when possible:
4383 $ContentType = powerpress_get_contenttype($UrlParts['path'], false);
4384 }
4385
4386 if (!$hosting) {
4387 if (!SSRFCheck($media_url, $feed_slug, true)) {
4388 return false;
4389 }
4390 } else {
4391 // hosting flag means unpublished--use filename only
4392 $media_url = powerpress_extract_filename($media_url);
4393 }
4394 if( !$ContentType )
4395 {
4396 $error = __('Unable to determine content type of media (e.g. audio/mpeg). Verify file extension is correct and try again.', 'powerpress');
4397 echo "$feed_slug\n";
4398 echo $error;
4399 wp_die();
4400 }
4401
4402 // Get media info here...
4403 if( $hosting )
4404 $MediaInfo = powerpress_get_media_info($media_url, $program_keyword );
4405 else
4406 $MediaInfo = powerpress_get_media_info_local($media_url, '', 0, '', true);
4407
4408 //If the file is unpublished, check to make sure the user has hosting space
4409 if( strpos($media_url, 'http://') !== 0 && strpos($media_url, 'https://') !== 0) {
4410 if (!empty($MediaInfo['hosting_status'])) {
4411 $hosting_status = esc_html($MediaInfo['hosting_status']);
4412 if (empty($MediaInfo['error'])) {
4413 $MediaInfo['error'] = $hosting_status;
4414 } else {
4415 $MediaInfo['error'] .= ' ' . $hosting_status;
4416 }
4417 } else if (isset($MediaInfo['space_remaining']) && !$MediaInfo['space_remaining']) {
4418 if (empty($MediaInfo['error'])) {
4419 $MediaInfo['error'] = __('This file exceeds your monthly publishing limit.', 'powerpress');
4420 } else {
4421 $MediaInfo['error'] .= ' ' . __('This file exceeds your monthly publishing limit.', 'powerpress');
4422 }
4423 }
4424 }
4425
4426 echo "$feed_slug\n";
4427 if (strpos($media_url, 'chrt.fm') !== false || strpos($media_url, 'chtbl') !== false) {
4428 if (empty($MediaInfo['error'])) {
4429 $MediaInfo['error'] = __("Previous Chartable Users: If you’re publishing a new episode please ensure that you have removed the Chartable stats redirect on your RSS feed. Chartable: Remove. Blubrry Prefix: Include.", 'powerpress') . " ";
4430 } else {
4431 $MediaInfo['error'] .= __(" Previous Chartable Users: If you’re publishing a new episode please ensure that you have removed the Chartable stats redirect on your RSS feed. Chartable: Remove. Blubrry Prefix: Include.", 'powerpress') . " ";
4432 }
4433 }
4434 if( !empty($MediaInfo['error']) ) {
4435 echo $MediaInfo['error'];
4436 if( preg_match('/^https?\:\/\//i', $media_url) )
4437 echo '<br />'. sprintf('Test: %s', "<a href=\"" . esc_attr($media_url) . "\" target=\"_blank\">" . htmlspecialchars($media_url) . "</a>");
4438 }
4439 echo "\n";
4440
4441 if( !isset($MediaInfo['error']) )
4442 {
4443 //substr('', 'abc');
4444 echo "VERIFY-OK\n";
4445 echo "$feed_slug\n"; // swap positions
4446 if (!empty($MediaInfo['length'])) {
4447 echo "{$MediaInfo['length']}\n";
4448 } else {
4449 echo "\n";
4450 }
4451 if (!empty($MediaInfo['duration'])) {
4452 echo powerpress_readable_duration($MediaInfo['duration'], true) . "\n";
4453 } else {
4454 echo "\n";
4455 }
4456 echo htmlspecialchars($orig_url ?: ($MediaInfo['enclosure_url'] ?? '')) . "\n";
4457 if (isset($MediaInfo['warnings']))
4458 echo $MediaInfo['warnings'];
4459
4460 echo "\n"; // make sure this line is ended
4461 wp_die();
4462 }
4463
4464 wp_die();
4465 }
4466
4467 add_action('wp_ajax_powerpress_media_info', 'powerpress_media_info_ajax');
4468
4469 function powerpress_metamarks_addrow_ajax()
4470 {
4471 // Check for nonce security
4472 if (!isset($_POST['nonce'])) {
4473 exit;
4474 }
4475 if ( ! wp_verify_nonce( $_POST['nonce'], 'powerpress-metamarks-addrow' ) ) {
4476 exit;
4477 }
4478 require_once(POWERPRESS_ABSPATH .'/views/episode-box.php');
4479 powerpress_metamarks_addrow();
4480 }
4481 add_action('wp_ajax_powerpress_metamarks_addrow', 'powerpress_metamarks_addrow_ajax');
4482
4483 /**
4484 * handler to switch stats program view for multi-program mode
4485 */
4486 function powerpress_save_stats_program_ajax()
4487 {
4488 // check for nonce security
4489 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'powerpress_stats_program')) {
4490 wp_send_json_error(__('Security check failed.', 'powerpress'));
4491 return;
4492 }
4493
4494 // check user capabilities
4495 if (!current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS)) {
4496 wp_send_json_error(__('You do not have sufficient permission to manage options.', 'powerpress'));
4497 return;
4498 }
4499
4500 $program_keyword = isset($_POST['program_keyword']) ? sanitize_text_field($_POST['program_keyword']) : '';
4501 $stacked = !empty($_POST['stacked']);
4502
4503 if (empty($program_keyword)) {
4504 wp_send_json_error(__('No program selected to display stats.', 'powerpress'));
4505 return;
4506 }
4507
4508 // render widget and show card for the requested program
4509 require_once(POWERPRESS_ABSPATH . '/powerpressadmin-program-card.class.php');
4510 $programCard = new PowerPressProgramCard('podcast', $program_keyword);
4511
4512 wp_send_json_success([
4513 'stats_widget_html' => $programCard->get_stats_widget_html($stacked),
4514 'show_card_html' => $programCard->get_show_info_card_html(),
4515 'program_info' => $programCard->get_program_info_data()
4516 ]);
4517 }
4518 add_action('wp_ajax_powerpress_switch_program', 'powerpress_save_stats_program_ajax');
4519
4520 /**
4521 * ajax handler for lazy loading initial stats data
4522 * used when page renders with deferred loading for faster initial load
4523 */
4524 function powerpress_load_stats_ajax()
4525 {
4526 // check nonce
4527 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'powerpress_stats_program')) {
4528 wp_send_json_error(__('Security check failed.', 'powerpress'));
4529 return;
4530 }
4531
4532 // check permissions
4533 if (!current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS)) {
4534 wp_send_json_error(__('You do not have sufficient permission to manage options.', 'powerpress'));
4535 return;
4536 }
4537
4538 try {
4539 // program keyword is optional, uses default if not provided
4540 $program_keyword = isset($_POST['program_keyword']) ? sanitize_text_field($_POST['program_keyword']) : '';
4541 $stacked = !empty($_POST['stacked']);
4542
4543 require_once(POWERPRESS_ABSPATH . '/powerpressadmin-program-card.class.php');
4544 // non-deferred mode to fetch actual data
4545 $programCard = new PowerPressProgramCard('podcast', $program_keyword, false);
4546
4547 wp_send_json_success([
4548 'stats_widget_html' => $programCard->get_stats_widget_html($stacked),
4549 'show_card_html' => $programCard->get_show_info_card_html(),
4550 'program_info' => $programCard->get_program_info_data()
4551 ]);
4552 } catch (Exception $e) {
4553 wp_send_json_error('Error loading stats: ' . $e->getMessage());
4554 } catch (Error $e) {
4555 wp_send_json_error('Fatal error: ' . $e->getMessage());
4556 }
4557 }
4558 add_action('wp_ajax_powerpress_load_stats', 'powerpress_load_stats_ajax');
4559
4560 /**
4561 * ajax handler for fetching month view chart data
4562 * lazy-loaded when user toggles from week to month view
4563 */
4564 function powerpress_stats_month_ajax()
4565 {
4566 // check nonce
4567 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'powerpress_stats_program')) {
4568 wp_send_json_error(__('Security check failed.', 'powerpress'));
4569 return;
4570 }
4571
4572 // check permissions
4573 if (!current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS)) {
4574 wp_send_json_error(__('You do not have sufficient permission.', 'powerpress'));
4575 return;
4576 }
4577
4578 // program keyword is optional, uses default if not provided
4579 $program_keyword = isset($_POST['program_keyword']) ? sanitize_text_field($_POST['program_keyword']) : '';
4580
4581 require_once(POWERPRESS_ABSPATH . '/powerpressadmin-program-card.class.php');
4582
4583 $programCard = new PowerPressProgramCard('podcast', $program_keyword, false);
4584 if ($programCard->get_stats_tier() === 'basic') {
4585 wp_send_json_error(__('Month view requires a premium stats subscription.', 'powerpress'));
4586 return;
4587 }
4588
4589 $chart_data = $programCard->get_month_chart_data();
4590
4591 if ($chart_data) {
4592 // chart.display_average contains calculated 30-day average
4593 wp_send_json_success([
4594 'chart' => $chart_data
4595 ]);
4596 } else {
4597 wp_send_json_error(__('Unable to retrieve month stats.', 'powerpress'));
4598 }
4599 }
4600 add_action('wp_ajax_powerpress_stats_month', 'powerpress_stats_month_ajax');
4601
4602 /**
4603 * ajax handler for refreshing stats (clears cache)
4604 */
4605 function powerpress_refresh_stats_ajax()
4606 {
4607 // check for nonce security
4608 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'powerpress_stats_program')) {
4609 wp_send_json_error(__('Security check failed.', 'powerpress'));
4610 return;
4611 }
4612
4613 // check user capabilities
4614 if (!current_user_can(POWERPRESS_CAPABILITY_MANAGE_OPTIONS)) {
4615 wp_send_json_error(__('You do not have sufficient permission.', 'powerpress'));
4616 return;
4617 }
4618
4619 // clear stats cache
4620 delete_option('powerpress_stats');
4621
4622 // program keyword is optional
4623 $program_keyword = isset($_POST['program_keyword']) ? sanitize_text_field($_POST['program_keyword']) : '';
4624 $stacked = !empty($_POST['stacked']);
4625
4626 // clear blubrry caches so card data refreshes too
4627 powerpress_clear_blubrry_caches($program_keyword);
4628
4629 require_once(POWERPRESS_ABSPATH . '/powerpressadmin-program-card.class.php');
4630 $programCard = new PowerPressProgramCard('podcast', $program_keyword, false);
4631
4632 wp_send_json_success([
4633 'stats_widget_html' => $programCard->get_stats_widget_html($stacked),
4634 'show_card_html' => $programCard->get_show_info_card_html(),
4635 'program_info' => $programCard->get_program_info_data()
4636 ]);
4637 }
4638 add_action('wp_ajax_powerpress_refresh_stats', 'powerpress_refresh_stats_ajax');
4639
4640 function powerpress_create_subscribe_page()
4641 {
4642 // Check for nonce security
4643 if (!isset($_POST['nonce'])) {
4644 exit;
4645 }
4646 if ( ! wp_verify_nonce( $_POST['nonce'], 'powerpress-create-subscribe-page' ) ) {
4647 exit;
4648 }
4649 $ajax = ( defined('DOING_AJAX') && DOING_AJAX ); // Now we can use this function without an ajax call! :)
4650
4651 $template_url = 'http://plugins.svn.wordpress.org/powerpress/assets/subscribe_template/';
4652 $languages = array();
4653 $language = get_option( 'WPLANG' );
4654 if( !empty($language) ) {
4655 switch( $language )
4656 {
4657 // Template translated for the following languages
4658 case 'en_AU':
4659 case 'en_CA':
4660 case 'en_GB':
4661 case 'en_NZ':
4662 case 'en_ZA': {
4663 $languages[] = $language; // Placed at the top of array
4664 }; break;
4665 }
4666 }
4667 $languages[] = 'en_US'; // fallback to the en_US version
4668
4669 $template_content = false;
4670 foreach( $languages as $index => $lang )
4671 {
4672 $template_content = powerpress_remote_fopen( $template_url . $lang . '.txt' );
4673 if( empty($template_content) ) { // Lets force cURL and see if that helps...
4674 $template_content = powerpress_remote_fopen($template_url . $lang . '.txt', false, array(), 15, false, true);
4675 }
4676 if( !empty($template_content) ) // We found a translation!
4677 break;
4678 }
4679
4680 if( empty($template_content) )
4681 {
4682 if( $ajax )
4683 {
4684 echo "PAGE-ERROR\n";
4685 echo __('Error occurred downloading subscribe page template.', 'powerpress');
4686 exit;
4687 }
4688 return false;
4689 }
4690
4691 // delete heading stuff from template
4692 $template_array = explode('[powerpress_subscribe]', $template_content);
4693 $template_content = '[powerpress_subscribe]' . $template_array[1];
4694
4695 // Create page here...
4696 global $user_ID;
4697 $page['post_type'] = 'page';
4698 $page['post_content'] = $template_content;
4699 $page['post_parent'] = 0;
4700 $page['post_author'] = $user_ID;
4701 $page['post_status'] = 'publish';
4702 $page['post_title'] = __('Subscribe to Podcast', 'powerpress');
4703
4704 $pageid = wp_insert_post ($page);
4705 if ($pageid == 0)
4706 {
4707 if( $ajax ) {
4708 echo "PAGE-ERROR\n";
4709 echo __('Error occurred creating subscribe page.', 'powerpress');
4710 exit;
4711 }
4712 return false;
4713 }
4714
4715 // Save to settings...
4716 $Save = array('subscribe_page_link_id'=>$pageid );
4717 powerpress_save_settings($Save, 'powerpress_feed_podcast');
4718
4719 // send back the page URL and Page ID
4720 if( $ajax ) {
4721 echo "PAGE-OK\n";
4722 echo "$pageid\n";
4723 echo get_page_link($pageid). "\n";
4724 echo $page['post_title']. "\n";
4725 exit;
4726 }
4727 return true;
4728 }
4729 add_action('wp_ajax_powerpress_create_subscribe_page', 'powerpress_create_subscribe_page');
4730
4731 function powerpress_disable_deprecated_feature_ajax() {
4732 if (!current_user_can('manage_options')) {
4733 wp_send_json_error('Unauthorized');
4734 }
4735
4736 if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'powerpress-disable-deprecated')) {
4737 wp_send_json_error('Invalid nonce');
4738 }
4739
4740 if (!isset($_POST['feature'])) {
4741 wp_send_json_error('Missing feature');
4742 }
4743
4744 $feature = sanitize_key($_POST['feature']);
4745 $allowed_features = ['taxonomy_podcasting', 'posttype_podcasting'];
4746
4747 if (!in_array($feature, $allowed_features)) {
4748 wp_send_json_error('Invalid feature');
4749 }
4750
4751 $General = get_option('powerpress_general');
4752 $General[$feature] = 0;
4753 update_option('powerpress_general', $General);
4754
4755 wp_send_json_success();
4756 }
4757 add_action('wp_ajax_powerpress_disable_deprecated_feature', 'powerpress_disable_deprecated_feature_ajax');
4758
4759 function powerpress_cat_row_actions($actions, $object)
4760 {
4761 $General = get_option('powerpress_general');
4762
4763
4764 // New 3.0+ tag in taxonomy check
4765 if( !empty($General['tag_casting']) && !empty($object->taxonomy) && $object->taxonomy == 'tag' )
4766 {
4767 // TODO:
4768 }
4769
4770 // Otherwise from here on in, we're working with a category or nothing at all.
4771 if( empty($General['cat_casting']) )
4772 return $actions;
4773
4774 // 3.0 category in taxonomy check
4775 if( !empty($object->taxonomy) && $object->taxonomy != 'category' )
4776 return $actions;
4777
4778 $cat_id = (isset($object->term_id)?$object->term_id : $object->cat_ID);
4779
4780 if( empty($cat_id) )
4781 return $actions;
4782
4783 if( isset($General['custom_cat_feeds']) && is_array($General['custom_cat_feeds']) && in_array($cat_id, $General['custom_cat_feeds']) )
4784 {
4785 $edit_link = admin_url('admin.php?page=powerpress/powerpressadmin_categoryfeeds.php&amp;from_categories=1&amp;action=powerpress-editcategoryfeed&amp;cat=') . $cat_id;
4786 $actions['powerpress'] = '<a href="' . $edit_link . '" title="'. __('Edit Blubrry PowerPress Podcast Settings', 'powerpress') .'">' . str_replace(' ', '&nbsp;', __('Podcast Settings', 'powerpress')) . '</a>';
4787 }
4788 else
4789 {
4790 $edit_link = admin_url() . wp_nonce_url("admin.php?page=powerpress/powerpressadmin_categoryfeeds.php&amp;from_categories=1&amp;action=powerpress-addcategoryfeed&amp;taxonomy=category&amp;cat=".$cat_id, 'powerpress-add-taxonomy-feed');
4791 $actions['powerpress'] = '<a href="' . $edit_link . '" title="'. __('Add Blubrry PowerPress Podcasting Settings', 'powerpress') .'">' . str_replace(' ', '&nbsp;', __('Add Podcasting', 'powerpress')) . '</a>';
4792 }
4793 return $actions;
4794 }
4795
4796 add_filter('cat_row_actions', 'powerpress_cat_row_actions', 1,2);
4797 add_filter('tag_row_actions', 'powerpress_cat_row_actions', 1,2);
4798
4799 // Handles category and all other taxonomy terms
4800 function powerpress_delete_term($term_id, $tt_id, $taxonomy)
4801 {
4802 if( $taxonomy == 'category' )
4803 {
4804 $Settings = get_option('powerpress_general');
4805 if( isset($Settings['custom_cat_feeds']) )
4806 {
4807 $key = array_search($term_id, $Settings['custom_cat_feeds']);
4808 if( $key !== false )
4809 {
4810 unset( $Settings['custom_cat_feeds'][$key] );
4811 powerpress_save_settings($Settings); // Delete the feed from the general settings
4812 }
4813 }
4814 delete_option('powerpress_cat_feed_'.$term_id); // Delete the actual feed settings
4815 }
4816 else // All other taxonomies handled here
4817 {
4818 $Settings = get_option('powerpress_taxonomy_podcasting');
4819
4820 if( isset($Settings[ $tt_id ]) )
4821 {
4822 unset( $Settings[ $tt_id ] );
4823 powerpress_save_settings($Settings); // Delete the feed from the general settings
4824 }
4825 delete_option('powerpress_taxonomy_'.$tt_id); // Delete the actual feed settings
4826 }
4827 }
4828
4829 add_action('delete_term', 'powerpress_delete_term', 10, 3);
4830
4831
4832 function powerpress_edit_category_form($cat)
4833 {
4834 if( empty($cat) || !isset( $cat->cat_ID ) )
4835 {
4836 ?>
4837 <div>
4838 <?php
4839 $General = get_option('powerpress_general');
4840 if( !isset($General['cat_casting']) || $General['cat_casting'] == 0 )
4841 {
4842 $enable_link = admin_url() . wp_nonce_url('edit-tags.php?taxonomy=category&action=powerpress-enable-categorypodcasting', 'powerpress-enable-categorypodcasting');
4843 ?>
4844 <h2><?php echo __('PowerPress Category Podcasting'); ?></h2>
4845 <p><a href="<?php echo $enable_link; ?>" title="<?php echo __('Enable Category Podcasting', 'powerpress'); ?>"><?php echo __('Enable Category Podcasting', 'powerpress'); ?></a> <?php echo __('if you would like to add specific podcasting settings to your blog categories.', 'powerpress'); ?></p>
4846 <?php
4847 }
4848 else
4849 {
4850 ?>
4851 <h2><?php echo __('PowerPress Category Podcasting', 'powerpress'); ?></h2>
4852 <p><?php echo __('PowerPress Category Podcasting is enabled. Select \'Add Podcasting\' to add podcasting settings. Select <u>Podcast Settings</u> to edit existing podcast settings.', 'powerpress'); ?></p>
4853 <?php
4854 }
4855 ?>
4856 </div>
4857 <?php
4858 }
4859 }
4860 add_action('category_edit_form', 'powerpress_edit_category_form');
4861
4862 // Admin page, header
4863 function powerpress_admin_page_header($page=false, $nonce_field = 'powerpress-edit', $page_type='')
4864 {
4865 if( !$page )
4866 $page = 'powerpressadmin_basic';
4867 ?>
4868 <div class="wrap" id="powerpress_settings">
4869 <?php
4870 if( $nonce_field )
4871 {
4872 ?>
4873 <form enctype="multipart/form-data" method="post" action="<?php echo admin_url( 'admin.php?page='. urlencode($page) ) ?>">
4874 <?php
4875 wp_nonce_field($nonce_field);
4876 }
4877 if( !empty($page_type) )
4878 echo '<input type="hidden" name="page_type" value="'. $page_type .'" />';
4879
4880 powerpress_page_message_print();
4881 }
4882
4883 // Admin page, footer
4884 function powerpress_admin_page_footer($SaveButton=true, $form=true)
4885 {
4886 if( $SaveButton ) { ?>
4887 <h2 style="margin-bottom: 0;"><b><?php echo __('Looking for Support?','powerpress'); ?></b></h2>
4888 <p class="submit" style="margin-top: 0; margin-left: 2em;">
4889 <a title="<?php echo esc_attr(__('Blubrry Services Info', 'powerpress')); ?>"
4890 href="https://blubrry.com/services/podcast-hosting/"
4891 target="_blank"><?php echo __('Learn more about Blubrry Support Options', 'powerpress'); ?></a>
4892 </p>
4893 <p class="submit">
4894 <strong><i><?php echo powerpress_review_message(); ?></i></strong>
4895 </p>
4896 <?php } ?>
4897 <p style="font-size: 85%; text-align: center; padding-bottom: 35px; width: 100%;">
4898 <a href="https://blubrry.com/services/powerpress-plugin/" title="Blubrry PowerPress" target="_blank"><?php echo __('Blubrry PowerPress', 'powerpress'); ?></a> <?php echo POWERPRESS_VERSION; ?> &#8212;
4899 <a href="https://blubrry.com/services/podcast-hosting/" target="_blank" title="<?php echo __('Blubrry PowerPress and related Resources', 'powerpress'); ?>"><?php echo __('Resources', 'powerpress'); ?></a> |
4900 <a href="https://blubrry.com/support/" target="_blank" title="<?php echo __('Blubrry Support', 'powerpress'); ?>"><?php echo __('Support', 'powerpress'); ?></a>
4901 </p>
4902 <?php if( $form ) { ?>
4903 </form><?php } ?>
4904 </div>
4905 <?php
4906 }
4907
4908 // Admin page, footer
4909 function powerpress_settings_save_button($blue = false, $float_left = false)
4910 {
4911 if ($float_left) {
4912 $float_string = '';
4913 } else {
4914 $float_string = ' pp-save-button-container-right';
4915 }
4916 if ($blue) {
4917 $class = "powerpress_save_button_other";
4918 } else {
4919 $class = "powerpress_save_button";
4920 }?>
4921
4922 <div class="pp-save-button-container<?php echo $float_string; ?>">
4923 <input type="submit" name="Submit" class="<?php echo $class; ?>" value="<?php echo __('Save Changes', 'powerpress') ?>" />
4924 </div>
4925 <?php
4926 }
4927
4928 // Admin page, advanced mode: basic settings
4929 function powerpress_admin_page_basic()
4930 {
4931 powerpress_admin_page_header();
4932 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
4933 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
4934 powerpress_admin_basic();
4935 powerpress_admin_page_footer(true);
4936 }
4937
4938 // Admin page, advanced mode: basic settings
4939 function powerpress_admin_page_players()
4940 {
4941 powerpress_admin_page_header('powerpress/powerpressadmin_player.php');
4942 require_once( POWERPRESS_ABSPATH.'/powerpressadmin-player-page.php');
4943 powerpress_admin_players('audio');
4944 powerpress_admin_page_footer(true);
4945 }
4946
4947 function powerpress_admin_page_videoplayers()
4948 {
4949 powerpress_admin_page_header('powerpress/powerpressadmin_videoplayer.php');
4950 require_once( POWERPRESS_ABSPATH.'/powerpressadmin-player-page.php');
4951 powerpress_admin_players('video');
4952 powerpress_admin_page_footer(true);
4953 }
4954
4955 function powerpress_admin_page_mobileplayers()
4956 {
4957 powerpress_admin_page_header('powerpress/powerpressadmin_mobileplayer.php');
4958 require_once( POWERPRESS_ABSPATH.'/powerpressadmin-player-page.php');
4959 powerpress_admin_players('mobile');
4960 powerpress_settings_save_button(true);
4961 powerpress_admin_page_footer(true);
4962 }
4963
4964 // Admin page, advanced mode: feed settings
4965 function powerpress_admin_page_podpress_stats()
4966 {
4967 powerpress_admin_page_header('powerpress/powerpressadmin_podpress-stats.php');
4968 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-podpress-stats.php');
4969 powerpress_admin_podpress_stats();
4970 powerpress_admin_page_footer(false);
4971 }
4972
4973 // Migrate
4974 function powerpress_admin_page_migrate()
4975 {
4976 powerpress_admin_page_header('powerpress/powerpressadmin_migrate.php');
4977 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-migrate.php');
4978 powerpress_admin_migrate();
4979 powerpress_admin_page_footer(false);
4980 }
4981
4982 function powerpress_admin_page_import_feed()
4983 {
4984 powerpress_admin_page_header('powerpress/powerpressadmin_import_feed.php');
4985 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-import-feed.php');
4986 powerpress_admin_import_feed();
4987 powerpress_admin_page_footer(false);
4988 }
4989
4990 function marketing_footer($button = false) {
4991 // only display if not signed in
4992 $page = htmlspecialchars($_GET['page']);
4993 $creds = get_option('powerpress_creds');
4994 if (!$creds) {
4995 $pp_nonce = powerpress_login_create_nonce();
4996 echo '<div class="powerpress-blubrry-hosting-marketing">';
4997 echo '<img class="hosting-marketing-blubrry-logo" src="' . powerpress_get_root_url() . 'images/Blubrry2017Logo-LOWERCASE.svg" alt="Blubrry Podcasting" />';
4998 echo '<div class="hosting-marketing-text-container" ';
4999 if ($button) {
5000 echo 'style="width: 55%">';
5001 } else {
5002 echo 'style="width: 70%">';
5003 }
5004 echo '<h4 class="hosting-marketing-title">Publish everywhere from this website</h4>';
5005 echo '<h5 class="hosting-marketing-text">You want podcast hosting that\'s easy to use with full control. ';
5006 if ($button) {
5007 echo 'Try Blubrry hosting ';
5008 } else {
5009 echo '<a class="hosting-marketing-text" href="' . esc_attr(add_query_arg( '_wpnonce', $pp_nonce, admin_url("admin.php?page={$page}&step=blubrrySignup&onboarding_type=stats"))) . '" target="_blank">Try Blubrry hosting</a> ';
5010 }
5011 echo 'for free and enjoy additional publishing features with PowerPress.</h4></div>';
5012 if ($button) {
5013 echo '<a class="hosting-marketing-link-button" href="' . esc_attr(add_query_arg( '_wpnonce', $pp_nonce, admin_url("admin.php?page={$page}&step=blubrrySignup&onboarding_type=stats"))) . '" target="_blank">';
5014 echo '<button class="hosting-marketing-button">TRY BLUBRRY HOSTING FOR FREE</button>';
5015 echo '</a>';
5016 }
5017 echo '</div>';
5018 }
5019 }
5020
5021 function powerpress_admin_page_onboarding() {
5022 powerpress_admin_page_header('powerpress/powerpressadmin_onboarding.php', false);
5023 require_once( POWERPRESS_ABSPATH .'/class.powerpress_onboarding.php');
5024 $onboardinClass = new PowerpressOnboarding();
5025 $onboardinClass->router($_GET);
5026 powerpress_admin_page_footer(false, false);
5027 }
5028
5029
5030 // Admin page, advanced mode: custom feeds
5031 function powerpress_admin_page_customfeeds()
5032 {
5033 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5034
5035 if (!$Action) {
5036 $Action = (!empty($_POST['action'])? $_POST['action'] : false);
5037 }
5038
5039 switch( $Action )
5040 {
5041 case 'powerpress-editfeed' : {
5042 powerpress_admin_page_header('powerpress/powerpressadmin_customfeeds.php');
5043 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
5044 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
5045 $feed_slug = esc_attr($_GET['feed_slug']);
5046 powerpress_admin_editfeed('channel', $feed_slug);
5047 powerpress_admin_page_footer();
5048 }; break;
5049 default: {
5050 powerpress_admin_page_header('powerpress/powerpressadmin_customfeeds.php', 'powerpress-add-feed');
5051 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-customfeeds.php');
5052 powerpress_admin_customfeeds();
5053 powerpress_admin_page_footer(false);
5054 };
5055 }
5056 }
5057
5058 function powerpress_admin_page_live_item()
5059 {
5060 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5061 switch( $Action )
5062 {
5063 case 'powerpress-editfeed' : {
5064 powerpress_admin_page_header('powerpress/powerpressadmin_customfeeds.php');
5065 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
5066 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
5067 $feed_slug = esc_attr($_GET['feed_slug']);
5068 powerpress_admin_editfeed('channel', $feed_slug);
5069 powerpress_admin_page_footer();
5070 }; break;
5071 default: {
5072 powerpress_admin_page_header('powerpress/powerpressadmin_live_item.php', 'powerpress-live-item');
5073 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-live-item.php');
5074 powerpress_admin_live_item();
5075 powerpress_admin_page_footer(false);
5076 };
5077 }
5078 }
5079
5080 // Category feeds
5081 function powerpress_admin_page_categoryfeeds()
5082 {
5083 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5084 switch( $Action )
5085 {
5086 case 'powerpress-editcategoryfeed' : {
5087 powerpress_admin_page_header('powerpress/powerpressadmin_categoryfeeds.php');
5088 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
5089 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
5090 powerpress_admin_editfeed('category', intval($_GET['cat']) );
5091 powerpress_admin_page_footer();
5092 }; break;
5093 default: {
5094 powerpress_admin_page_header('powerpress/powerpressadmin_categoryfeeds.php', 'powerpress-add-categoryfeed');
5095 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-categoryfeeds.php');
5096 powerpress_admin_categoryfeeds();
5097 powerpress_admin_page_footer(false);
5098 };
5099 }
5100 }
5101
5102 // Taxonomy Feeds
5103 function powerpress_admin_page_taxonomyfeeds()
5104 {
5105 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5106 switch( $Action )
5107 {
5108 case 'powerpress-edittaxonomyfeed' : {
5109 if( !empty($_GET['ttid']) )
5110 {
5111 powerpress_admin_page_header('powerpress/powerpressadmin_taxonomyfeeds.php');
5112 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
5113 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
5114 powerpress_admin_editfeed('ttid', intval($_GET['ttid']));
5115 powerpress_admin_page_footer();
5116 }
5117 }; break;
5118 default: {
5119 powerpress_admin_page_header('powerpress/powerpressadmin_taxonomyfeeds.php', 'powerpress-add-taxonomyfeed');
5120 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-taxonomyfeeds.php');
5121 powerpress_admin_taxonomyfeeds();
5122 powerpress_admin_page_footer(false);
5123 };
5124 }
5125 }
5126
5127 // Custom Post Type Feeds
5128 function powerpress_admin_page_posttypefeeds()
5129 {
5130
5131 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5132 switch( $Action )
5133 {
5134 case 'powerpress-editposttypefeed' : {
5135 if( !empty($_GET['podcast_post_type']) && !empty($_GET['feed_slug']) ) {
5136
5137 powerpress_admin_page_header('powerpress/powerpressadmin_posttypefeeds.php');
5138 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-editfeed.php');
5139 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-basic.php');
5140 $post_type = esc_attr( $_GET['podcast_post_type'] );
5141 $feed_slug = esc_attr( $_GET['feed_slug'] );
5142 powerpress_admin_editfeed('post_type', $post_type, $feed_slug);
5143 powerpress_admin_page_footer();
5144
5145 }
5146 } break;
5147 default: {
5148 powerpress_admin_page_header('powerpress/powerpressadmin_posttypefeeds.php', 'powerpress-add-posttypefeed');
5149 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-posttypefeeds.php');
5150 powerpress_admin_posttypefeeds();
5151 powerpress_admin_page_footer(false);
5152 };
5153 }
5154 }
5155
5156 // Admin page, advanced mode: tools
5157 function powerpress_admin_page_tools()
5158 {
5159 $Action = (!empty($_GET['action'])? $_GET['action'] : false);
5160 if ($Action == 'powerpress-network-mode-off') {
5161 $GeneralSettings = get_option('powerpress_general');
5162 $GeneralSettings['network_mode'] = 0;
5163 powerpress_save_settings($GeneralSettings);
5164 $Action = '';
5165 } elseif ($Action == 'powerpress-network-mode-on') {
5166 $GeneralSettings = get_option('powerpress_general');
5167 $GeneralSettings['network_mode'] = 1;
5168 powerpress_save_settings($GeneralSettings);
5169 $Action = '';
5170 }
5171 switch( $Action )
5172 {
5173 case 'powerpress-podpress-epiosdes' : {
5174 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', 'powerpress-import-podpress');
5175 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-podpress.php');
5176 powerpress_admin_podpress();
5177 powerpress_admin_page_footer(false);
5178 }; break;
5179 case 'powerpress-mt-epiosdes': {
5180 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', 'powerpress-import-mt');
5181 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-mt.php');
5182 powerpress_admin_mt();
5183 powerpress_admin_page_footer(false);
5184 }; break;
5185 case 'powerpress-ping-sites': {
5186 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', 'powerpress-ping-sites');
5187 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-ping-sites.php');
5188 powerpress_admin_ping_sites();
5189 powerpress_admin_page_footer(false);
5190 }; break;
5191 case 'powerpress-find-replace': {
5192 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', 'powerpress-find-replace');
5193 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-find-replace.php');
5194 powerpress_admin_find_replace();
5195 powerpress_admin_page_footer(false);
5196 }; break;
5197 case 'powerpress-diagnostics': {
5198 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', false);
5199 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-diagnostics.php');
5200 powerpressadmin_diagnostics();
5201 powerpress_admin_page_footer(false, false);
5202 }; break;
5203 default: {
5204 powerpress_admin_page_header('powerpress/powerpressadmin_tools.php', false);
5205 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-tools.php');
5206 powerpress_admin_tools();
5207 powerpress_admin_page_footer(false, false);
5208 };
5209 }
5210 }
5211
5212 function powerpress_podpress_episodes_exist()
5213 {
5214 global $wpdb;
5215 $query = "SELECT post_id ";
5216 $query .= "FROM {$wpdb->postmeta} ";
5217 $query .= "WHERE meta_key LIKE '%podPressMedia' ";
5218 $query .= "LIMIT 0, 1";
5219 $results = $wpdb->get_results($query, ARRAY_A);
5220 if( count($results) )
5221 return true;
5222 return false;
5223 }
5224
5225 function powerpress_podpress_stats_exist()
5226 {
5227 global $wpdb;
5228 // First, see if the table exists...
5229 $query = "SHOW TABLES LIKE '{$wpdb->prefix}podpress_statcounts'";
5230 $wpdb->hide_errors();
5231 $results = $wpdb->get_results($query, ARRAY_A);
5232 $wpdb->show_errors();
5233 if( count($results) == 0 )
5234 return false;
5235
5236 // Now see if a record exists...
5237 $query = "SELECT `media` ";
5238 $query .= "FROM {$wpdb->prefix}podpress_statcounts ";
5239 $query .= "LIMIT 1";
5240 $results = $wpdb->get_results($query, ARRAY_A);
5241 if( count($results) )
5242 return true;
5243 return false;
5244 }
5245
5246 /*
5247 // Helper functions:
5248 */
5249 // Import podpress settings
5250 function powerpress_admin_import_podpress_settings()
5251 {
5252 // First pull in the Podpress settings
5253 $PodpressData = get_option('podPress_config');
5254 if( !$PodpressData )
5255 return false;
5256
5257 $General = get_option('powerpress_general');
5258 if( !$General)
5259 $General = array();
5260 $General['process_podpress'] = 1;
5261 $General['display_player'] = 1;
5262 $General['player_function'] = 1;
5263 $General['podcast_link'] = 1;
5264 // Lets try to copy settings from podpress
5265 $General['default_url'] = $PodpressData['mediaWebPath'];
5266 if( substr($General['default_url'], 0, -1) != '/' )
5267 $General['default_url'] .= '/'; // Add the trailing slash, donno it's not there...
5268
5269 // Insert the blubrry redirect
5270 if( isset($PodpressData['statBluBrryProgramKeyword']) && strlen($PodpressData['statBluBrryProgramKeyword']) > 2 )
5271 {
5272 $General['redirect1'] = 'https://media.blubrry.com/'.$PodpressData['statBluBrryProgramKeyword'].'/';
5273 }
5274
5275 // Insert the Podtrac redirect
5276 if( $PodpressData['enable3rdPartyStats'] == 'PodTrac' )
5277 {
5278 if( $General['redirect1'] )
5279 $General['redirect2'] = 'http://www.podtrac.com/pts/redirect.mp3/';
5280 else
5281 $General['redirect1'] = 'http://www.podtrac.com/pts/redirect.mp3/';
5282 }
5283
5284 if( $PodpressData['contentDownload'] == 'enabled' )
5285 $General['podcast_link'] = 1;
5286 else
5287 $General['podcast_link'] = 0;
5288
5289 if( $PodpressData['contentPlayer'] == 'both' )
5290 $General['player_function'] = 1;
5291 else if( $PodpressData['contentPlayer'] == 'inline' )
5292 $General['player_function'] = 2;
5293 else if( $PodpressData['contentPlayer'] == 'popup' )
5294 $General['player_function'] = 3;
5295 else
5296 $General['player_function'] = 0;
5297
5298 if( $PodpressData['contentPlayer'] == 'start' )
5299 $General['display_player'] = 2;
5300 else
5301 $General['display_player'] = 1;
5302
5303 // save these imported general settings
5304 powerpress_save_settings($General, 'powerpress_general');
5305
5306 $FeedSettings = get_option('powerpress_feed');
5307
5308 if( !$FeedSettings ) // If no feed settings, lets set defaults or copy from podpress.
5309 $FeedSettings = array();
5310
5311 $FeedSettings['apply_to'] = 1; // Default, apply to all the rss2 feeds
5312
5313 $FeedSettings['itunes_image'] = $PodpressData['iTunes']['image'];
5314 if( strstr($FeedSettings['itunes_image'], 'powered_by_podpress') )
5315 $FeedSettings['itunes_image'] = ''; // We're not using podpress anymore
5316
5317 $FeedSettings['itunes_talent_name'] = $PodpressData['iTunes']['author'];
5318 $FeedSettings['copyright'] = $PodpressData['rss_copyright'];
5319
5320 // Categories are tricky...
5321 $iTunesCategories = powerpress_itunes_categories(true);
5322 for( $x = 0; $x < 3; $x++ )
5323 {
5324 if( isset($PodpressData['iTunes']['category'][$x]) )
5325 {
5326 $CatDesc = str_replace(':', ' > ', $PodpressData['iTunes']['category'][$x]);
5327 $CatKey = array_search($CatDesc, $iTunesCategories);
5328 if( $CatKey )
5329 $FeedSettings['itunes_cat_'.($x+1)] = $CatKey;
5330 }
5331 }
5332
5333 if( $PodpressData['iTunes']['explicit'] == 'No' )
5334 $FeedSettings['itunes_explicit'] = 0;
5335 else if( $PodpressData['iTunes']['explicit'] == 'Yes' )
5336 $FeedSettings['itunes_explicit'] = 1;
5337 else if( $PodpressData['iTunes']['explicit'] == 'Clean' )
5338 $FeedSettings['itunes_explicit'] = 2;
5339
5340 if( !empty($PodpressData['iTunes']['FeedID']) )
5341 $FeedSettings['itunes_url'] = 'http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id='. $PodpressData['iTunes']['FeedID'];
5342
5343 // Lastly, lets try to get the RSS image from the database
5344 $RSSImage = get_option('rss_image');
5345 if( $RSSImage )
5346 $FeedSettings['itunes_image'] = $RSSImage;
5347 if( strstr($FeedSettings['itunes_image'], 'powered_by_podpress') )
5348 $FeedSettings['itunes_image'] = ''; // We're not using podpress anymore
5349 $AdminEmail = get_option('admin_email');
5350 if( $AdminEmail )
5351 $FeedSettings['email'] = $AdminEmail;
5352
5353 // save these imported feed settings
5354 powerpress_save_settings($FeedSettings, 'powerpress_feed');
5355 return true;
5356 }
5357
5358 // Import plugin Podcasting settings
5359 function powerpress_admin_import_podcasting_settings()
5360 {
5361 $Changes = false;
5362
5363 $General = get_option('powerpress_general');
5364 if( !$General)
5365 {
5366 $General = array();
5367 $Changes = true;
5368 $General['process_podpress'] = 0;
5369 $General['display_player'] = 1;
5370 $General['player_function'] = 1;
5371 $General['podcast_link'] = 1;
5372 }
5373
5374 $pod_player_location = get_option('pod_player_location');
5375 if( $pod_player_location == 'top' ) // display player below posts is default in PowerPress
5376 {
5377 $General['display_player'] = 2; // display above posts
5378 $Changes = true;
5379 }
5380
5381 $pod_audio_width = get_option('pod_audio_width');
5382 if( is_int( (int)$pod_audio_width) && $pod_audio_width > 100 ) // audio player width
5383 {
5384 $General['player_width_audio'] = $pod_audio_width;
5385 $Changes = true;
5386 }
5387
5388 $pod_player_width = get_option('pod_player_width');
5389 if( is_int( (int)$pod_player_width) && $pod_player_width > 100 ) // video player width
5390 {
5391 $General['player_width'] = $pod_player_width;
5392 $Changes = true;
5393 }
5394
5395 $pod_player_height = get_option('pod_player_height');
5396 if( is_int( (int)$pod_player_height) && $pod_player_height > 100 ) // video player width
5397 {
5398 $General['player_height'] = $pod_player_height;
5399 $Changes = true;
5400 }
5401
5402 if( $Changes == true )
5403 {
5404 // save these imported general settings
5405 powerpress_save_settings($General, 'powerpress_general');
5406 }
5407
5408 $FeedChanges = false;
5409 // Feed settings:
5410 $FeedSettings = get_option('powerpress_feed');
5411
5412 if( !$FeedSettings ) // If no feed settings, lets set defaults or copy from podpress.
5413 {
5414 $FeedSettings = array();
5415 $FeedChanges = true;
5416 }
5417
5418 $pod_itunes_image = get_option('pod_itunes_image');
5419 if( $pod_itunes_image )
5420 {
5421 $FeedSettings['itunes_image'] = $pod_itunes_image;
5422 $FeedChanges = true;
5423 }
5424
5425 $iTunesCategories = powerpress_itunes_categories(true);
5426 for( $x = 1; $x <= 3; $x++ )
5427 {
5428 $pod_itunes_cat = get_option('pod_itunes_cat'.$x);
5429 $find = str_replace('&amp;', '&', $pod_itunes_cat);
5430 $CatDesc = str_replace('||', ' > ', $find);
5431 $CatKey = array_search($CatDesc, $iTunesCategories);
5432 if( $CatKey )
5433 {
5434 $FeedSettings['itunes_cat_'.$x] = $CatKey;
5435 $FeedChanges = true;
5436 }
5437 }
5438
5439 $pod_itunes_ownername = get_option('pod_itunes_ownername');
5440 if( $pod_itunes_ownername )
5441 {
5442 $FeedSettings['itunes_talent_name'] = stripslashes($pod_itunes_ownername);
5443 $FeedChanges = true;
5444 }
5445
5446 $pod_itunes_owneremail = get_option('pod_itunes_owneremail');
5447 if( $pod_itunes_owneremail )
5448 {
5449 $FeedSettings['email'] = $pod_itunes_owneremail;
5450 $FeedChanges = true;
5451 }
5452
5453 $rss_language = get_option('rss_language');
5454 if( $rss_language )
5455 {
5456 $FeedSettings['rss_language'] = $rss_language;
5457 $FeedChanges = true;
5458 }
5459
5460 $pod_itunes_explicit = get_option('pod_itunes_explicit');
5461 if( $pod_itunes_explicit == 'yes' )
5462 {
5463 $FeedSettings['itunes_explicit'] = 1;
5464 $FeedChanges = true;
5465 }
5466 else if( $pod_itunes_explicit == 'clean' )
5467 {
5468 $FeedSettings['itunes_explicit'] = 2;
5469 $FeedChanges = true;
5470 }
5471
5472 if( $FeedChanges )
5473 {
5474 // save these imported feed settings
5475 powerpress_save_settings($FeedSettings, 'powerpress_feed');
5476 }
5477
5478 return ($Changes||$FeedChanges);
5479 }
5480
5481 function powerpress_admin_episodes_not_hosted() {
5482 // no need to specify feed slug--this is for use during onboarding, before additional feeds are set up
5483 $field = 'enclosure';
5484 global $wpdb;
5485 if ($results = $wpdb->get_results("SELECT COUNT(pm.post_id) AS episodes_total FROM $wpdb->posts AS p INNER JOIN $wpdb->postmeta AS pm ON pm.post_id = p.ID WHERE pm.meta_key = '$field' AND p.post_status <> 'auto-draft' AND p.post_status <> 'trash' AND p.post_status <> 'inherit' AND pm.meta_value NOT LIKE '%content.blubrry.com%' ", ARRAY_A)) {
5486 if (count($results)) {
5487 foreach ($results as $key => $row) {
5488 if ($row['episodes_total'])
5489 return $row['episodes_total'];
5490 }
5491 }
5492 }
5493 return 0;
5494 }
5495
5496 /**
5497 * count episodes for a feed based on feed type.
5498 *
5499 * @param string $feed_slug feed slug (used for 'custom' and 'posttype' types)
5500 * @param string $feed_type feed type: 'custom', 'category', 'taxonomy', or 'posttype'
5501 * @param mixed $type_id context identifier - term_taxonomy_id for category/taxonomy, post_type string for posttype
5502 * @return int episode count (0 if none or on error)
5503 */
5504 function powerpress_admin_episodes_per_feed($feed_slug, $feed_type='custom', $type_id=null)
5505 {
5506 global $wpdb;
5507
5508 switch ($feed_type) {
5509 case 'category':
5510 case 'taxonomy':
5511 // count episodes in a taxonomy term (category or custom taxonomy)
5512 $type_id = absint($type_id);
5513 if ($type_id <= 0) return 0;
5514
5515 $count = $wpdb->get_var($wpdb->prepare(
5516 "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p
5517 INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
5518 INNER JOIN {$wpdb->term_relationships} tr ON tr.object_id = p.ID
5519 WHERE pm.meta_key = 'enclosure'
5520 AND tr.term_taxonomy_id = %d
5521 AND p.post_status NOT IN ('draft', 'auto-draft', 'trash', 'inherit')",
5522 $type_id
5523 ));
5524 break;
5525
5526 case 'posttype':
5527 // count episodes for a posttype feed
5528 $feed_slug = sanitize_key($feed_slug);
5529 $type_id = sanitize_key($type_id);
5530 if (empty($type_id)) return 0;
5531
5532 $meta_key = ($feed_slug === 'podcast' || empty($feed_slug)) ? 'enclosure' : '_' . $feed_slug . ':enclosure';
5533 $count = $wpdb->get_var($wpdb->prepare(
5534 "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p
5535 INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
5536 WHERE pm.meta_key = %s
5537 AND p.post_type = %s
5538 AND p.post_status NOT IN ('draft', 'auto-draft', 'trash', 'inherit')",
5539 $meta_key,
5540 $type_id
5541 ));
5542 break;
5543
5544 case 'custom':
5545 default:
5546 // count episodes for custom channel feeds
5547 $feed_slug = sanitize_key($feed_slug);
5548 $meta_key = ($feed_slug === 'podcast' || empty($feed_slug)) ? 'enclosure' : '_' . $feed_slug . ':enclosure';
5549 $count = $wpdb->get_var($wpdb->prepare(
5550 "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p
5551 INNER JOIN {$wpdb->postmeta} pm ON pm.post_id = p.ID
5552 WHERE pm.meta_key = %s
5553 AND p.post_status NOT IN ('draft', 'auto-draft', 'trash', 'inherit')",
5554 $meta_key
5555 ));
5556 break;
5557 }
5558
5559 return (int) ($count ?: 0);
5560 }
5561
5562 // Set the default settings basedon the section user is in.
5563 function powerpress_default_settings($Settings, $Section='basic')
5564 {
5565 // Set the default settings if the setting does not exist...
5566 switch($Section)
5567 {
5568 case 'basic': {
5569 // Nothing needs to be pre-set in the basic settings area
5570
5571 if( !isset($Settings['player_options'] ) )
5572 {
5573 $Settings['player_options'] = 0;
5574 if( isset($Settings['player']) && $Settings['player'] != '' && $Settings['player'] != 'default' )
5575 $Settings['player_options'] = 1;
5576 }
5577
5578 if( !isset($Settings['cat_casting'] ) )
5579 {
5580 $Settings['cat_casting'] = 0;
5581 //if( isset($Settings['custom_cat_feeds']) && count($Settings['custom_cat_feeds']) > 0 )
5582 // $Settings['cat_casting'] = 1;
5583 }
5584
5585 if( !isset($Settings['channels'] ) )
5586 $Settings['channels'] = 0;
5587 if( isset($Settings['custom_feeds']) && count($Settings['custom_feeds']) > 0 ) // They can't delete this until they remove all the channels
5588 $Settings['channels'] = 1;
5589
5590 }; break;
5591 case 'editfeed': {
5592 if( !isset($Settings['apply_to']) )
5593 $Settings['apply_to'] = 1; // Make sure settings are applied to all feeds by default
5594 }; break;
5595 case 'appearance': {
5596 if( !isset($Settings['display_player']) )
5597 $Settings['display_player'] = 1;
5598 if( !isset($Settings['player_function']) )
5599 $Settings['player_function'] = 1;
5600 if( !isset($Settings['podcast_link']) )
5601 $Settings['podcast_link'] = 1;
5602 if( !isset($Settings['display_player_excerpt']) )
5603 $Settings['display_player_excerpt'] = 0;
5604 //if( !isset($Settings['display_player_disable_mobile']) )
5605 // $Settings['display_player_disable_mobile'] = 0;
5606
5607 // Play in page obsolete, switching here:
5608 if( $Settings['player_function'] == 5 )
5609 $Settings['player_function'] = 1;
5610 else if( $Settings['player_function'] == 4 )
5611 $Settings['player_function'] = 2;
5612 if(!isset($Settings['subscribe_widget_shape'])) {
5613 $Settings['subscribe_widget_shape'] = 'squared';
5614 }
5615 if(!isset($Settings['subscribe_no_important_styling'])) {
5616 $Settings['subscribe_no_important_styling'] = 'include';
5617 }
5618 }; break;
5619 }
5620
5621 return $Settings;
5622 }
5623
5624 // Call this function when there is no enclosure currently detected for the post but users set the option to auto-add first media file linked within post option is checked.
5625 function powerpress_do_enclose( $content, $post_ID, $use_last_media_link = false )
5626 {
5627 $ltrs = '\w';
5628 $gunk = '/#~:.?+=&%@!\-';
5629 $punc = '.:?\-';
5630 $any = $ltrs . $gunk . $punc;
5631
5632 preg_match_all( "{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp );
5633
5634 if( $use_last_media_link )
5635 $post_links_temp[0] = array_reverse($post_links_temp[0]);
5636
5637 $enclosure = false;
5638 foreach ( (array) $post_links_temp[0] as $link_test ) {
5639 $test = parse_url( $link_test );
5640 // Wordpress also acecpts query strings, which doesn't matter to us what's more important is taht the request ends with a file extension.
5641 // get the file extension at the end of the request:
5642 if( preg_match('/\.([a-z0-9]{2,7})$/i', $link_test, $matches) )
5643 {
5644 // see if the file extension is one of the supported media types...
5645 $content_type = powerpress_get_contenttype('test.'.$matches[1], false); // we want to strictly use the content types known for media, so pass false for second argument
5646 if( $content_type )
5647 {
5648 $enclosure = $link_test;
5649 $MediaInfo = powerpress_get_media_info_local($link_test, $content_type);
5650 if( !isset($MediaInfo['error']) && !empty($MediaInfo['length']) )
5651 {
5652 // Insert enclosure here:
5653 $EnclosureData = $link_test . "\n" . $MediaInfo['length'] . "\n". $content_type;
5654 if( !empty($MediaInfo['duration']) )
5655 $EnclosureData .= "\n".serialize( array('duration'=>$MediaInfo['duration']) );
5656 add_post_meta($post_ID, 'enclosure', $EnclosureData, true);
5657 break; // We don't wnat to insert anymore enclosures, this was it!
5658 }
5659 }
5660 }
5661 }
5662 }
5663
5664 function powerpress_get_episode_count($feed_slug, $post_type = 'post')
5665 {
5666 global $wpdb;
5667 $custom_field = 'enclosure';
5668 if( $feed_slug != 'podcast' )
5669 $custom_field = '_'. $feed_slug .':enclosure';
5670
5671 $query = "SELECT COUNT( * ) AS num_posts FROM {$wpdb->posts} ";
5672 $query .= "INNER JOIN {$wpdb->postmeta} ON {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id ";
5673 $query .= "WHERE {$wpdb->postmeta}.meta_key = '". $custom_field ."' AND post_type = %s AND post_status = 'publish' ";
5674
5675 $results = $wpdb->get_results( $wpdb->prepare( $query, $post_type ), ARRAY_A );
5676 if( !empty($results[0]['num_posts']) )
5677 {
5678 return $results[0]['num_posts'];
5679 }
5680 return 0;
5681 }
5682
5683 function powerpress_get_media_info_local($media_file, $content_type='', $file_size=0, $duration='', $return_warnings=false)
5684 {
5685 $error_msg = '';
5686 $warning_msg = '';
5687 if( $content_type == '' )
5688 $content_type = powerpress_get_contenttype($media_file);
5689
5690 if( isset($GLOBALS['objWPOSFLV']) && is_object($GLOBALS['objWPOSFLV']) )
5691 return array('error'=>__('The WP OS FLV plugin is not compatible with Blubrry PowerPress.', 'powerpress') );
5692
5693 $get_duration_info = ( ($content_type == 'audio/mpeg' || $content_type == 'audio/x-m4a' || $content_type == 'video/x-m4v' || $content_type == 'video/mp4' || $content_type == 'audio/ogg' ) && $duration === '');
5694 // Lets use the mp3info class:
5695 require_once( POWERPRESS_ABSPATH .'/mp3info.class.php');
5696 $Mp3Info = new Mp3Info();
5697
5698 if( $get_duration_info )
5699 {
5700 if( preg_match('/video/i', $content_type) )
5701 {
5702 if( defined('POWERPRESS_DOWNLOAD_BYTE_LIMIT_VIDEO') )
5703 $Mp3Info->SetDownloadBytesLimit(POWERPRESS_DOWNLOAD_BYTE_LIMIT_VIDEO);
5704 }
5705 else
5706 {
5707 if( defined('POWERPRESS_DOWNLOAD_BYTE_LIMIT') )
5708 $Mp3Info->SetDownloadBytesLimit(POWERPRESS_DOWNLOAD_BYTE_LIMIT);
5709 }
5710 }
5711
5712 $Mp3Data = $Mp3Info->GetMp3Info($media_file, !$get_duration_info);
5713 if( $Mp3Data )
5714 {
5715 if( $Mp3Info->GetRedirectCount() > 5 )
5716 {
5717 // Add a warning that the redirect count exceeded 5, which may prevent some podcatchers from downloading the media.
5718 $warning = sprintf( __('Warning, the Media URL %s contains %d redirects.', 'powerpress'), $media_file, $Mp3Info->GetRedirectCount() );
5719 $warning .= ' [<a href="https://blubrry.com/support/powerpress-documentation/warning-messages-explained/" title="'. __('PowerPress Warnings Explained', 'powerpress') .'" target="_blank">'. __('PowerPress Warnings Explained') .'</a>]';
5720 if( $return_warnings )
5721 $warning_msg .= $warning;
5722 else
5723 powerpress_page_message_add_error( $warning );
5724 }
5725
5726 if( $file_size == 0 )
5727 $file_size = $Mp3Info->GetContentLength();
5728
5729 if( $get_duration_info )
5730 {
5731 $playtime_string = ( !empty($Mp3Data['playtime_string']) ? $Mp3Data['playtime_string'] : '');
5732 $duration = powerpress_readable_duration($playtime_string, true); // Fix so it looks better when viewed for editing
5733 }
5734
5735 $GeneralSettings = get_option('powerpress_general');
5736 if( empty($GeneralSettings['hide_warnings']) && count( $Mp3Info->GetWarnings() ) > 0 )
5737 {
5738 $Warnings = $Mp3Info->GetWarnings();
5739 foreach( $Warnings as $null => $warning )
5740 {
5741 $warning = sprintf( __('Warning, Media URL %s', 'powerpress'), $media_file) .': '. $warning .' [<a href="https://blubrry.com/support/powerpress-documentation/warning-messages-explained/" target="_blank">'. __('PowerPress Warnings Explained', 'powerpress') .'</a>]';
5742 if( $return_warnings )
5743 $warning_msg .= $warning;
5744 else
5745 powerpress_page_message_add_error( $warning );
5746 }
5747 }
5748 }
5749 else
5750 {
5751 if( $Mp3Info->GetError() != '' )
5752 return array('error'=>$Mp3Info->GetError() );
5753 else
5754 return array('error'=>__('Error occurred obtaining media information.', 'powerpress') );
5755 }
5756
5757 if( $file_size == 0 )
5758 return array('error'=>__('Error occurred obtaining media file size.', 'powerpress') );
5759
5760 if( $return_warnings && $warning_msg != '' )
5761 return array('content-type'=>$content_type, 'length'=>$file_size, 'duration'=>$duration, 'warnings'=>$warning_msg, 'enclosure_url' => $media_file);
5762 return array('content-type'=>$content_type, 'length'=>$file_size, 'duration'=>$duration, 'enclosure_url' => $media_file);
5763 }
5764
5765 function powerpress_print_options($options,$selected=null, $return=false)
5766 {
5767 reset($options);
5768 if( $return )
5769 {
5770 $html = '';
5771 foreach( $options as $key=> $value )
5772 {
5773 $html .= '<option value="'. esc_attr($key) .'"'. ( ($selected !== null && strcmp($selected, $key) == 0 )?' selected':'') .'>';
5774 $html .= htmlspecialchars($value);
5775 $html .= "</option>\n";
5776 }
5777
5778 return $html;
5779 }
5780 foreach( $options as $key=> $value )
5781 {
5782 echo '<option value="'. esc_attr($key) .'"'. ( ($selected !== null && strcmp($selected, $key) == 0 )?' selected':'') .'>';
5783 echo htmlspecialchars($value);
5784 echo "</option>\n";
5785 }
5786 }
5787
5788 /*
5789 Help Link
5790 2.0 beta
5791 */
5792 function powerpress_help_link($link, $title = false )
5793 {
5794 if( $title == '' )
5795 $title = __('Learn More', 'powerpress');
5796
5797 return ' [<a href="'. $link .'" title="'. htmlspecialchars($title) .'" target="_blank">'. htmlspecialchars($title) .'</a>] ';
5798 }
5799
5800 $g_SupportUploads = null;
5801 function powerpressadmin_support_uploads()
5802 {
5803 global $g_SupportUploads;
5804 if( $g_SupportUploads != null )
5805 return $g_SupportUploads;
5806
5807 $g_SupportUploads = false;
5808 $UploadArray = wp_upload_dir();
5809 if( false === $UploadArray['error'] )
5810 {
5811 $upload_path = $UploadArray['basedir'].'/powerpress/';
5812
5813 if( !file_exists($upload_path) )
5814 $g_SupportUploads = @wp_mkdir_p( rtrim($upload_path, '/') );
5815 else
5816 $g_SupportUploads = true;
5817 }
5818 return $g_SupportUploads;
5819 }
5820
5821 function powerpressadmin_new($span = false, $additional_style='')
5822 {
5823 $style = 'color: #CC0000; font-weight: bold; background-color: white; padding: 2px; border-radius: 4px;';
5824 if( !empty($additional_style) )
5825 $style .= $additional_style;
5826 if ($span) {
5827 return '<span style="'.$style.'">'. __('New!', 'powerpress') .'</span>';
5828 }
5829 return '<sup style="'.$style.'">'. __('New!', 'powerpress') .'</sup>';
5830 }
5831
5832 function powerpressadmin_community_news($items=4, $pp_settings=false)
5833 {
5834 require_once( POWERPRESS_ABSPATH. '/powerpress-player.php'); // Include, if not included already
5835 $rss_items = powerpress_get_news(POWERPRESS_FEED_NEWS, $items);
5836 echo '<div class="powerpress-news-dashboard">';
5837 echo '<ul>';
5838
5839 if ( !$rss_items )
5840 {
5841 echo '<li>'. __('Error occurred retrieving news.' , 'powerpress') .'</li>';
5842 }
5843 else
5844 {
5845 $first_item = true;
5846 foreach( $rss_items as $null=> $item)
5847 {
5848 preg_match_all('/<img.*?src="(.*?)"/', $item->get_content(), $matches);
5849 if (!isset($matches[1][0])) {
5850 $img_url = powerpress_get_root_url() . 'images/pts_cover.jpg';
5851 } else {
5852 $img_url = $matches[1][0];
5853 }
5854 $enclosure = $item->get_enclosure();
5855 echo '<li class="pp-news-item">';
5856 echo "<img class='pp-news-image' src=\"$img_url\" alt=\"No image\" /><div class='pp-news-details-container'>";
5857 echo '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'" target="_blank">'. esc_html( $item->get_title() ) .'</a>';
5858 echo ' <div class="rss-date">'. $item->get_date('F j, Y') .'</div>';
5859 echo '<div class="rssSummary">'. esc_html( powerpress_feed_text_limit( strip_tags( $item->get_description() ), 150 ) );
5860 echo '<a href="' . esc_url($item->get_permalink(), $protocolls = null, 'display') . '" target="_blank">' . __('Read more', 'powerpress') . '</a>';
5861 echo '</div>';
5862 if( $enclosure && !empty($enclosure->link) )
5863 {
5864 $poster_image = '';
5865 $poster_tag = $item->get_item_tags('https://blubrry.com/developer/rawvoice-rss/', 'poster');
5866 if( $poster_tag && !empty($poster_tag[0]['attribs']['']['url']) )
5867 $poster_image = $item->sanitize($poster_tag[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
5868
5869 $embed = '';
5870 $embed_tag = $item->get_item_tags('https://blubrry.com/developer/rawvoice-rss/', 'embed');
5871 if( $embed_tag && !empty($embed_tag[0]['data']) )
5872 $embed = $embed_tag[0]['data'];
5873
5874
5875 // Only show an episode with the latest item
5876 if( $first_item && $embed )
5877 {
5878 if( preg_match('/width="(\d{1,4})"/i', $embed, $matches ) && count($matches) > 1 )
5879 {
5880 $max_width = $matches[1];
5881 $embed = preg_replace('/width="/i', 'style="max-width: '.$max_width.'px;" width="', $embed );
5882 }
5883 $embed = preg_replace('/width="(\d{1,4})"/i', 'width="100%"', $embed );
5884
5885 echo '<div class="powerpressNewsPlayer">';
5886 echo SanitizeEmbed($embed);
5887 echo '</div>';
5888 }
5889 else if( $first_item )
5890 {
5891 $EpisodeData = array();
5892 $EpisodeData['type'] = isset($enclosure->type) ? $enclosure->type : '';
5893 $EpisodeData['duration'] = isset($enclosure->duration) ? $enclosure->duration : '';
5894 $EpisodeData['poster'] = $poster_image;
5895 $EpisodeData['width'] = '100%';
5896 $EpisodeData['custom_play_button'] = powerpress_get_root_url() . 'play_audio.png';
5897 $ext = powerpressplayer_get_extension($enclosure->link);
5898 switch($ext)
5899 {
5900 case 'mp4':
5901 case 'm4v':
5902 case 'webm': {
5903 echo '<div class="powerpressNewsPlayer powerpressadmin-mejs-video">';
5904 echo powerpressplayer_build_mediaelementvideo($enclosure->link, $EpisodeData);
5905 echo '</div>';
5906 }; break;
5907 case 'mp3':
5908 case 'm4a': {
5909 echo '<div class="powerpressNewsPlayer">';
5910 echo powerpressplayer_build_mediaelementaudio($enclosure->link, $EpisodeData);
5911 echo '</div>';
5912 }; break;
5913 }
5914 }
5915
5916 echo '<div style="clear: both;"></div>';
5917 }
5918 echo '</div>';
5919 echo '</li>';
5920 //$first_item = false;
5921 }
5922 }
5923
5924 echo '</ul>';
5925 echo '<br class="clear"/>';
5926 echo '<div style="text-align:center;"><b>';
5927 echo __('MORE ARTICLES AT', 'powerpress');
5928 echo '&nbsp;';
5929 echo '<em><a href="https://blubrry.com/podcast-insider/">'. __('PODCAST INSIDER', 'powerpress') .'</a></em>';
5930
5931 echo '</b></div>';
5932 echo '</div>';
5933 }
5934
5935 function powerpressadmin_community_highlighted($items=8)
5936 {
5937 require_once( POWERPRESS_ABSPATH. '/powerpress-player.php'); // Include, if not included already
5938 $rss_items = powerpress_get_news(POWERPRESS_FEED_HIGHLIGHTED, $items);
5939 echo '<div class="powerpress-highlighted-dashboard">';
5940 echo '<ul>';
5941
5942 if ( !$rss_items )
5943 {
5944 echo '<li>'. __('Error occurred retrieving highlighted items.' , 'powerpress') .'</li>';
5945 }
5946 else
5947 {
5948 foreach( $rss_items as $null=> $item)
5949 {
5950 echo '<li>';
5951 echo '<a class="rsswidget" href="'.esc_url( $item->get_permalink(), $protocolls=null, 'display' ).'" target="_blank">'. esc_html( $item->get_title() ) .'</a>';
5952 //echo ' <span class="rss-date">'. $item->get_date('F j, Y') .'</span>';
5953 echo '<div class="rssSummary">'. esc_html( powerpress_feed_text_limit( strip_tags( $item->get_description() ), 150 ) ).'</div>';
5954 echo '</li>';
5955 }
5956 }
5957
5958 echo '</ul>';
5959 echo '</div>';
5960 }
5961
5962 function powerpress_admin_plugin_action_links( $links, $file )
5963 {
5964 if( preg_match('/powerpress\.php$/', $file) )
5965 array_push( $links, '<a href="'. admin_url("admin.php?page=powerpressadmin_basic") .'">'. __('Settings', 'powerpress') .'</a>');
5966 return $links;
5967 }
5968 add_filter( 'plugin_action_links', 'powerpress_admin_plugin_action_links', 10, 2 );
5969
5970 function powerpress_plugin_row_meta( $links, $file ) {
5971
5972 if ( strpos( $file, 'powerpress.php' ) !== false ) {
5973
5974 $new_links = array();
5975 $new_links[] = powerpress_get_documentation_link();
5976 //$new_links[] = '<a href="https://blubrry.com/support/powerpress-documentation/powerpress-documentation/" target="_blank">' . __( 'Support', 'powerpress' ) . '</a>';
5977 $new_links[] = powerpress_get_review_link();
5978
5979
5980 $links = array_merge( $links, $new_links );
5981 }
5982
5983 return $links;
5984 }
5985
5986 function powerpress_admin_get_page()
5987 {
5988 if( !empty($_REQUEST['page']) )
5989 return htmlspecialchars($_REQUEST['page']);
5990 return 'powerpressadmin_basic';
5991 }
5992
5993 function powerpress_review_message($type=0)
5994 {
5995 if( $type == 1 )
5996 return sprintf(__('If you appreciate PowerPress and the features provided, we would greatly appreciate it if you could <a href="%s" target="_blank">leave a review on WordPress.org</a>.', 'powerpress'), 'https://wordpress.org/support/plugin/powerpress/reviews/?rate=5#new-post');
5997
5998 return sprintf(__('Fan of PowerPress? Please show your appreciation by <a href="%s" target="_blank">leaving a review</a>.', 'powerpress'), 'https://wordpress.org/support/plugin/powerpress/reviews/?rate=5#new-post');
5999 }
6000
6001 function powerpress_get_review_link()
6002 {
6003 return '<a href="https://wordpress.org/support/view/plugin-reviews/powerpress?rate=5#postform" target="_blank">' . __( 'Write a review', 'powerpress' ) . '</a>';
6004 }
6005
6006 function powerpress_get_documentation_link()
6007 {
6008 return '<a href="https://blubrry.com/support/powerpress-documentation/powerpress-documentation/" target="_blank">' . __( 'Documentation', 'powerpress' ) . '</a>';
6009 }
6010
6011
6012
6013 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-jquery.php');
6014 // Only include the dashboard when appropriate.
6015 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-dashboard.php');
6016
6017 if( defined('WP_LOAD_IMPORTERS') ) {
6018 require_once( POWERPRESS_ABSPATH .'/powerpressadmin-rss-import.php');
6019 }
6020
6021
6022