Version Description
- Fix: Harden security of job dashboard actions. Reported by Slavco.
- Updated template:
job-dashboard.php
.
Download this release
Release Info
Developer | jakeom |
Plugin | WP Job Manager |
Version | 1.34.4 |
Comparing to | |
See all releases |
Code changes from version 1.34.3 to 1.34.4
- changelog.txt +4 -0
- includes/class-wp-job-manager-shortcodes.php +193 -32
- languages/wp-job-manager.pot +42 -41
- readme.txt +6 -2
- templates/job-dashboard.php +17 -40
- wp-job-manager-functions.php +12 -5
- wp-job-manager.php +3 -3
changelog.txt
CHANGED
@@ -1,3 +1,7 @@
|
|
|
|
|
|
|
|
|
|
1 |
= 1.34.3 =
|
2 |
* Fix: Hide filled listings in WordPress 5.5 sitemaps.
|
3 |
* Fix: Issue with editing a job after getting to a preview step for another job.
|
1 |
+
= 1.34.4 =
|
2 |
+
* Fix: Harden security of job dashboard actions. Reported by Slavco.
|
3 |
+
* Updated template: `job-dashboard.php`.
|
4 |
+
|
5 |
= 1.34.3 =
|
6 |
* Fix: Hide filled listings in WordPress 5.5 sitemaps.
|
7 |
* Fix: Issue with editing a job after getting to a preview step for another job.
|
includes/class-wp-job-manager-shortcodes.php
CHANGED
@@ -24,6 +24,13 @@ class WP_Job_Manager_Shortcodes {
|
|
24 |
*/
|
25 |
private $job_dashboard_message = '';
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
/**
|
28 |
* The single instance of the class.
|
29 |
*
|
@@ -66,13 +73,13 @@ class WP_Job_Manager_Shortcodes {
|
|
66 |
}
|
67 |
|
68 |
/**
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
private function is_job_dashboard_page() {
|
77 |
global $post;
|
78 |
|
@@ -110,19 +117,27 @@ class WP_Job_Manager_Shortcodes {
|
|
110 |
public function job_dashboard_handler() {
|
111 |
if (
|
112 |
! empty( $_REQUEST['action'] )
|
|
|
113 |
&& ! empty( $_REQUEST['_wpnonce'] )
|
114 |
-
&& wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'job_manager_my_job_actions' ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce should not be modified.
|
115 |
) {
|
116 |
|
117 |
-
$action = sanitize_title( wp_unslash( $_REQUEST['action'] ) );
|
118 |
$job_id = isset( $_REQUEST['job_id'] ) ? absint( $_REQUEST['job_id'] ) : 0;
|
|
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
|
124 |
-
|
125 |
-
if ( ! job_manager_user_can_edit_job( $job_id ) ) {
|
126 |
throw new Exception( __( 'Invalid ID', 'wp-job-manager' ) );
|
127 |
}
|
128 |
|
@@ -212,6 +227,60 @@ class WP_Job_Manager_Shortcodes {
|
|
212 |
}
|
213 |
}
|
214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
/**
|
216 |
* Handles shortcode which lists the logged in user's jobs.
|
217 |
*
|
@@ -250,21 +319,10 @@ class WP_Job_Manager_Shortcodes {
|
|
250 |
}
|
251 |
|
252 |
// ....If not show the job dashboard.
|
253 |
-
$
|
254 |
-
'job_manager_get_dashboard_jobs_args',
|
255 |
-
[
|
256 |
-
'post_type' => 'job_listing',
|
257 |
-
'post_status' => [ 'publish', 'expired', 'pending', 'draft', 'preview' ],
|
258 |
-
'ignore_sticky_posts' => 1,
|
259 |
-
'posts_per_page' => $posts_per_page,
|
260 |
-
'offset' => ( max( 1, get_query_var( 'paged' ) ) - 1 ) * $posts_per_page,
|
261 |
-
'orderby' => 'date',
|
262 |
-
'order' => 'desc',
|
263 |
-
'author' => get_current_user_id(),
|
264 |
-
]
|
265 |
-
);
|
266 |
|
267 |
-
|
|
|
268 |
|
269 |
echo wp_kses_post( $this->job_dashboard_message );
|
270 |
|
@@ -278,10 +336,16 @@ class WP_Job_Manager_Shortcodes {
|
|
278 |
]
|
279 |
);
|
280 |
|
|
|
|
|
|
|
|
|
|
|
281 |
get_job_manager_template(
|
282 |
'job-dashboard.php',
|
283 |
[
|
284 |
-
'jobs' => $jobs->
|
|
|
285 |
'max_num_pages' => $jobs->max_num_pages,
|
286 |
'job_dashboard_columns' => $job_dashboard_columns,
|
287 |
]
|
@@ -290,6 +354,102 @@ class WP_Job_Manager_Shortcodes {
|
|
290 |
return ob_get_clean();
|
291 |
}
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
/**
|
294 |
* Filters the url from paginate_links to avoid multiple calls for same action in job dashboard
|
295 |
*
|
@@ -298,7 +458,8 @@ class WP_Job_Manager_Shortcodes {
|
|
298 |
*/
|
299 |
public function filter_paginate_links( $link ) {
|
300 |
|
301 |
-
|
|
|
302 |
return remove_query_arg( [ 'action', 'job_id', '_wpnonce' ], $link );
|
303 |
}
|
304 |
|
@@ -385,8 +546,8 @@ class WP_Job_Manager_Shortcodes {
|
|
385 |
$disable_client_state = true;
|
386 |
}
|
387 |
if ( ! empty( $_GET['search_location'] ) ) {
|
388 |
-
$atts['location']
|
389 |
-
$disable_client_state
|
390 |
}
|
391 |
if ( ! empty( $_GET['search_category'] ) ) {
|
392 |
$atts['selected_category'] = sanitize_text_field( wp_unslash( $_GET['search_category'] ) );
|
24 |
*/
|
25 |
private $job_dashboard_message = '';
|
26 |
|
27 |
+
/**
|
28 |
+
* Cache of job post IDs currently displayed on job dashboard.
|
29 |
+
*
|
30 |
+
* @var int[]
|
31 |
+
*/
|
32 |
+
private $job_dashboard_job_ids;
|
33 |
+
|
34 |
/**
|
35 |
* The single instance of the class.
|
36 |
*
|
73 |
}
|
74 |
|
75 |
/**
|
76 |
+
* Helper function used to check if page is WPJM dashboard page.
|
77 |
+
*
|
78 |
+
* Checks if page has 'job_dashboard' shortcode.
|
79 |
+
*
|
80 |
+
* @access private
|
81 |
+
* @return bool True if page is dashboard page, false otherwise.
|
82 |
+
*/
|
83 |
private function is_job_dashboard_page() {
|
84 |
global $post;
|
85 |
|
117 |
public function job_dashboard_handler() {
|
118 |
if (
|
119 |
! empty( $_REQUEST['action'] )
|
120 |
+
&& ! empty( $_REQUEST['job_id'] )
|
121 |
&& ! empty( $_REQUEST['_wpnonce'] )
|
|
|
122 |
) {
|
123 |
|
|
|
124 |
$job_id = isset( $_REQUEST['job_id'] ) ? absint( $_REQUEST['job_id'] ) : 0;
|
125 |
+
$action = sanitize_title( wp_unslash( $_REQUEST['action'] ) );
|
126 |
|
127 |
+
$job = get_post( $job_id );
|
128 |
+
$job_actions = $this->get_job_actions( $job );
|
129 |
+
|
130 |
+
if (
|
131 |
+
! isset( $job_actions[ $action ] )
|
132 |
+
|| empty( $job_actions[ $action ]['nonce'] )
|
133 |
+
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce should not be modified.
|
134 |
+
|| ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), $job_actions[ $action ]['nonce'] )
|
135 |
+
) {
|
136 |
+
return;
|
137 |
+
}
|
138 |
|
139 |
+
try {
|
140 |
+
if ( empty( $job ) || 'job_listing' !== $job->post_type || ! job_manager_user_can_edit_job( $job_id ) ) {
|
141 |
throw new Exception( __( 'Invalid ID', 'wp-job-manager' ) );
|
142 |
}
|
143 |
|
227 |
}
|
228 |
}
|
229 |
|
230 |
+
/**
|
231 |
+
* Check if a job is listed on the current user's job dashboard page.
|
232 |
+
*
|
233 |
+
* @param WP_Post $job Job post object.
|
234 |
+
*
|
235 |
+
* @return bool
|
236 |
+
*/
|
237 |
+
private function is_job_available_on_dashboard( WP_Post $job ) {
|
238 |
+
// Check cache of currently displayed job dashboard IDs first to avoid lots of queries.
|
239 |
+
if ( isset( $this->job_dashboard_job_ids ) && in_array( (int) $job->ID, $this->job_dashboard_job_ids, true ) ) {
|
240 |
+
return true;
|
241 |
+
}
|
242 |
+
|
243 |
+
$args = $this->get_job_dashboard_query_args();
|
244 |
+
$args['p'] = $job->ID;
|
245 |
+
$args['fields'] = 'ids';
|
246 |
+
|
247 |
+
$query = new WP_Query( $args );
|
248 |
+
|
249 |
+
return (int) $query->post_count > 0;
|
250 |
+
}
|
251 |
+
|
252 |
+
/**
|
253 |
+
* Helper that generates the job dashboard query args.
|
254 |
+
*
|
255 |
+
* @param int $posts_per_page Number of posts per page.
|
256 |
+
*
|
257 |
+
* @return array
|
258 |
+
*/
|
259 |
+
private function get_job_dashboard_query_args( $posts_per_page = -1 ) {
|
260 |
+
$job_dashboard_args = [
|
261 |
+
'post_type' => 'job_listing',
|
262 |
+
'post_status' => [ 'publish', 'expired', 'pending', 'draft', 'preview' ],
|
263 |
+
'ignore_sticky_posts' => 1,
|
264 |
+
'posts_per_page' => $posts_per_page,
|
265 |
+
'orderby' => 'date',
|
266 |
+
'order' => 'desc',
|
267 |
+
'author' => get_current_user_id(),
|
268 |
+
];
|
269 |
+
|
270 |
+
if ( $posts_per_page > 0 ) {
|
271 |
+
$job_dashboard_args['offset'] = ( max( 1, get_query_var( 'paged' ) ) - 1 ) * $posts_per_page;
|
272 |
+
}
|
273 |
+
|
274 |
+
/**
|
275 |
+
* Customize the query that is used to get jobs on the job dashboard.
|
276 |
+
*
|
277 |
+
* @since 1.0.0
|
278 |
+
*
|
279 |
+
* @param array $job_dashboard_args Arguments to pass to WP_Query.
|
280 |
+
*/
|
281 |
+
return apply_filters( 'job_manager_get_dashboard_jobs_args', $job_dashboard_args );
|
282 |
+
}
|
283 |
+
|
284 |
/**
|
285 |
* Handles shortcode which lists the logged in user's jobs.
|
286 |
*
|
319 |
}
|
320 |
|
321 |
// ....If not show the job dashboard.
|
322 |
+
$jobs = new WP_Query( $this->get_job_dashboard_query_args( $posts_per_page ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
|
324 |
+
// Cache IDs for access check later on.
|
325 |
+
$this->job_dashboard_job_ids = wp_list_pluck( $jobs->posts, 'ID' );
|
326 |
|
327 |
echo wp_kses_post( $this->job_dashboard_message );
|
328 |
|
336 |
]
|
337 |
);
|
338 |
|
339 |
+
$job_actions = [];
|
340 |
+
foreach ( $jobs->posts as $job ) {
|
341 |
+
$job_actions[ $job->ID ] = $this->get_job_actions( $job );
|
342 |
+
}
|
343 |
+
|
344 |
get_job_manager_template(
|
345 |
'job-dashboard.php',
|
346 |
[
|
347 |
+
'jobs' => $jobs->posts,
|
348 |
+
'job_actions' => $job_actions,
|
349 |
'max_num_pages' => $jobs->max_num_pages,
|
350 |
'job_dashboard_columns' => $job_dashboard_columns,
|
351 |
]
|
354 |
return ob_get_clean();
|
355 |
}
|
356 |
|
357 |
+
/**
|
358 |
+
* Get the actions available to the user for a job listing on the job dashboard page.
|
359 |
+
*
|
360 |
+
* @param WP_Post $job The job post object.
|
361 |
+
*
|
362 |
+
* @return array
|
363 |
+
*/
|
364 |
+
public function get_job_actions( $job ) {
|
365 |
+
if (
|
366 |
+
! get_current_user_id()
|
367 |
+
|| ! $job instanceof WP_Post
|
368 |
+
|| 'job_listing' !== $job->post_type
|
369 |
+
|| ! $this->is_job_available_on_dashboard( $job )
|
370 |
+
) {
|
371 |
+
return [];
|
372 |
+
}
|
373 |
+
|
374 |
+
$base_nonce_action_name = 'job_manager_my_job_actions';
|
375 |
+
|
376 |
+
$actions = [];
|
377 |
+
switch ( $job->post_status ) {
|
378 |
+
case 'publish':
|
379 |
+
if ( WP_Job_Manager_Post_Types::job_is_editable( $job->ID ) ) {
|
380 |
+
$actions['edit'] = [
|
381 |
+
'label' => __( 'Edit', 'wp-job-manager' ),
|
382 |
+
'nonce' => false,
|
383 |
+
];
|
384 |
+
}
|
385 |
+
if ( is_position_filled( $job ) ) {
|
386 |
+
$actions['mark_not_filled'] = [
|
387 |
+
'label' => __( 'Mark not filled', 'wp-job-manager' ),
|
388 |
+
'nonce' => $base_nonce_action_name,
|
389 |
+
];
|
390 |
+
} else {
|
391 |
+
$actions['mark_filled'] = [
|
392 |
+
'label' => __( 'Mark filled', 'wp-job-manager' ),
|
393 |
+
'nonce' => $base_nonce_action_name,
|
394 |
+
];
|
395 |
+
}
|
396 |
+
|
397 |
+
$actions['duplicate'] = [
|
398 |
+
'label' => __( 'Duplicate', 'wp-job-manager' ),
|
399 |
+
'nonce' => $base_nonce_action_name,
|
400 |
+
];
|
401 |
+
break;
|
402 |
+
case 'expired':
|
403 |
+
if ( job_manager_get_permalink( 'submit_job_form' ) ) {
|
404 |
+
$actions['relist'] = [
|
405 |
+
'label' => __( 'Relist', 'wp-job-manager' ),
|
406 |
+
'nonce' => $base_nonce_action_name,
|
407 |
+
];
|
408 |
+
}
|
409 |
+
break;
|
410 |
+
case 'pending_payment':
|
411 |
+
case 'pending':
|
412 |
+
if ( WP_Job_Manager_Post_Types::job_is_editable( $job->ID ) ) {
|
413 |
+
$actions['edit'] = [
|
414 |
+
'label' => __( 'Edit', 'wp-job-manager' ),
|
415 |
+
'nonce' => false,
|
416 |
+
];
|
417 |
+
}
|
418 |
+
break;
|
419 |
+
case 'draft':
|
420 |
+
case 'preview':
|
421 |
+
$actions['continue'] = [
|
422 |
+
'label' => __( 'Continue Submission', 'wp-job-manager' ),
|
423 |
+
'nonce' => $base_nonce_action_name,
|
424 |
+
];
|
425 |
+
break;
|
426 |
+
}
|
427 |
+
|
428 |
+
$actions['delete'] = [
|
429 |
+
'label' => __( 'Delete', 'wp-job-manager' ),
|
430 |
+
'nonce' => $base_nonce_action_name,
|
431 |
+
];
|
432 |
+
|
433 |
+
/**
|
434 |
+
* Filter the actions available to the current user for a job on the job dashboard page.
|
435 |
+
*
|
436 |
+
* @since 1.0.0
|
437 |
+
*
|
438 |
+
* @param array $actions Actions to filter.
|
439 |
+
* @param WP_Post $job Job post object.
|
440 |
+
*/
|
441 |
+
$actions = apply_filters( 'job_manager_my_job_actions', $actions, $job );
|
442 |
+
|
443 |
+
// For backwards compatibility, convert `nonce => true` to the nonce action name.
|
444 |
+
foreach ( $actions as $key => $action ) {
|
445 |
+
if ( true === $action['nonce'] ) {
|
446 |
+
$actions[ $key ]['nonce'] = $base_nonce_action_name;
|
447 |
+
}
|
448 |
+
}
|
449 |
+
|
450 |
+
return $actions;
|
451 |
+
}
|
452 |
+
|
453 |
/**
|
454 |
* Filters the url from paginate_links to avoid multiple calls for same action in job dashboard
|
455 |
*
|
458 |
*/
|
459 |
public function filter_paginate_links( $link ) {
|
460 |
|
461 |
+
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Input is used for comparison only.
|
462 |
+
if ( $this->is_job_dashboard_page() && isset( $_GET['action'] ) && in_array( $_GET['action'], [ 'mark_filled', 'mark_not_filled' ], true ) ) {
|
463 |
return remove_query_arg( [ 'action', 'job_id', '_wpnonce' ], $link );
|
464 |
}
|
465 |
|
546 |
$disable_client_state = true;
|
547 |
}
|
548 |
if ( ! empty( $_GET['search_location'] ) ) {
|
549 |
+
$atts['location'] = sanitize_text_field( wp_unslash( $_GET['search_location'] ) );
|
550 |
+
$disable_client_state = true;
|
551 |
}
|
552 |
if ( ! empty( $_GET['search_category'] ) ) {
|
553 |
$atts['selected_category'] = sanitize_text_field( wp_unslash( $_GET['search_category'] ) );
|
languages/wp-job-manager.pot
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
# This file is distributed under the GPL2+.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: WP Job Manager 1.34.
|
6 |
"Report-Msgid-Bugs-To: https://github.com/Automattic/WP-Job-Manager/issues\n"
|
7 |
-
"POT-Creation-Date: 2020-
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -230,7 +230,7 @@ msgid "Featured?"
|
|
230 |
msgstr ""
|
231 |
|
232 |
#: includes/admin/class-wp-job-manager-cpt.php:503
|
233 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
234 |
msgid "Filled?"
|
235 |
msgstr ""
|
236 |
|
@@ -268,12 +268,13 @@ msgstr ""
|
|
268 |
|
269 |
#: includes/admin/class-wp-job-manager-cpt.php:647
|
270 |
#: includes/class-wp-job-manager-post-types.php:335
|
271 |
-
#:
|
|
|
272 |
msgid "Edit"
|
273 |
msgstr ""
|
274 |
|
275 |
#: includes/admin/class-wp-job-manager-cpt.php:654
|
276 |
-
#:
|
277 |
msgid "Delete"
|
278 |
msgstr ""
|
279 |
|
@@ -1385,55 +1386,75 @@ msgstr ""
|
|
1385 |
msgid "Listing Expiry Date"
|
1386 |
msgstr ""
|
1387 |
|
1388 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1389 |
msgid "Invalid ID"
|
1390 |
msgstr ""
|
1391 |
|
1392 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1393 |
msgid "This position has already been filled"
|
1394 |
msgstr ""
|
1395 |
|
1396 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1397 |
#. translators: Placeholder %s is the job listing title.
|
1398 |
msgid "%s has been filled"
|
1399 |
msgstr ""
|
1400 |
|
1401 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1402 |
msgid "This position is not filled"
|
1403 |
msgstr ""
|
1404 |
|
1405 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1406 |
#. translators: Placeholder %s is the job listing title.
|
1407 |
msgid "%s has been marked as not filled"
|
1408 |
msgstr ""
|
1409 |
|
1410 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1411 |
#. translators: Placeholder %s is the job listing title.
|
1412 |
msgid "%s has been deleted"
|
1413 |
msgstr ""
|
1414 |
|
1415 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1416 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1417 |
msgid "Missing submission page."
|
1418 |
msgstr ""
|
1419 |
|
1420 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1421 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:36
|
1422 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:52
|
1423 |
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:36
|
1424 |
msgid "Title"
|
1425 |
msgstr ""
|
1426 |
|
1427 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1428 |
msgid "Date Posted"
|
1429 |
msgstr ""
|
1430 |
|
1431 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1432 |
msgid "Listing Expires"
|
1433 |
msgstr ""
|
1434 |
|
1435 |
-
#: includes/class-wp-job-manager-shortcodes.php:
|
1436 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1437 |
msgid "Load more listings"
|
1438 |
msgstr ""
|
1439 |
|
@@ -2118,38 +2139,18 @@ msgstr ""
|
|
2118 |
msgid "You need to be signed in to manage your listings."
|
2119 |
msgstr ""
|
2120 |
|
2121 |
-
#: templates/job-dashboard.php:
|
2122 |
msgid "Your listings are shown in the table below."
|
2123 |
msgstr ""
|
2124 |
|
2125 |
-
#: templates/job-dashboard.php:
|
2126 |
msgid "You do not have any active listings."
|
2127 |
msgstr ""
|
2128 |
|
2129 |
-
#: templates/job-dashboard.php:
|
2130 |
msgid "Featured Job"
|
2131 |
msgstr ""
|
2132 |
|
2133 |
-
#: templates/job-dashboard.php:55
|
2134 |
-
msgid "Mark not filled"
|
2135 |
-
msgstr ""
|
2136 |
-
|
2137 |
-
#: templates/job-dashboard.php:57
|
2138 |
-
msgid "Mark filled"
|
2139 |
-
msgstr ""
|
2140 |
-
|
2141 |
-
#: templates/job-dashboard.php:60
|
2142 |
-
msgid "Duplicate"
|
2143 |
-
msgstr ""
|
2144 |
-
|
2145 |
-
#: templates/job-dashboard.php:64
|
2146 |
-
msgid "Relist"
|
2147 |
-
msgstr ""
|
2148 |
-
|
2149 |
-
#: templates/job-dashboard.php:75
|
2150 |
-
msgid "Continue Submission"
|
2151 |
-
msgstr ""
|
2152 |
-
|
2153 |
#: templates/job-filters.php:30 templates/job-filters.php:31
|
2154 |
msgid "Keywords"
|
2155 |
msgstr ""
|
2 |
# This file is distributed under the GPL2+.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: WP Job Manager 1.34.4\n"
|
6 |
"Report-Msgid-Bugs-To: https://github.com/Automattic/WP-Job-Manager/issues\n"
|
7 |
+
"POT-Creation-Date: 2020-11-23 22:28:27+00:00\n"
|
8 |
"MIME-Version: 1.0\n"
|
9 |
"Content-Type: text/plain; charset=utf-8\n"
|
10 |
"Content-Transfer-Encoding: 8bit\n"
|
230 |
msgstr ""
|
231 |
|
232 |
#: includes/admin/class-wp-job-manager-cpt.php:503
|
233 |
+
#: includes/class-wp-job-manager-shortcodes.php:333
|
234 |
msgid "Filled?"
|
235 |
msgstr ""
|
236 |
|
268 |
|
269 |
#: includes/admin/class-wp-job-manager-cpt.php:647
|
270 |
#: includes/class-wp-job-manager-post-types.php:335
|
271 |
+
#: includes/class-wp-job-manager-shortcodes.php:381
|
272 |
+
#: includes/class-wp-job-manager-shortcodes.php:414
|
273 |
msgid "Edit"
|
274 |
msgstr ""
|
275 |
|
276 |
#: includes/admin/class-wp-job-manager-cpt.php:654
|
277 |
+
#: includes/class-wp-job-manager-shortcodes.php:429
|
278 |
msgid "Delete"
|
279 |
msgstr ""
|
280 |
|
1386 |
msgid "Listing Expiry Date"
|
1387 |
msgstr ""
|
1388 |
|
1389 |
+
#: includes/class-wp-job-manager-shortcodes.php:141
|
1390 |
msgid "Invalid ID"
|
1391 |
msgstr ""
|
1392 |
|
1393 |
+
#: includes/class-wp-job-manager-shortcodes.php:148
|
1394 |
msgid "This position has already been filled"
|
1395 |
msgstr ""
|
1396 |
|
1397 |
+
#: includes/class-wp-job-manager-shortcodes.php:156
|
1398 |
#. translators: Placeholder %s is the job listing title.
|
1399 |
msgid "%s has been filled"
|
1400 |
msgstr ""
|
1401 |
|
1402 |
+
#: includes/class-wp-job-manager-shortcodes.php:161
|
1403 |
msgid "This position is not filled"
|
1404 |
msgstr ""
|
1405 |
|
1406 |
+
#: includes/class-wp-job-manager-shortcodes.php:169
|
1407 |
#. translators: Placeholder %s is the job listing title.
|
1408 |
msgid "%s has been marked as not filled"
|
1409 |
msgstr ""
|
1410 |
|
1411 |
+
#: includes/class-wp-job-manager-shortcodes.php:177
|
1412 |
#. translators: Placeholder %s is the job listing title.
|
1413 |
msgid "%s has been deleted"
|
1414 |
msgstr ""
|
1415 |
|
1416 |
+
#: includes/class-wp-job-manager-shortcodes.php:182
|
1417 |
+
#: includes/class-wp-job-manager-shortcodes.php:196
|
1418 |
msgid "Missing submission page."
|
1419 |
msgstr ""
|
1420 |
|
1421 |
+
#: includes/class-wp-job-manager-shortcodes.php:332
|
1422 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:36
|
1423 |
#: includes/widgets/class-wp-job-manager-widget-featured-jobs.php:52
|
1424 |
#: includes/widgets/class-wp-job-manager-widget-recent-jobs.php:36
|
1425 |
msgid "Title"
|
1426 |
msgstr ""
|
1427 |
|
1428 |
+
#: includes/class-wp-job-manager-shortcodes.php:334
|
1429 |
msgid "Date Posted"
|
1430 |
msgstr ""
|
1431 |
|
1432 |
+
#: includes/class-wp-job-manager-shortcodes.php:335
|
1433 |
msgid "Listing Expires"
|
1434 |
msgstr ""
|
1435 |
|
1436 |
+
#: includes/class-wp-job-manager-shortcodes.php:387
|
1437 |
+
msgid "Mark not filled"
|
1438 |
+
msgstr ""
|
1439 |
+
|
1440 |
+
#: includes/class-wp-job-manager-shortcodes.php:392
|
1441 |
+
msgid "Mark filled"
|
1442 |
+
msgstr ""
|
1443 |
+
|
1444 |
+
#: includes/class-wp-job-manager-shortcodes.php:398
|
1445 |
+
msgid "Duplicate"
|
1446 |
+
msgstr ""
|
1447 |
+
|
1448 |
+
#: includes/class-wp-job-manager-shortcodes.php:405
|
1449 |
+
msgid "Relist"
|
1450 |
+
msgstr ""
|
1451 |
+
|
1452 |
+
#: includes/class-wp-job-manager-shortcodes.php:422
|
1453 |
+
msgid "Continue Submission"
|
1454 |
+
msgstr ""
|
1455 |
+
|
1456 |
+
#: includes/class-wp-job-manager-shortcodes.php:617
|
1457 |
+
#: includes/class-wp-job-manager-shortcodes.php:655
|
1458 |
msgid "Load more listings"
|
1459 |
msgstr ""
|
1460 |
|
2139 |
msgid "You need to be signed in to manage your listings."
|
2140 |
msgstr ""
|
2141 |
|
2142 |
+
#: templates/job-dashboard.php:26
|
2143 |
msgid "Your listings are shown in the table below."
|
2144 |
msgstr ""
|
2145 |
|
2146 |
+
#: templates/job-dashboard.php:38
|
2147 |
msgid "You do not have any active listings."
|
2148 |
msgstr ""
|
2149 |
|
2150 |
+
#: templates/job-dashboard.php:51
|
2151 |
msgid "Featured Job"
|
2152 |
msgstr ""
|
2153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2154 |
#: templates/job-filters.php:30 templates/job-filters.php:31
|
2155 |
msgid "Keywords"
|
2156 |
msgstr ""
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: mikejolley, automattic, adamkheckler, alexsanford1, annezazu, cena, chaselivingston, csonnek, davor.altman, donnapep, donncha, drawmyface, erania-pinnera, jacobshere, jakeom, jeherve, jenhooks, jgs, jonryan, kraftbj, lamdayap, lschuyler, macmanx, nancythanki, orangesareorange, rachelsquirrel, ryancowles, richardmtl, scarstocea
|
3 |
Tags: job manager, job listing, job board, job management, job lists, job list, job, jobs, company, hiring, employment, employer, employees, candidate, freelance, internship, job listings, positions, board, application, hiring, listing, manager, recruiting, recruitment, talent
|
4 |
Requires at least: 5.2
|
5 |
-
Tested up to: 5.
|
6 |
Requires PHP: 7.0
|
7 |
-
Stable tag: 1.34.
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -153,6 +153,10 @@ It then creates a database based on the parameters passed to it.
|
|
153 |
|
154 |
== Changelog ==
|
155 |
|
|
|
|
|
|
|
|
|
156 |
= 1.34.3 =
|
157 |
* Fix: Hide filled listings in WordPress 5.5 sitemaps.
|
158 |
* Fix: Issue with editing a job after getting to a preview step for another job.
|
2 |
Contributors: mikejolley, automattic, adamkheckler, alexsanford1, annezazu, cena, chaselivingston, csonnek, davor.altman, donnapep, donncha, drawmyface, erania-pinnera, jacobshere, jakeom, jeherve, jenhooks, jgs, jonryan, kraftbj, lamdayap, lschuyler, macmanx, nancythanki, orangesareorange, rachelsquirrel, ryancowles, richardmtl, scarstocea
|
3 |
Tags: job manager, job listing, job board, job management, job lists, job list, job, jobs, company, hiring, employment, employer, employees, candidate, freelance, internship, job listings, positions, board, application, hiring, listing, manager, recruiting, recruitment, talent
|
4 |
Requires at least: 5.2
|
5 |
+
Tested up to: 5.6
|
6 |
Requires PHP: 7.0
|
7 |
+
Stable tag: 1.34.4
|
8 |
License: GPLv3
|
9 |
License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
153 |
|
154 |
== Changelog ==
|
155 |
|
156 |
+
= 1.34.4 =
|
157 |
+
* Fix: Harden security of job dashboard actions. Reported by Slavco.
|
158 |
+
* Updated template: `job-dashboard.php`.
|
159 |
+
|
160 |
= 1.34.3 =
|
161 |
* Fix: Hide filled listings in WordPress 5.5 sitemaps.
|
162 |
* Fix: Issue with editing a job after getting to a preview step for another job.
|
templates/job-dashboard.php
CHANGED
@@ -8,7 +8,14 @@
|
|
8 |
* @author Automattic
|
9 |
* @package wp-job-manager
|
10 |
* @category Template
|
11 |
-
* @version 1.34.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
*/
|
13 |
|
14 |
if ( ! defined( 'ABSPATH' ) ) {
|
@@ -44,47 +51,17 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
44 |
<?php echo is_position_featured( $job ) ? '<span class="featured-job-icon" title="' . esc_attr__( 'Featured Job', 'wp-job-manager' ) . '"></span>' : ''; ?>
|
45 |
<ul class="job-dashboard-actions">
|
46 |
<?php
|
47 |
-
$
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
$actions['mark_not_filled'] = [ 'label' => __( 'Mark not filled', 'wp-job-manager' ), 'nonce' => true ];
|
56 |
-
} else {
|
57 |
-
$actions['mark_filled'] = [ 'label' => __( 'Mark filled', 'wp-job-manager' ), 'nonce' => true ];
|
58 |
-
}
|
59 |
-
|
60 |
-
$actions['duplicate'] = [ 'label' => __( 'Duplicate', 'wp-job-manager' ), 'nonce' => true ];
|
61 |
-
break;
|
62 |
-
case 'expired' :
|
63 |
-
if ( job_manager_get_permalink( 'submit_job_form' ) ) {
|
64 |
-
$actions['relist'] = [ 'label' => __( 'Relist', 'wp-job-manager' ), 'nonce' => true ];
|
65 |
-
}
|
66 |
-
break;
|
67 |
-
case 'pending_payment' :
|
68 |
-
case 'pending' :
|
69 |
-
if ( WP_Job_Manager_Post_Types::job_is_editable( $job->ID ) ) {
|
70 |
-
$actions['edit'] = [ 'label' => __( 'Edit', 'wp-job-manager' ), 'nonce' => false ];
|
71 |
}
|
72 |
-
|
73 |
-
case 'draft' :
|
74 |
-
case 'preview' :
|
75 |
-
$actions['continue'] = [ 'label' => __( 'Continue Submission', 'wp-job-manager' ), 'nonce' => true ];
|
76 |
-
break;
|
77 |
-
}
|
78 |
-
|
79 |
-
$actions['delete'] = [ 'label' => __( 'Delete', 'wp-job-manager' ), 'nonce' => true ];
|
80 |
-
$actions = apply_filters( 'job_manager_my_job_actions', $actions, $job );
|
81 |
-
|
82 |
-
foreach ( $actions as $action => $value ) {
|
83 |
-
$action_url = add_query_arg( [ 'action' => $action, 'job_id' => $job->ID ] );
|
84 |
-
if ( $value['nonce'] ) {
|
85 |
-
$action_url = wp_nonce_url( $action_url, 'job_manager_my_job_actions' );
|
86 |
}
|
87 |
-
echo '<li><a href="' . esc_url( $action_url ) . '" class="job-dashboard-action-' . esc_attr( $action ) . '">' . esc_html( $value['label'] ) . '</a></li>';
|
88 |
}
|
89 |
?>
|
90 |
</ul>
|
8 |
* @author Automattic
|
9 |
* @package wp-job-manager
|
10 |
* @category Template
|
11 |
+
* @version 1.34.4
|
12 |
+
*
|
13 |
+
* @since 1.34.4 Available job actions are passed in an array (`$job_actions`, keyed by job ID) and not generated in the template.
|
14 |
+
*
|
15 |
+
* @var array $job_dashboard_columns Array of the columns to show on the job dashboard page.
|
16 |
+
* @var int $max_num_pages Maximum number of pages
|
17 |
+
* @var WP_Post[] $jobs Array of job post results.
|
18 |
+
* @var array $job_actions Array of actions available for each job.
|
19 |
*/
|
20 |
|
21 |
if ( ! defined( 'ABSPATH' ) ) {
|
51 |
<?php echo is_position_featured( $job ) ? '<span class="featured-job-icon" title="' . esc_attr__( 'Featured Job', 'wp-job-manager' ) . '"></span>' : ''; ?>
|
52 |
<ul class="job-dashboard-actions">
|
53 |
<?php
|
54 |
+
if ( ! empty( $job_actions[ $job->ID ] ) ) {
|
55 |
+
foreach ( $job_actions[ $job->ID ] as $action => $value ) {
|
56 |
+
$action_url = add_query_arg( [
|
57 |
+
'action' => $action,
|
58 |
+
'job_id' => $job->ID
|
59 |
+
] );
|
60 |
+
if ( $value['nonce'] ) {
|
61 |
+
$action_url = wp_nonce_url( $action_url, $value['nonce'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
63 |
+
echo '<li><a href="' . esc_url( $action_url ) . '" class="job-dashboard-action-' . esc_attr( $action ) . '">' . esc_html( $value['label'] ) . '</a></li>';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
}
|
|
|
65 |
}
|
66 |
?>
|
67 |
</ul>
|
wp-job-manager-functions.php
CHANGED
@@ -718,7 +718,7 @@ function job_manager_user_can_edit_job( $job_id ) {
|
|
718 |
} else {
|
719 |
$job = get_post( $job_id );
|
720 |
|
721 |
-
if ( ! $job || ( absint( $job->post_author ) !== get_current_user_id() && ! current_user_can( 'edit_post', $job_id ) ) ) {
|
722 |
$can_edit = false;
|
723 |
}
|
724 |
}
|
@@ -1464,7 +1464,7 @@ function job_manager_duplicate_listing( $post_id ) {
|
|
1464 |
}
|
1465 |
|
1466 |
$post = get_post( $post_id );
|
1467 |
-
if ( ! $post ) {
|
1468 |
return 0;
|
1469 |
}
|
1470 |
|
@@ -1509,14 +1509,21 @@ function job_manager_duplicate_listing( $post_id ) {
|
|
1509 |
if ( ! empty( $post_meta ) ) {
|
1510 |
$post_meta = wp_list_pluck( $post_meta, 'meta_value', 'meta_key' );
|
1511 |
|
1512 |
-
$default_duplicate_ignore_keys = [ '_filled', '_featured', '_job_expires', '_job_duration', '_package_id', '_user_package_id' ];
|
1513 |
$duplicate_ignore_keys = apply_filters( 'job_manager_duplicate_listing_ignore_keys', $default_duplicate_ignore_keys, true );
|
1514 |
|
1515 |
foreach ( $post_meta as $meta_key => $meta_value ) {
|
1516 |
-
|
|
|
|
|
1517 |
continue;
|
1518 |
}
|
1519 |
-
|
|
|
|
|
|
|
|
|
|
|
1520 |
}
|
1521 |
}
|
1522 |
|
718 |
} else {
|
719 |
$job = get_post( $job_id );
|
720 |
|
721 |
+
if ( ! $job || 'job_listing' !== $job->post_type || ( absint( $job->post_author ) !== get_current_user_id() && ! current_user_can( 'edit_post', $job_id ) ) ) {
|
722 |
$can_edit = false;
|
723 |
}
|
724 |
}
|
1464 |
}
|
1465 |
|
1466 |
$post = get_post( $post_id );
|
1467 |
+
if ( ! $post || 'job_listing' !== $post->post_type ) {
|
1468 |
return 0;
|
1469 |
}
|
1470 |
|
1509 |
if ( ! empty( $post_meta ) ) {
|
1510 |
$post_meta = wp_list_pluck( $post_meta, 'meta_value', 'meta_key' );
|
1511 |
|
1512 |
+
$default_duplicate_ignore_keys = [ '_filled', '_featured', '_job_expires', '_job_duration', '_package_id', '_user_package_id', '_edit_lock', '_submitting_key', '_tracked_submitted', '_tracked_approved' ];
|
1513 |
$duplicate_ignore_keys = apply_filters( 'job_manager_duplicate_listing_ignore_keys', $default_duplicate_ignore_keys, true );
|
1514 |
|
1515 |
foreach ( $post_meta as $meta_key => $meta_value ) {
|
1516 |
+
$sanitized_key = preg_replace( "/[^\x20-\x7E]/", '', $meta_key );
|
1517 |
+
|
1518 |
+
if ( in_array( $sanitized_key, $duplicate_ignore_keys, true ) ) {
|
1519 |
continue;
|
1520 |
}
|
1521 |
+
|
1522 |
+
if ( 1 === preg_match( '/^(_wp_|_oembed_)/', $sanitized_key ) ) {
|
1523 |
+
continue;
|
1524 |
+
}
|
1525 |
+
|
1526 |
+
update_post_meta( $new_post_id, wp_slash( $meta_key ), wp_slash( maybe_unserialize( $meta_value ) ) );
|
1527 |
}
|
1528 |
}
|
1529 |
|
wp-job-manager.php
CHANGED
@@ -3,11 +3,11 @@
|
|
3 |
* Plugin Name: WP Job Manager
|
4 |
* Plugin URI: https://wpjobmanager.com/
|
5 |
* Description: Manage job listings from the WordPress admin panel, and allow users to post jobs directly to your site.
|
6 |
-
* Version: 1.34.
|
7 |
* Author: Automattic
|
8 |
* Author URI: https://wpjobmanager.com/
|
9 |
* Requires at least: 5.2
|
10 |
-
* Tested up to: 5.
|
11 |
* Requires PHP: 7.0
|
12 |
* Text Domain: wp-job-manager
|
13 |
* Domain Path: /languages/
|
@@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
21 |
}
|
22 |
|
23 |
// Define constants.
|
24 |
-
define( 'JOB_MANAGER_VERSION', '1.34.
|
25 |
define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
|
26 |
define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
|
27 |
define( 'JOB_MANAGER_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|
3 |
* Plugin Name: WP Job Manager
|
4 |
* Plugin URI: https://wpjobmanager.com/
|
5 |
* Description: Manage job listings from the WordPress admin panel, and allow users to post jobs directly to your site.
|
6 |
+
* Version: 1.34.4
|
7 |
* Author: Automattic
|
8 |
* Author URI: https://wpjobmanager.com/
|
9 |
* Requires at least: 5.2
|
10 |
+
* Tested up to: 5.6
|
11 |
* Requires PHP: 7.0
|
12 |
* Text Domain: wp-job-manager
|
13 |
* Domain Path: /languages/
|
21 |
}
|
22 |
|
23 |
// Define constants.
|
24 |
+
define( 'JOB_MANAGER_VERSION', '1.34.4' );
|
25 |
define( 'JOB_MANAGER_PLUGIN_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
|
26 |
define( 'JOB_MANAGER_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
|
27 |
define( 'JOB_MANAGER_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
|