Add From Server - Version 3.3.2

Version Description

  • Security Fix: Fixes a CSRF vulnerability which could be used to trick a user into importing a large file to their site. Props to Edwin Molenaar (https://www.linkedin.com/in/edwinmolenaar)
    • Fix a typo that caused subsequent plugin activations to fail if the server doesn't meet the Add From Server requirements
    • Fix a path mismatch on certain windows configurations (No longer need to specify uppercase disk markers)
    • Import Audio metadata and store image/audio metadata in the same manner as core.
Download this release

Release Info

Developer dd32
Plugin Icon wp plugin Add From Server
Version 3.3.2
Comparing to
See all releases

Code changes from version 3.3.1 to 3.3.2

add-from-server.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /*
3
  * Plugin Name: Add From Server
4
- * Version: 3.3.1
5
  * Plugin URI: https://dd32.id.au/wordpress-plugins/add-from-server/
6
  * Description: Plugin to allow the Media Manager to add files from the webservers filesystem. <strong>Note:</strong> All files are copied to the uploads directory.
7
  * Author: Dion Hulse
1
  <?php
2
  /*
3
  * Plugin Name: Add From Server
4
+ * Version: 3.3.2
5
  * Plugin URI: https://dd32.id.au/wordpress-plugins/add-from-server/
6
  * Description: Plugin to allow the Media Manager to add files from the webservers filesystem. <strong>Note:</strong> All files are copied to the uploads directory.
7
  * Author: Dion Hulse
changelog.txt CHANGED
@@ -1,3 +1,9 @@
 
 
 
 
 
 
1
  = 3.3.1 =
2
  * Fix plugin activation
3
 
1
+ = 3.3.2 =
2
+ * Security Fix: Fixes a CSRF vulnerability which could be used to trick a user into importing a large file to their site. Props to Edwin Molenaar (https://www.linkedin.com/in/edwinmolenaar)
3
+ * Fix a typo that caused subsequent plugin activations to fail if the server doesn't meet the Add From Server requirements
4
+ * Fix a path mismatch on certain windows configurations (No longer need to specify uppercase disk markers)
5
+ * Import Audio metadata and store image/audio metadata in the same manner as core.
6
+
7
  = 3.3.1 =
8
  * Fix plugin activation
9
 
class.add-from-server.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  class Add_From_Server {
4
 
5
- var $version = '3.3.1';
6
  var $basename = '';
7
 
8
  function __construct( $plugin ) {
@@ -183,7 +183,8 @@ class Add_From_Server {
183
  $input = get_option( 'frmsvr_root' );
184
  }
185
 
186
- $input = wp_normalize_path( $input );
 
187
 
188
  return $input;
189
  }
@@ -214,10 +215,16 @@ class Add_From_Server {
214
 
215
  if ( !empty($_POST['files']) && !empty($_POST['cwd']) ) {
216
 
 
 
217
  $files = wp_unslash( $_POST['files'] );
218
 
219
  $cwd = trailingslashit( wp_unslash( $_POST['cwd'] ) );
220
- $post_id = isset($_REQUEST['post_id']) ? intval( $_REQUEST['post_id'] ) : 0;
 
 
 
 
221
  $import_date = isset($_REQUEST['import-date']) ? $_REQUEST['import-date'] : 'current';
222
 
223
  $import_to_gallery = isset($_POST['gallery']) && 'on' == $_POST['gallery'];
@@ -276,7 +283,8 @@ class Add_From_Server {
276
  }
277
 
278
  // Is the file allready in the uploads folder?
279
- if ( preg_match( '|^' . preg_quote( wp_normalize_path( $uploads['basedir'] ), '|' ) . '(.*)$|i', $file, $mat ) ) {
 
280
 
281
  $filename = basename( $file );
282
  $new_file = $file;
@@ -340,15 +348,67 @@ class Add_From_Server {
340
  $type = $return['type'];
341
 
342
  $title = preg_replace( '!\.[^.]+$!', '', basename( $file ) );
343
- $content = '';
344
 
345
- // use image exif/iptc data for title and caption defaults if possible
346
- if ( $image_meta = @wp_read_image_metadata( $new_file ) ) {
347
- if ( '' != trim( $image_meta['title'] ) ) {
348
- $title = trim( $image_meta['title'] );
 
349
  }
350
- if ( '' != trim( $image_meta['caption'] ) ) {
351
- $content = trim( $image_meta['caption'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
352
  }
353
  }
354
 
@@ -368,13 +428,15 @@ class Add_From_Server {
368
  'post_title' => $title,
369
  'post_name' => $title,
370
  'post_content' => $content,
 
371
  'post_date' => $post_date,
372
  'post_date_gmt' => $post_date_gmt
373
  );
374
 
375
  $attachment = apply_filters( 'afs-import_details', $attachment, $file, $post_id, $import_date );
376
 
377
- $new_file = str_replace( wp_normalize_path( $uploads['basedir'] ), $uploads['basedir'], $new_file );
 
378
 
379
  // Save the data
380
  $id = wp_insert_attachment( $attachment, $new_file, $post_id );
@@ -440,7 +502,8 @@ class Add_From_Server {
440
  $cwd = $this->get_root();
441
  }
442
 
443
- $cwd = wp_normalize_path( $cwd );
 
444
 
445
  if ( strlen( $cwd ) > 1 ) {
446
  $cwd = untrailingslashit( $cwd );
@@ -461,11 +524,15 @@ class Add_From_Server {
461
  }
462
 
463
  array_walk( $parts, function( &$item, $index ) use( $url, $parts ) {
464
- $path = implode( '/', array_slice( $parts, 0, $index ) );
465
  $path = ltrim( $path, '/' ) ?: '/';
466
  $item_url = add_query_arg( array( 'adirectory' => $path ), $url );
467
 
468
- $item = sprintf( '<a href="%s">%s/</a>', esc_url( $item_url ), esc_html( $item ) );
 
 
 
 
469
  } );
470
  $dirparts = implode( '', $parts );
471
 
@@ -595,6 +662,7 @@ class Add_From_Server {
595
  <?php endif; ?>
596
  </fieldset>
597
  <br class="clear"/>
 
598
  <input type="hidden" name="cwd" value="<?php echo esc_attr( $cwd ); ?>"/>
599
  <?php submit_button( __( 'Import', 'add-from-server' ), 'primary', 'import', false ); ?>
600
  </form>
@@ -607,17 +675,17 @@ class Add_From_Server {
607
  $quickjumps = array();
608
  $quickjumps[] = array(
609
  __( 'WordPress Root', 'add-from-server' ),
610
- wp_normalize_path( ABSPATH )
611
  );
612
  if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) {
613
  $quickjumps[] = array(
614
  __( 'Uploads Folder', 'add-from-server' ),
615
- wp_normalize_path( $uploads['path'] )
616
  );
617
  }
618
  $quickjumps[] = array(
619
  __( 'Content Folder', 'add-from-server' ),
620
- wp_normalize_path( WP_CONTENT_DIR )
621
  );
622
 
623
  $quickjumps = apply_filters( 'frmsvr_quickjumps', $quickjumps );
@@ -629,7 +697,7 @@ class Add_From_Server {
629
  $pieces = array();
630
  foreach ( $quickjumps as $jump ) {
631
  list( $text, $adir ) = $jump;
632
- $adir = wp_normalize_path( $adir );
633
 
634
  // Validate it's within the locked directory
635
  if ( strpos( $adir, $this->get_root() ) === false )
@@ -660,12 +728,12 @@ class Add_From_Server {
660
  function language_notice( $force = false ) {
661
  $message_english = 'Hi there!
662
  I notice you use WordPress in a Language other than English (US), Did you know you can translate WordPress Plugins into your native language as well?
663
- If you\'d like to help out with translating this plugin into %1$s you can head over to <a href="%2$s">translate.WordPress.org page</a> and suggest translations for any languages which you know.
664
  Thanks! Dion.';
665
  /* translators: %1$s = The Locale (de_DE, en_US, fr_FR, he_IL, etc). %2$s = The translate.wordpress.org link to the plugin overview */
666
  $message = __( 'Hi there!
667
  I notice you use WordPress in a Language other than English (US), Did you know you can translate WordPress Plugins into your native language as well?
668
- If you\'d like to help out with translating this plugin into %1$s you can head over to <a href="%2$s">translate.WordPress.org page</a> and suggest translations for any languages which you know.
669
  Thanks! Dion.', 'add-from-server' );
670
 
671
  // Don't display the message for English (US) or what we'll assume to be fully translated localised builds.
2
 
3
  class Add_From_Server {
4
 
5
+ var $version = '3.3.2';
6
  var $basename = '';
7
 
8
  function __construct( $plugin ) {
183
  $input = get_option( 'frmsvr_root' );
184
  }
185
 
186
+ // WP < 4.4 Compat: ucfirt
187
+ $input = ucfirst( wp_normalize_path( $input ) );
188
 
189
  return $input;
190
  }
215
 
216
  if ( !empty($_POST['files']) && !empty($_POST['cwd']) ) {
217
 
218
+ check_admin_referer( 'afs_import' );
219
+
220
  $files = wp_unslash( $_POST['files'] );
221
 
222
  $cwd = trailingslashit( wp_unslash( $_POST['cwd'] ) );
223
+ if ( false === strpos( $cwd, $this->get_root() ) ) {
224
+ return;
225
+ }
226
+
227
+ $post_id = isset($_REQUEST['post_id']) ? absint( $_REQUEST['post_id'] ) : 0;
228
  $import_date = isset($_REQUEST['import-date']) ? $_REQUEST['import-date'] : 'current';
229
 
230
  $import_to_gallery = isset($_POST['gallery']) && 'on' == $_POST['gallery'];
283
  }
284
 
285
  // Is the file allready in the uploads folder?
286
+ // WP < 4.4 Compat: ucfirt
287
+ if ( preg_match( '|^' . preg_quote( ucfirst( wp_normalize_path( $uploads['basedir'] ) ), '|' ) . '(.*)$|i', $file, $mat ) ) {
288
 
289
  $filename = basename( $file );
290
  $new_file = $file;
348
  $type = $return['type'];
349
 
350
  $title = preg_replace( '!\.[^.]+$!', '', basename( $file ) );
351
+ $content = $excerpt = '';
352
 
353
+ if ( preg_match( '#^audio#', $type ) ) {
354
+ $meta = wp_read_audio_metadata( $new_file );
355
+
356
+ if ( ! empty( $meta['title'] ) ) {
357
+ $title = $meta['title'];
358
  }
359
+
360
+ if ( ! empty( $title ) ) {
361
+
362
+ if ( ! empty( $meta['album'] ) && ! empty( $meta['artist'] ) ) {
363
+ /* translators: 1: audio track title, 2: album title, 3: artist name */
364
+ $content .= sprintf( __( '"%1$s" from %2$s by %3$s.', 'add-from-server' ), $title, $meta['album'], $meta['artist'] );
365
+ } elseif ( ! empty( $meta['album'] ) ) {
366
+ /* translators: 1: audio track title, 2: album title */
367
+ $content .= sprintf( __( '"%1$s" from %2$s.', 'add-from-server' ), $title, $meta['album'] );
368
+ } elseif ( ! empty( $meta['artist'] ) ) {
369
+ /* translators: 1: audio track title, 2: artist name */
370
+ $content .= sprintf( __( '"%1$s" by %2$s.', 'add-from-server' ), $title, $meta['artist'] );
371
+ } else {
372
+ $content .= sprintf( __( '"%s".', 'add-from-server' ), $title );
373
+ }
374
+
375
+ } elseif ( ! empty( $meta['album'] ) ) {
376
+
377
+ if ( ! empty( $meta['artist'] ) ) {
378
+ /* translators: 1: audio album title, 2: artist name */
379
+ $content .= sprintf( __( '%1$s by %2$s.', 'add-from-server' ), $meta['album'], $meta['artist'] );
380
+ } else {
381
+ $content .= $meta['album'] . '.';
382
+ }
383
+
384
+ } elseif ( ! empty( $meta['artist'] ) ) {
385
+
386
+ $content .= $meta['artist'] . '.';
387
+
388
+ }
389
+
390
+ if ( ! empty( $meta['year'] ) )
391
+ $content .= ' ' . sprintf( __( 'Released: %d.' ), $meta['year'] );
392
+
393
+ if ( ! empty( $meta['track_number'] ) ) {
394
+ $track_number = explode( '/', $meta['track_number'] );
395
+ if ( isset( $track_number[1] ) )
396
+ $content .= ' ' . sprintf( __( 'Track %1$s of %2$s.', 'add-from-server' ), number_format_i18n( $track_number[0] ), number_format_i18n( $track_number[1] ) );
397
+ else
398
+ $content .= ' ' . sprintf( __( 'Track %1$s.', 'add-from-server' ), number_format_i18n( $track_number[0] ) );
399
+ }
400
+
401
+ if ( ! empty( $meta['genre'] ) )
402
+ $content .= ' ' . sprintf( __( 'Genre: %s.', 'add-from-server' ), $meta['genre'] );
403
+
404
+ // Use image exif/iptc data for title and caption defaults if possible.
405
+ } elseif ( 0 === strpos( $type, 'image/' ) && $image_meta = @wp_read_image_metadata( $new_file ) ) {
406
+ if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) {
407
+ $title = $image_meta['title'];
408
+ }
409
+
410
+ if ( trim( $image_meta['caption'] ) ) {
411
+ $excerpt = $image_meta['caption'];
412
  }
413
  }
414
 
428
  'post_title' => $title,
429
  'post_name' => $title,
430
  'post_content' => $content,
431
+ 'post_excerpt' => $excerpt,
432
  'post_date' => $post_date,
433
  'post_date_gmt' => $post_date_gmt
434
  );
435
 
436
  $attachment = apply_filters( 'afs-import_details', $attachment, $file, $post_id, $import_date );
437
 
438
+ // WP < 4.4 Compat: ucfirt
439
+ $new_file = str_replace( ucfirst( wp_normalize_path( $uploads['basedir'] ) ), $uploads['basedir'], $new_file );
440
 
441
  // Save the data
442
  $id = wp_insert_attachment( $attachment, $new_file, $post_id );
502
  $cwd = $this->get_root();
503
  }
504
 
505
+ // WP < 4.4 Compat: ucfirt
506
+ $cwd = ucfirst( wp_normalize_path( $cwd ) );
507
 
508
  if ( strlen( $cwd ) > 1 ) {
509
  $cwd = untrailingslashit( $cwd );
524
  }
525
 
526
  array_walk( $parts, function( &$item, $index ) use( $url, $parts ) {
527
+ $path = implode( '/', array_slice( $parts, 0, $index + 1 ) );
528
  $path = ltrim( $path, '/' ) ?: '/';
529
  $item_url = add_query_arg( array( 'adirectory' => $path ), $url );
530
 
531
+ if ( $index == count( $parts ) - 1 ) {
532
+ $item = esc_html( $item ) . '/';
533
+ } else {
534
+ $item = sprintf( '<a href="%s">%s/</a>', esc_url( $item_url ), esc_html( $item ) );
535
+ }
536
  } );
537
  $dirparts = implode( '', $parts );
538
 
662
  <?php endif; ?>
663
  </fieldset>
664
  <br class="clear"/>
665
+ <?php wp_nonce_field( 'afs_import' ); ?>
666
  <input type="hidden" name="cwd" value="<?php echo esc_attr( $cwd ); ?>"/>
667
  <?php submit_button( __( 'Import', 'add-from-server' ), 'primary', 'import', false ); ?>
668
  </form>
675
  $quickjumps = array();
676
  $quickjumps[] = array(
677
  __( 'WordPress Root', 'add-from-server' ),
678
+ ucfirst( wp_normalize_path( ABSPATH ) ) // WP < 4.4 Compat: ucfirt
679
  );
680
  if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) {
681
  $quickjumps[] = array(
682
  __( 'Uploads Folder', 'add-from-server' ),
683
+ ucfirst( wp_normalize_path( $uploads['path'] ) ) // WP < 4.4 Compat: ucfirt
684
  );
685
  }
686
  $quickjumps[] = array(
687
  __( 'Content Folder', 'add-from-server' ),
688
+ ucfirst( wp_normalize_path( WP_CONTENT_DIR ) ) // WP < 4.4 Compat: ucfirt
689
  );
690
 
691
  $quickjumps = apply_filters( 'frmsvr_quickjumps', $quickjumps );
697
  $pieces = array();
698
  foreach ( $quickjumps as $jump ) {
699
  list( $text, $adir ) = $jump;
700
+ $adir = ucfirst( wp_normalize_path( $adir ) ); // WP < 4.4 Compat: ucfirt
701
 
702
  // Validate it's within the locked directory
703
  if ( strpos( $adir, $this->get_root() ) === false )
728
  function language_notice( $force = false ) {
729
  $message_english = 'Hi there!
730
  I notice you use WordPress in a Language other than English (US), Did you know you can translate WordPress Plugins into your native language as well?
731
+ If you\'d like to help out with translating this plugin into %1$s you can head over to <a href="%2$s">translate.WordPress.org</a> and suggest translations for any languages which you know.
732
  Thanks! Dion.';
733
  /* translators: %1$s = The Locale (de_DE, en_US, fr_FR, he_IL, etc). %2$s = The translate.wordpress.org link to the plugin overview */
734
  $message = __( 'Hi there!
735
  I notice you use WordPress in a Language other than English (US), Did you know you can translate WordPress Plugins into your native language as well?
736
+ If you\'d like to help out with translating this plugin into %1$s you can head over to <a href="%2$s">translate.WordPress.org</a> and suggest translations for any languages which you know.
737
  Thanks! Dion.', 'add-from-server' );
738
 
739
  // Don't display the message for English (US) or what we'll assume to be fully translated localised builds.
old-versions.php CHANGED
@@ -4,7 +4,7 @@ class Add_From_Server {
4
  function __construct( $plugin_basename ) {
5
 
6
  // Handle activation gracefully with a block screen.
7
- if ( isset( $_REQUEST['action'] ) && ( 'activate' == $_REQUEST['action'] || 'error_scrape' == $_REQUEST['action'] ) && isset( $_REQUEST['plugin'] ) && $plugin_basename = $_REQUEST['plugin'] ) {
8
  load_plugin_textdomain( 'add-from-server' );
9
  die( sprintf(
10
  __( 'This plugin requires WordPress %1$s or greater, and PHP %2$s or greater. You are currently running WordPress %3$s and PHP %4$s. Please contact your website host or server administrator for more information. The plugin has been deactivated.', 'add-from-server' ),
4
  function __construct( $plugin_basename ) {
5
 
6
  // Handle activation gracefully with a block screen.
7
+ if ( isset( $_REQUEST['action'] ) && ( 'activate' == $_REQUEST['action'] || 'error_scrape' == $_REQUEST['action'] ) && isset( $_REQUEST['plugin'] ) && $plugin_basename == $_REQUEST['plugin'] ) {
8
  load_plugin_textdomain( 'add-from-server' );
9
  die( sprintf(
10
  __( 'This plugin requires WordPress %1$s or greater, and PHP %2$s or greater. You are currently running WordPress %3$s and PHP %4$s. Please contact your website host or server administrator for more information. The plugin has been deactivated.', 'add-from-server' ),
readme.txt CHANGED
@@ -2,7 +2,7 @@
2
  Contributors: dd32
3
  Tags: admin, media, uploads, post, import, files
4
  Requires at least: 4.0
5
- Stable tag: 3.3.1
6
 
7
  "Add From Server" is a quick plugin which allows you to import media & files into the WordPress uploads manager from the Webservers filesystem
8
 
@@ -13,6 +13,12 @@ Add From Server is designed to help ease this pain, You can upload a bunch of fi
13
 
14
  == Changelog ==
15
 
 
 
 
 
 
 
16
  = 3.3.1 =
17
  * Fix plugin activation
18
 
2
  Contributors: dd32
3
  Tags: admin, media, uploads, post, import, files
4
  Requires at least: 4.0
5
+ Stable tag: 3.3.2
6
 
7
  "Add From Server" is a quick plugin which allows you to import media & files into the WordPress uploads manager from the Webservers filesystem
8
 
13
 
14
  == Changelog ==
15
 
16
+ = 3.3.2 =
17
+ * Security Fix: Fixes a CSRF vulnerability which could be used to trick a user into importing a large file to their site. Props to Edwin Molenaar (https://www.linkedin.com/in/edwinmolenaar)
18
+ * Fix a typo that caused subsequent plugin activations to fail if the server doesn't meet the Add From Server requirements
19
+ * Fix a path mismatch on certain windows configurations (No longer need to specify uppercase disk markers)
20
+ * Import Audio metadata and store image/audio metadata in the same manner as core.
21
+
22
  = 3.3.1 =
23
  * Fix plugin activation
24