Version Description
- Security: Prevent unprivileged users from inserting private posts by others.
- Security: Filter out possible XSS in post meta using wp_kses_post() when using display=all.
- New Setting: Only show Authors and Contributors their own content in the TinyMCE Insert Pages popup.
Download this release
Release Info
Developer | figureone |
Plugin | Insert Pages |
Version | 3.7.0 |
Comparing to | |
See all releases |
Code changes from version 3.6.1 to 3.7.0
- insert-pages.php +103 -35
- options.php +28 -0
- readme.txt +11 -2
insert-pages.php
CHANGED
@@ -7,7 +7,8 @@
|
|
7 |
* Text Domain: insert-pages
|
8 |
* Domain Path: /languages
|
9 |
* License: GPL2
|
10 |
-
*
|
|
|
11 |
*
|
12 |
* @package insert-pages
|
13 |
*/
|
@@ -422,6 +423,15 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
422 |
$inserted_page = get_post( intval( $attributes['page'] ) );
|
423 |
}
|
424 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
425 |
// If inserted page's status is private, don't show to anonymous users
|
426 |
// unless 'public' option is set.
|
427 |
if ( is_object( $inserted_page ) && 'private' === $inserted_page->post_status && ! $attributes['public'] ) {
|
@@ -648,38 +658,7 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
648 |
$content = apply_filters( 'the_content', $content );
|
649 |
}
|
650 |
echo $content;
|
651 |
-
|
652 |
-
* Meta.
|
653 |
-
*
|
654 |
-
* @see https://core.trac.wordpress.org/browser/tags/4.4/src/wp-includes/post-template.php#L968
|
655 |
-
*/
|
656 |
-
$keys = get_post_custom_keys( $inserted_page->ID );
|
657 |
-
if ( $keys ) {
|
658 |
-
echo "<ul class='post-meta'>\n";
|
659 |
-
foreach ( (array) $keys as $key ) {
|
660 |
-
$keyt = trim( $key );
|
661 |
-
if ( is_protected_meta( $keyt, 'post' ) ) {
|
662 |
-
continue;
|
663 |
-
}
|
664 |
-
$value = get_post_custom_values( $key, $inserted_page->ID );
|
665 |
-
if ( is_array( $value ) ) {
|
666 |
-
$values = array_map( 'trim', $value );
|
667 |
-
$value = implode( $values, ', ' );
|
668 |
-
}
|
669 |
-
|
670 |
-
/**
|
671 |
-
* Filter the HTML output of the li element in the post custom fields list.
|
672 |
-
*
|
673 |
-
* @since 2.2.0
|
674 |
-
*
|
675 |
-
* @param string $html The HTML output for the li element.
|
676 |
-
* @param string $key Meta key.
|
677 |
-
* @param string $value Meta value.
|
678 |
-
*/
|
679 |
-
echo apply_filters( 'the_meta_key', "<li><span class='post-meta-key'>$key:</span> $value</li>\n", $key, $value );
|
680 |
-
}
|
681 |
-
echo "</ul>\n";
|
682 |
-
}
|
683 |
break;
|
684 |
|
685 |
default: // Display is either invalid, or contains a template file to use.
|
@@ -755,12 +734,30 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
755 |
'post_status' => $attributes['public'] ? array( 'publish', 'private' ) : array( 'publish' ),
|
756 |
);
|
757 |
}
|
|
|
758 |
// We save the previous query state here instead of using
|
759 |
// wp_reset_query() because wp_reset_query() only has a single stack
|
760 |
// variable ($GLOBALS['wp_the_query']). This allows us to support
|
761 |
// pages inserted into other pages (multiple nested pages).
|
762 |
$old_query = $GLOBALS['wp_query'];
|
763 |
$posts = query_posts( $args );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
764 |
if ( have_posts() ) {
|
765 |
// Start output buffering so we can save the output to string.
|
766 |
ob_start();
|
@@ -947,7 +944,7 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
947 |
} else {
|
948 |
echo get_the_content();
|
949 |
}
|
950 |
-
the_meta();
|
951 |
// Render any <!--nextpage--> pagination links.
|
952 |
wp_link_pages( array(
|
953 |
'before' => '<div class="page-links">' . __( 'Pages:', 'twentynineteen' ),
|
@@ -1035,7 +1032,6 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
1035 |
}
|
1036 |
}
|
1037 |
|
1038 |
-
|
1039 |
return $content;
|
1040 |
}
|
1041 |
|
@@ -1426,6 +1422,16 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
1426 |
// 'post__not_in' => array( $args['pageID'] ), // Remove?
|
1427 |
);
|
1428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1429 |
$args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
|
1430 |
$query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
|
1431 |
|
@@ -1455,6 +1461,13 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
1455 |
// Build results.
|
1456 |
$results = array();
|
1457 |
foreach ( $posts as $post ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1458 |
if ( 'post' === $post->post_type ) {
|
1459 |
$info = mysql2date( 'Y/m/d', $post->post_date );
|
1460 |
} else {
|
@@ -1565,6 +1578,61 @@ if ( ! class_exists( 'InsertPagesPlugin' ) ) {
|
|
1565 |
register_widget( 'InsertPagesWidget' );
|
1566 |
}
|
1567 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1568 |
}
|
1569 |
}
|
1570 |
|
7 |
* Text Domain: insert-pages
|
8 |
* Domain Path: /languages
|
9 |
* License: GPL2
|
10 |
+
* Requires at least: 3.0.1
|
11 |
+
* Version: 3.7.0
|
12 |
*
|
13 |
* @package insert-pages
|
14 |
*/
|
423 |
$inserted_page = get_post( intval( $attributes['page'] ) );
|
424 |
}
|
425 |
|
426 |
+
// Prevent unprivileged users from inserting private posts from others.
|
427 |
+
if ( is_object( $inserted_page ) && 'publish' !== $inserted_page->post_status ) {
|
428 |
+
$post_type = get_post_type_object( $inserted_page->post_type );
|
429 |
+
$parent_post_author_id = intval( get_the_author_meta( 'ID' ) );
|
430 |
+
if ( ! user_can( $parent_post_author_id, $post_type->cap->read_post, $inserted_page->ID ) ) {
|
431 |
+
$inserted_page = null;
|
432 |
+
}
|
433 |
+
}
|
434 |
+
|
435 |
// If inserted page's status is private, don't show to anonymous users
|
436 |
// unless 'public' option is set.
|
437 |
if ( is_object( $inserted_page ) && 'private' === $inserted_page->post_status && ! $attributes['public'] ) {
|
658 |
$content = apply_filters( 'the_content', $content );
|
659 |
}
|
660 |
echo $content;
|
661 |
+
$this->the_meta( $inserted_page->ID );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
662 |
break;
|
663 |
|
664 |
default: // Display is either invalid, or contains a template file to use.
|
734 |
'post_status' => $attributes['public'] ? array( 'publish', 'private' ) : array( 'publish' ),
|
735 |
);
|
736 |
}
|
737 |
+
|
738 |
// We save the previous query state here instead of using
|
739 |
// wp_reset_query() because wp_reset_query() only has a single stack
|
740 |
// variable ($GLOBALS['wp_the_query']). This allows us to support
|
741 |
// pages inserted into other pages (multiple nested pages).
|
742 |
$old_query = $GLOBALS['wp_query'];
|
743 |
$posts = query_posts( $args );
|
744 |
+
|
745 |
+
// Prevent unprivileged users from inserting private posts from others.
|
746 |
+
if ( have_posts() ) {
|
747 |
+
$can_read = true;
|
748 |
+
$parent_post_author_id = intval( get_the_author_meta( 'ID' ) );
|
749 |
+
foreach ( $posts as $post ) {
|
750 |
+
$post_type = get_post_type_object( $post->post_type );
|
751 |
+
if ( ! user_can( $parent_post_author_id, $post_type->cap->read_post, $post->ID ) ) {
|
752 |
+
$can_read = false;
|
753 |
+
}
|
754 |
+
}
|
755 |
+
if ( ! $can_read ) {
|
756 |
+
// Force an empty query so we don't show any posts.
|
757 |
+
$posts = query_posts( array( 'post__in' => array( 0 ) ) );
|
758 |
+
}
|
759 |
+
}
|
760 |
+
|
761 |
if ( have_posts() ) {
|
762 |
// Start output buffering so we can save the output to string.
|
763 |
ob_start();
|
944 |
} else {
|
945 |
echo get_the_content();
|
946 |
}
|
947 |
+
$this->the_meta();
|
948 |
// Render any <!--nextpage--> pagination links.
|
949 |
wp_link_pages( array(
|
950 |
'before' => '<div class="page-links">' . __( 'Pages:', 'twentynineteen' ),
|
1032 |
}
|
1033 |
}
|
1034 |
|
|
|
1035 |
return $content;
|
1036 |
}
|
1037 |
|
1422 |
// 'post__not_in' => array( $args['pageID'] ), // Remove?
|
1423 |
);
|
1424 |
|
1425 |
+
// Show non-admins only their own posts if the option is enabled.
|
1426 |
+
$options = get_option( 'wpip_settings' );
|
1427 |
+
if (
|
1428 |
+
! empty( $options['wpip_classic_editor_hide_others_posts'] ) &&
|
1429 |
+
'enabled' === $options['wpip_classic_editor_hide_others_posts'] &&
|
1430 |
+
! current_user_can( 'edit_others_posts' )
|
1431 |
+
) {
|
1432 |
+
$query['author'] = get_current_user_id();
|
1433 |
+
}
|
1434 |
+
|
1435 |
$args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
|
1436 |
$query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
|
1437 |
|
1461 |
// Build results.
|
1462 |
$results = array();
|
1463 |
foreach ( $posts as $post ) {
|
1464 |
+
// Prevent unprivileged users (e.g., Contributors) from seeing and
|
1465 |
+
// inserting other user's private posts.
|
1466 |
+
$post_type = get_post_type_object( $post->post_type );
|
1467 |
+
if ( 'publish' !== $post->post_status && ! current_user_can( $post_type->cap->read_post, $post->ID ) ) {
|
1468 |
+
continue;
|
1469 |
+
}
|
1470 |
+
|
1471 |
if ( 'post' === $post->post_type ) {
|
1472 |
$info = mysql2date( 'Y/m/d', $post->post_date );
|
1473 |
} else {
|
1578 |
register_widget( 'InsertPagesWidget' );
|
1579 |
}
|
1580 |
|
1581 |
+
/**
|
1582 |
+
* Render post meta as an unordered list.
|
1583 |
+
*
|
1584 |
+
* Note: This function sanitizes postmeta value via wp_kses_post(); the
|
1585 |
+
* core WordPress function the_meta() does not.
|
1586 |
+
*
|
1587 |
+
* @see https://developer.wordpress.org/reference/functions/the_meta/
|
1588 |
+
*
|
1589 |
+
* @param int $post_id Post ID.
|
1590 |
+
*/
|
1591 |
+
public function the_meta( $post_id = 0 ) {
|
1592 |
+
if ( empty( $post_id ) ) {
|
1593 |
+
$post_id = get_the_ID();
|
1594 |
+
}
|
1595 |
+
|
1596 |
+
$keys = get_post_custom_keys( $post_id );
|
1597 |
+
if ( $keys ) {
|
1598 |
+
$li_html = '';
|
1599 |
+
foreach ( (array) $keys as $key ) {
|
1600 |
+
$keyt = trim( $key );
|
1601 |
+
if ( is_protected_meta( $keyt, 'post' ) ) {
|
1602 |
+
continue;
|
1603 |
+
}
|
1604 |
+
|
1605 |
+
$values = array_map( 'trim', get_post_custom_values( $key, $post_id ) );
|
1606 |
+
$value = implode( ', ', $values );
|
1607 |
+
|
1608 |
+
// Sanitize post meta values.
|
1609 |
+
$value = wp_kses_post( $value );
|
1610 |
+
|
1611 |
+
$html = sprintf(
|
1612 |
+
"<li><span class='post-meta-key'>%s</span> %s</li>\n",
|
1613 |
+
/* translators: %s: Post custom field name. */
|
1614 |
+
sprintf( _x( '%s:', 'Post custom field name' ), $key ),
|
1615 |
+
$value
|
1616 |
+
);
|
1617 |
+
|
1618 |
+
/**
|
1619 |
+
* Filters the HTML output of the li element in the post custom fields list.
|
1620 |
+
*
|
1621 |
+
* @since 2.2.0
|
1622 |
+
*
|
1623 |
+
* @param string $html The HTML output for the li element.
|
1624 |
+
* @param string $key Meta key.
|
1625 |
+
* @param string $value Meta value.
|
1626 |
+
*/
|
1627 |
+
$li_html .= apply_filters( 'the_meta_key', $html, $key, $value );
|
1628 |
+
}
|
1629 |
+
|
1630 |
+
if ( $li_html ) {
|
1631 |
+
echo "<ul class='post-meta'>\n{$li_html}</ul>\n";
|
1632 |
+
}
|
1633 |
+
}
|
1634 |
+
}
|
1635 |
+
|
1636 |
}
|
1637 |
}
|
1638 |
|
options.php
CHANGED
@@ -63,6 +63,13 @@ function wpip_settings_init() {
|
|
63 |
'wpipSettings',
|
64 |
'wpip_section'
|
65 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
}
|
67 |
add_action( 'admin_init', 'wpip_settings_init' );
|
68 |
|
@@ -104,6 +111,10 @@ function wpip_set_defaults() {
|
|
104 |
$options['wpip_gutenberg_block'] = 'enabled';
|
105 |
}
|
106 |
|
|
|
|
|
|
|
|
|
107 |
update_option( 'wpip_settings', $options );
|
108 |
|
109 |
return $options;
|
@@ -219,3 +230,20 @@ function wpip_gutenberg_block_render() {
|
|
219 |
<input type='radio' name='wpip_settings[wpip_gutenberg_block]' <?php checked( $options['wpip_gutenberg_block'], 'disabled' ); ?> id="wpip_gutenberg_block_disabled" value='disabled'><label for="wpip_gutenberg_block_disabled">Disable Insert Pages Gutenberg block.</label>
|
220 |
<?php
|
221 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
'wpipSettings',
|
64 |
'wpip_section'
|
65 |
);
|
66 |
+
add_settings_field(
|
67 |
+
'wpip_classic_editor_hide_others_posts',
|
68 |
+
__( 'TinyMCE capabilities', 'insert-pages' ),
|
69 |
+
'wpip_classic_editor_hide_others_posts_render',
|
70 |
+
'wpipSettings',
|
71 |
+
'wpip_section'
|
72 |
+
);
|
73 |
}
|
74 |
add_action( 'admin_init', 'wpip_settings_init' );
|
75 |
|
111 |
$options['wpip_gutenberg_block'] = 'enabled';
|
112 |
}
|
113 |
|
114 |
+
if ( empty( $options['wpip_classic_editor_hide_others_posts'] ) ) {
|
115 |
+
$options['wpip_classic_editor_hide_others_posts'] = 'disabled';
|
116 |
+
}
|
117 |
+
|
118 |
update_option( 'wpip_settings', $options );
|
119 |
|
120 |
return $options;
|
230 |
<input type='radio' name='wpip_settings[wpip_gutenberg_block]' <?php checked( $options['wpip_gutenberg_block'], 'disabled' ); ?> id="wpip_gutenberg_block_disabled" value='disabled'><label for="wpip_gutenberg_block_disabled">Disable Insert Pages Gutenberg block.</label>
|
231 |
<?php
|
232 |
}
|
233 |
+
|
234 |
+
/**
|
235 |
+
* Print 'TinyMCE capabilities' setting.
|
236 |
+
*
|
237 |
+
* @return void
|
238 |
+
*/
|
239 |
+
function wpip_classic_editor_hide_others_posts_render() {
|
240 |
+
$options = get_option( 'wpip_settings' );
|
241 |
+
if ( false === $options || ! is_array( $options ) || empty( $options['wpip_classic_editor_hide_others_posts'] ) ) {
|
242 |
+
$options = wpip_set_defaults();
|
243 |
+
}
|
244 |
+
?>
|
245 |
+
<input type='radio' name='wpip_settings[wpip_classic_editor_hide_others_posts]' <?php checked( $options['wpip_classic_editor_hide_others_posts'], 'enabled' ); ?> id="wpip_classic_editor_hide_others_posts_enabled" value='enabled'><label for="wpip_classic_editor_hide_others_posts_enabled">Authors and Contributors only see their own content to insert.</label><br />
|
246 |
+
<input type='radio' name='wpip_settings[wpip_classic_editor_hide_others_posts]' <?php checked( $options['wpip_classic_editor_hide_others_posts'], 'disabled' ); ?> id="wpip_classic_editor_hide_others_posts_disabled" value='disabled'><label for="wpip_classic_editor_hide_others_posts_disabled">Authors and Contributors see all published content to insert.</label><br />
|
247 |
+
<small><em>Note: this option only restricts Contributors and Authors (i.e., the roles without the <code>edit_others_posts</code> capability) from seeing other's content in the TinyMCE Insert Page popup; they can still insert any published content if they know the page slug.</em></small>
|
248 |
+
<?php
|
249 |
+
}
|
readme.txt
CHANGED
@@ -1,8 +1,7 @@
|
|
1 |
=== Insert Pages ===
|
2 |
Contributors: figureone, the_magician
|
3 |
Tags: insert, pages, shortcode, embed
|
4 |
-
|
5 |
-
Tested up to: 5.7
|
6 |
Stable tag: trunk
|
7 |
License: GPLv2 or later
|
8 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
@@ -111,6 +110,11 @@ Just one! The plugin prevents you from embedding a page in itself, but you can t
|
|
111 |
|
112 |
== Changelog ==
|
113 |
|
|
|
|
|
|
|
|
|
|
|
114 |
= 3.6.1 =
|
115 |
* Fix TinyMCE dialog not closing properly. Props @astaryne for the report!
|
116 |
|
@@ -460,3 +464,8 @@ Added retina toolbar icon.
|
|
460 |
|
461 |
= 1.0 =
|
462 |
Upgrade to v1.0 to get the first stable version.
|
|
|
|
|
|
|
|
|
|
1 |
=== Insert Pages ===
|
2 |
Contributors: figureone, the_magician
|
3 |
Tags: insert, pages, shortcode, embed
|
4 |
+
Tested up to: 5.8.1
|
|
|
5 |
Stable tag: trunk
|
6 |
License: GPLv2 or later
|
7 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
110 |
|
111 |
== Changelog ==
|
112 |
|
113 |
+
= 3.7.0 =
|
114 |
+
* Security: Prevent unprivileged users from inserting private posts by others.
|
115 |
+
* Security: Filter out possible XSS in post meta using wp_kses_post() when using display=all.
|
116 |
+
* New Setting: Only show Authors and Contributors their own content in the TinyMCE Insert Pages popup.
|
117 |
+
|
118 |
= 3.6.1 =
|
119 |
* Fix TinyMCE dialog not closing properly. Props @astaryne for the report!
|
120 |
|
464 |
|
465 |
= 1.0 =
|
466 |
Upgrade to v1.0 to get the first stable version.
|
467 |
+
|
468 |
+
== Upgrade Notice ==
|
469 |
+
|
470 |
+
= 3.7.0 =
|
471 |
+
Note: if you insert private pages/posts, please review the post authors of the pages containing the inserted page and confirm they have the capability to read the private content. This upgrade enforces private page visibility based on the role of the author of the page that inserts any private content.
|