Add From Server - Version 3.4

Version Description

Download this release

Release Info

Developer dd32-githubsync
Plugin Icon wp plugin Add From Server
Version 3.4
Comparing to
See all releases

Code changes from version 3.3.3 to 3.4

add-from-server.css CHANGED
@@ -1,9 +1,13 @@
1
  .frmsvr_wrap .widefat tbody tr.doesnt-meet-guidelines,
2
  .frmsvr_wrap .widefat tbody tr.unreadable {
3
  background-color: #FFE8EE;
 
 
 
 
 
4
  }
5
 
6
- .frmsvr_wrap fieldset {
7
- padding: 5px;
8
- margin-top: 0.7em;
9
  }
1
  .frmsvr_wrap .widefat tbody tr.doesnt-meet-guidelines,
2
  .frmsvr_wrap .widefat tbody tr.unreadable {
3
  background-color: #FFE8EE;
4
+ display: none;
5
+ }
6
+ .frmsvr_wrap .widefat.showhidden tbody tr.doesnt-meet-guidelines,
7
+ .frmsvr_wrap .widefat.showhidden tbody tr.unreadable {
8
+ display: table-row;
9
  }
10
 
11
+ .frmsvr_wrap .widefat.showhidden .hidden-toggle {
12
+ display: none;
 
13
  }
add-from-server.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ jQuery( document ).ready( function($) {
2
+ $( 'tr.hidden-toggle a' ).click( function( e ) {
3
+ e.preventDefault();
4
+
5
+ $(this).parents( 'table' ).addClass( 'showhidden' );
6
+
7
+ } )
8
+ });
add-from-server.php CHANGED
@@ -1,7 +1,8 @@
1
  <?php
 
2
  /*
3
  * Plugin Name: Add From Server
4
- * Version: 3.3.3
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
@@ -13,14 +14,25 @@ if ( !is_admin() ) {
13
  return;
14
  }
15
 
16
- define( 'ADD_FROM_SERVER_WP_REQUIREMENT', '4.5' );
17
- define( 'ADD_FROM_SERVER_PHP_REQUIREMENT', '5.4' );
 
 
 
 
18
 
19
  // Old versions of WordPress or PHP
20
- if ( version_compare( $GLOBALS['wp_version'], ADD_FROM_SERVER_WP_REQUIREMENT, '<' ) || version_compare( phpversion(), ADD_FROM_SERVER_PHP_REQUIREMENT, '<' ) ) {
 
 
 
 
21
  include dirname( __FILE__ ) . '/old-versions.php';
22
  } else {
23
  include __DIR__ . '/class.add-from-server.php';
24
  }
25
 
26
- $add_from_server = new Add_From_Server( plugin_basename( __FILE__ ) );
 
 
 
1
  <?php
2
+ namespace dd32\WordPress\AddFromServer;
3
  /*
4
  * Plugin Name: Add From Server
5
+ * Version: 3.4
6
  * Plugin URI: https://dd32.id.au/wordpress-plugins/add-from-server/
7
  * 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.
8
  * Author: Dion Hulse
14
  return;
15
  }
16
 
17
+ const MIN_WP = '5.1';
18
+ const MIN_PHP = '7.0';
19
+ const VERSION = '3.4';
20
+
21
+ // Dynamic constants must be define()'d.
22
+ define( __NAMESPACE__ . '\PLUGIN', plugin_basename( __FILE__ ) );
23
 
24
  // Old versions of WordPress or PHP
25
+ if (
26
+ version_compare( $GLOBALS['wp_version'], MIN_WP, '<' )
27
+ ||
28
+ version_compare( phpversion(), MIN_PHP, '<' )
29
+ ) {
30
  include dirname( __FILE__ ) . '/old-versions.php';
31
  } else {
32
  include __DIR__ . '/class.add-from-server.php';
33
  }
34
 
35
+ // Load PHP8 compat functions.
36
+ include __DIR__ . '/compat.php';
37
+
38
+ Plugin::instance();
changelog.txt CHANGED
@@ -1,3 +1,13 @@
 
 
 
 
 
 
 
 
 
 
1
  = 3.3.3 =
2
  * Fixes some scenario's where the translation warning sticks around for translated (and other english locales)
3
  * Fixes a PHP Warning
1
+ = 3.4 =
2
+ * The plugin now requires WordPress 5.1+ and PHP 7.0+. No reason other than why not.
3
+ * Bumps the version to stop the invalid vulnerability warnings.
4
+ * Cleans up code.
5
+ * Removes the User Access Control. Any user with File Upload ability can now use the plugin.
6
+ * Removes the Root Directory Control. The root directory is now assumed. You can use the ADD_FROM_SERVER constant to change it.
7
+ * Removes the Quick Jump functionality.
8
+ * Removes the ability to be able to select the date for imported media. It's always today. Or, the 1st of the month if it's stored in a dated folder.
9
+ * Removed Media Manager integration, as it's no longer shown with the WordPress Block Editor. Classic Editor is not supported by this plugin.
10
+
11
  = 3.3.3 =
12
  * Fixes some scenario's where the translation warning sticks around for translated (and other english locales)
13
  * Fixes a PHP Warning
class.add-from-server-settings.php DELETED
@@ -1,118 +0,0 @@
1
- <?php
2
-
3
- class Add_From_Server_Settings {
4
- var $main; // main Add From Server instance.
5
-
6
- function __construct($afs) {
7
- $this->main = $afs;
8
- }
9
-
10
- function render() {
11
- echo '<div class="wrap">';
12
- screen_icon( 'options-general' );
13
- echo '<h1>' . __( 'Add From Server', 'add-from-server' ) . '</h1>';
14
- echo '<form method="post" action="options.php">';
15
-
16
- settings_fields( 'add_from_server' );
17
-
18
- $uac = get_option( 'frmsvr_uac', 'allusers' );
19
- $root = $this->main->get_root( 'raw' );
20
- ?>
21
- <table class="form-table">
22
- <tr valign="top">
23
- <th scope="row"><?php _e( 'User Access Control', 'add-from-server' ); ?></th>
24
-
25
- <td>
26
- <fieldset>
27
- <legend class="screen-reader-text">
28
- <span><?php _e( 'User Access Control', 'add-from-server' ); ?></span></legend>
29
- <label for="frmsvr_uac-allusers">
30
- <input name="frmsvr_uac" type="radio" id="frmsvr_uac-allusers"
31
- value="allusers" <?php checked( $uac, 'allusers' ); ?> />
32
- <?php _e( 'All users with the ability to upload files', 'add-from-server' ); ?>
33
- </label>
34
- <br/>
35
- <label for="frmsvr_uac-role">
36
- <input name="frmsvr_uac" type="radio" id="frmsvr_uac-role"
37
- value="role" <?php checked( $uac, 'role' ); ?> />
38
- <?php _e( 'Any user with the ability to upload files in the following roles', 'add-from-server' ); ?>
39
- </label>
40
- <?php
41
- $current_roles = (array)get_option( 'frmsvr_uac_role', array() );
42
- foreach ( get_editable_roles() as $role => $details ) {
43
- if ( !isset($details['capabilities']['upload_files']) || !$details['capabilities']['upload_files'] )
44
- continue;
45
- ?>
46
- <label for="frmsvr_uac-role-<?php echo esc_attr( $role ); ?>">
47
- <input type="checkbox" name="frmsvr_uac_role[]"
48
- id="frmsvr_uac-role-<?php echo esc_attr( $role ); ?>"
49
- value="<?php echo esc_attr( $role ); ?>" <?php checked( in_array( $role, $current_roles ) ); ?> />
50
- <?php echo translate_user_role( $details['name'] ); ?>
51
- </label>
52
- <?php
53
- }
54
- ?>
55
- <br/>
56
- <label for="frmsvr_uac-listusers">
57
- <input name="frmsvr_uac" type="radio" id="frmsvr_uac-listusers"
58
- value="listusers" <?php checked( $uac, 'listusers' ); ?> />
59
- <?php _e( 'Any users with the ability to upload files listed below', 'add-from-server' ); ?>
60
- </label>
61
- <br/>
62
- <textarea rows="5" cols="20" name="frmsvr_uac_users"
63
- class="large-text code"><?php echo esc_textarea( get_option( 'frmsvr_uac_users', 'admin' ) ); ?></textarea>
64
- <br/>
65
- <small><em><?php _e( "List the user login's one per line", 'add-from-server' ); ?></em></small>
66
- </fieldset>
67
- </td>
68
- </tr>
69
- <tr valign="top">
70
- <th scope="row"><?php _e( 'Root Directory', 'add-from-server' ); ?></th>
71
-
72
- <td>
73
- <fieldset>
74
- <legend class="screen-reader-text">
75
- <span><?php _e( 'Root Directory', 'add-from-server' ); ?></span></legend>
76
- <label for="frmsvr_root-default">
77
- <?php
78
- $default_root = '/';
79
- if ( preg_match( '!(\w:)!', __FILE__, $matches ) )
80
- $default_root = strtolower( $matches[1] );
81
- ?>
82
- <input name="frmsvr_root" type="radio" id="frmsvr_root-default"
83
- value="<?php echo esc_attr( $default_root ); ?>" <?php checked( $root, $default_root ); ?> />
84
- <?php _e( 'Do not lock browsing to a specific directory', 'add-from-server' ); ?>
85
- </label>
86
- <br/>
87
- <label for="frmsvr_root-specify">
88
- <input name="frmsvr_root" type="radio" id="frmsvr_root-specify"
89
- value="specific" <?php checked( $root != $default_root ); ?> />
90
- <?php _e( 'Lock browsing to the directory specified below', 'add-from-server' ); ?>
91
- </label>
92
- <br/>
93
- <input type="text" name="frmsvr_root-specified" id="frmsvr_root-specify-specified"
94
- class="large-text code"
95
- value="<?php echo esc_attr( str_replace( '/', DIRECTORY_SEPARATOR, $root ) . (strlen( $root ) > 1 ? DIRECTORY_SEPARATOR : '') ); ?>"/>
96
- <br/>
97
- <small><em><?php
98
- printf( __( 'You may use placeholders such as %s and %s in the path.', 'add-from-server' ), '%username%', '%role%' );
99
- echo '&nbsp;&nbsp;';
100
- printf( __( 'For reference, Your WordPress Root path is: <code>%s</code>', 'add-from-server' ), ABSPATH );
101
- ?>
102
- </em></small>
103
- </fieldset>
104
- </td>
105
- </tr>
106
- </table>
107
- <script type="text/javascript">
108
- jQuery('#frmsvr_root-specify-specified').change(function () {
109
- jQuery('#frmsvr_root-specify').attr('checked', 'checked');
110
- });
111
- </script>
112
- <?php
113
- submit_button( __( 'Save Changes', 'add-from-server' ), 'primary', 'submit' );
114
- echo '</form>';
115
- $this->main->language_notice( ( get_locale() !== 'en_US' ) );
116
- echo '</div>';
117
- }
118
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
class.add-from-server.php CHANGED
@@ -1,252 +1,152 @@
1
  <?php
 
 
2
 
3
- class Add_From_Server {
4
 
5
- var $version = '3.3.3';
6
- var $basename = '';
7
 
8
- function __construct( $plugin ) {
9
- $this->basename = $plugin;
10
- // Register general hooks.
11
- add_action( 'init', array( $this, 'load_translations' ) ); // must run before admin_menu
12
- add_action( 'admin_init', array( $this, 'admin_init' ) );
13
- add_action( 'admin_menu', array( $this, 'admin_menu' ) );
14
  }
15
 
16
- function load_translations() {
17
- // Load any translation files needed:
18
- load_plugin_textdomain( 'add-from-server' );
19
  }
20
 
21
  function admin_init() {
22
- // Register our JS & CSS
23
- wp_register_style( 'add-from-server', plugins_url( '/add-from-server.css', __FILE__ ), array(), $this->version );
24
-
25
- // Enqueue JS & CSS
26
- add_action( 'load-media_page_add-from-server', array( $this, 'add_styles' ) );
27
- add_action( 'media_upload_server', array( $this, 'add_styles' ) );
28
-
29
- add_filter( 'plugin_action_links_' . $this->basename, array( $this, 'add_configure_link' ) );
30
-
31
- if ( $this->user_allowed() ) {
32
- // Add actions/filters
33
- add_filter( 'media_upload_tabs', array( $this, 'tabs' ) );
34
- add_action( 'media_upload_server', array( $this, 'tab_handler' ) );
35
- }
36
 
37
- // Register our settings:
38
- register_setting( 'add_from_server', 'frmsvr_root', array( $this, 'sanitize_option_root' ) );
39
- // register_setting('add-from-server', 'frmsvr_last_folder');
40
- register_setting( 'add_from_server', 'frmsvr_uac' );
41
- register_setting( 'add_from_server', 'frmsvr_uac_users' );
42
- register_setting( 'add_from_server', 'frmsvr_uac_role' );
43
 
 
 
44
  }
45
 
46
  function admin_menu() {
47
- if ( $this->user_allowed() ) {
48
- add_media_page( __( 'Add From Server', 'add-from-server' ), __( 'Add From Server', 'add-from-server' ), 'read', 'add-from-server', array( $this, 'menu_page' ) );
49
- }
50
- add_options_page( __( 'Add From Server', 'add-from-server' ), __( 'Add From Server', 'add-from-server' ), 'manage_options', 'add-from-server-settings', array( $this, 'options_page' ) );
51
- }
52
-
53
- function add_configure_link( $_links ) {
54
- $links = array();
55
- if ( $this->user_allowed() ) {
56
- $links[] = '<a href="' . admin_url( 'upload.php?page=add-from-server' ) . '">' . __( 'Import Files', 'add-from-server' ) . '</a>';
57
- }
58
- if ( current_user_can( 'manage_options' ) ) {
59
- $links[] = '<a href="' . admin_url( 'options-general.php?page=add-from-server-settings' ) . '">' . __( 'Options', 'add-from-server' ) . '</a>';
60
- }
61
-
62
- return array_merge( $links, $_links );
63
  }
64
 
65
- // Add a tab to the media uploader:
66
- function tabs( $tabs ) {
67
- if ( $this->user_allowed() ) {
68
- $tabs['server'] = __( 'Add From Server', 'add-from-server' );
69
  }
70
- return $tabs;
71
- }
72
 
73
- function add_styles() {
74
- // Enqueue support files.
75
- if ( 'media_upload_server' == current_filter() ) {
76
- wp_enqueue_style( 'media' );
77
- }
78
- wp_enqueue_style( 'add-from-server' );
79
- }
80
-
81
- // Handle the actual page:
82
- function tab_handler() {
83
- global $body_id;
84
- if ( !$this->user_allowed() ) {
85
- return;
86
- }
87
-
88
- $body_id = 'media-upload';
89
- iframe_header( __( 'Add From Server', 'add-from-server' ) );
90
- $this->handle_imports();
91
- $this->main_content();
92
- iframe_footer();
93
  }
94
 
95
  function menu_page() {
96
- if ( !$this->user_allowed() ) {
97
- return;
98
- }
99
-
100
- // Handle any imports:
101
  $this->handle_imports();
102
 
103
  echo '<div class="wrap">';
104
  echo '<h1>' . __( 'Add From Server', 'add-from-server' ) . '</h1>';
105
- $this->main_content();
106
- echo '</div>';
107
- }
108
 
109
- function options_page() {
110
- if ( !current_user_can( 'manage_options' ) ) {
111
- return;
112
- }
113
 
114
- include __DIR__ . '/class.add-from-server-settings.php';
115
- $settings = new Add_From_Server_Settings( $this );
116
- $settings->render();
117
  }
118
 
119
- function get_root( $context = 'use' ) {
120
- static $static_root = null;
121
- if ( $static_root )
122
- return $static_root;
 
123
 
124
- $root = get_option( 'frmsvr_root', false );
125
- if ( strpos( $root, '%' ) !== false && 'raw' != $context ) {
126
- $user = wp_get_current_user();
127
-
128
- $root = str_replace( '%username%', $user->user_login, $root );
129
- $root = str_replace( '%role%', $user->roles[0], $root );
130
- }
131
- if ( ! $root ) {
132
- if ( '/' == substr( __FILE__, 0, 1 ) ) {
133
- $root = '/';
134
- } elseif ( preg_match( '!^[a-zA-Z]:!', __FILE__, $root_win_match ) ) {
135
- $root = $root_win_match[1];
136
  }
137
  }
138
 
139
- if ( strlen( $root ) > 1 ) {
140
- $root = untrailingslashit( $root );
 
 
 
 
 
 
 
141
  }
142
 
143
  return $root;
144
  }
145
 
146
- function user_allowed() {
147
- if ( !current_user_can( 'upload_files' ) ) {
148
- return false;
149
- }
150
-
151
- switch ( get_option( 'frmsvr_uac', 'allusers' ) ) {
152
- default:
153
- case 'allusers':
154
- return true;
155
-
156
- case 'role':
157
- $user = wp_get_current_user();
158
- $roles = $user->roles;
159
- $allowed_roles = get_option( 'frmsvr_uac_role', array() );
160
- foreach ( $roles as $r ) {
161
- if ( in_array( $r, $allowed_roles ) )
162
- return true;
163
- }
164
- return false;
165
-
166
- case 'listusers':
167
- $user = wp_get_current_user();
168
- $allowed_users = explode( "\n", get_option( 'frmsvr_uac_users', '' ) );
169
- $allowed_users = array_map( 'trim', $allowed_users );
170
- $allowed_users = array_filter( $allowed_users );
171
- return in_array( $user->user_login, $allowed_users );
172
- }
173
- return false;
174
- }
175
-
176
- function sanitize_option_root($input) {
177
- $_input = $input;
178
- if ( 'specific' == $input ) {
179
- $input = wp_unslash( $_POST['frmsvr_root-specified'] );
180
- }
181
-
182
- if ( !$this->validate_option_root( $input ) ) {
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
- }
191
 
192
- function validate_option_root($o) {
193
- if ( strpos( $o, '%' ) !== false ) {
194
- // Ensure only valid placeholders are used:
195
- if ( preg_match_all( '!%(.*?)%!', $o, $placeholders ) ) {
196
- $valid_ph = array( 'username', 'role' );
197
- foreach ( $placeholders[1] as $ph ) {
198
- if ( !in_array( $ph, $valid_ph ) ) {
199
- add_settings_error( 'general', 'update_failed', sprintf( __( 'The placeholder %s is not valid in the root path.', 'add-from-server' ), '%' . $ph . '%' ), 'error' );
200
- return false;
201
- }
202
- }
203
- return true;
204
- }
205
- }
206
- if ( !is_dir( $o ) || !is_readable( $o ) ) {
207
- add_settings_error( 'general', 'update_failed', __( 'The root path specified could not be read.', 'add-from-server' ), 'error' );
208
- return false;
209
  }
210
- return true;
211
  }
212
 
213
  // Handle the imports
214
  function handle_imports() {
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'];
231
- if ( !$import_to_gallery && !isset($_REQUEST['cwd']) ) {
232
- $import_to_gallery = true; // cwd should always be set, if it's not, and neither is gallery, this must be the first page load.
233
- }
234
-
235
- if ( !$import_to_gallery ) {
236
- $post_id = 0;
237
  }
238
 
239
  flush();
240
  wp_ob_end_flush_all();
241
 
242
  foreach ( (array)$files as $file ) {
243
- $filename = $cwd . $file;
244
- $id = $this->handle_import_file( $filename, $post_id, $import_date );
 
 
 
 
 
 
245
  if ( is_wp_error( $id ) ) {
246
- echo '<div class="updated error"><p>' . sprintf( __( '<em>%s</em> was <strong>not</strong> imported due to an error: %s', 'add-from-server' ), esc_html( $file ), $id->get_error_message() ) . '</p></div>';
247
  } else {
248
- echo '<div class="updated"><p>' . sprintf( __( '<em>%s</em> has been added to Media library', 'add-from-server' ), esc_html( $file ) ) . '</p></div>';
249
  }
 
250
  flush();
251
  wp_ob_end_flush_all();
252
  }
@@ -254,37 +154,26 @@ class Add_From_Server {
254
  }
255
 
256
  // Handle an individual file import.
257
- function handle_import_file( $file, $post_id = 0, $import_date = 'current' ) {
258
  set_time_limit( 0 );
259
 
260
  // Initially, Base it on the -current- time.
261
  $time = current_time( 'mysql', 1 );
262
- // Next, If it's post to base the upload off:
263
- if ( 'post' == $import_date && $post_id > 0 ) {
264
- $post = get_post( $post_id );
265
- if ( $post && substr( $post->post_date_gmt, 0, 4 ) > 0 ) {
266
- $time = $post->post_date_gmt;
267
- }
268
- } elseif ( 'file' == $import_date ) {
269
- $time = gmdate( 'Y-m-d H:i:s', @filemtime( $file ) );
270
- }
271
 
272
  // A writable uploads dir will pass this test. Again, there's no point overriding this one.
273
- if ( !(($uploads = wp_upload_dir( $time )) && false === $uploads['error']) ) {
274
  return new WP_Error( 'upload_error', $uploads['error'] );
275
  }
276
 
277
  $wp_filetype = wp_check_filetype( $file, null );
278
-
279
- extract( $wp_filetype );
280
-
281
- if ( (!$type || !$ext) && !current_user_can( 'unfiltered_upload' ) ) {
282
  return new WP_Error( 'wrong_file_type', __( 'Sorry, this file type is not permitted for security reasons.', 'add-from-server' ) );
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;
@@ -293,34 +182,31 @@ class Add_From_Server {
293
 
294
  $attachment = get_posts( array( 'post_type' => 'attachment', 'meta_key' => '_wp_attached_file', 'meta_value' => ltrim( $mat[1], '/' ) ) );
295
  if ( !empty($attachment) ) {
296
- return new WP_Error( 'file_exists', __( 'Sorry, That file already exists in the WordPress media library.', 'add-from-server' ) );
297
  }
298
 
299
  // Ok, Its in the uploads folder, But NOT in WordPress's media library.
300
- if ( 'file' == $import_date ) {
301
- $time = @filemtime( $file );
302
- if ( preg_match( "|(\d+)/(\d+)|", $mat[1], $datemat ) ) { // So lets set the date of the import to the date folder its in, IF its in a date folder.
303
- $hour = $min = $sec = 0;
304
- $day = 1;
305
- $year = $datemat[1];
306
- $month = $datemat[2];
307
-
308
- // If the files datetime is set, and it's in the same region of upload directory, set the minute details to that too, else, override it.
309
- if ( $time && date( 'Y-m', $time ) == "$year-$month" ) {
310
- list($hour, $min, $sec, $day) = explode( ';', date( 'H;i;s;j', $time ) );
311
- }
312
-
313
- $time = mktime( $hour, $min, $sec, $month, $day, $year );
314
  }
315
- $time = gmdate( 'Y-m-d H:i:s', $time );
316
 
317
- // A new time has been found! Get the new uploads folder:
318
- // A writable uploads dir will pass this test. Again, there's no point overriding this one.
319
- if ( !(($uploads = wp_upload_dir( $time )) && false === $uploads['error']) ) {
320
- return new WP_Error( 'upload_error', $uploads['error'] );
321
- }
322
- $url = $uploads['baseurl'] . $mat[1];
 
 
323
  }
 
324
  } else {
325
  $filename = wp_unique_filename( $uploads['path'], basename( $file ) );
326
 
@@ -336,9 +222,6 @@ class Add_From_Server {
336
  // Compute the URL
337
  $url = $uploads['url'] . '/' . $filename;
338
 
339
- if ( 'file' == $import_date ) {
340
- $time = gmdate( 'Y-m-d H:i:s', @filemtime( $file ) );
341
- }
342
  }
343
 
344
  // Apply upload filters
@@ -412,140 +295,161 @@ class Add_From_Server {
412
  }
413
  }
414
 
415
- if ( $time ) {
416
- $post_date_gmt = $time;
417
- $post_date = $time;
418
- } else {
419
- $post_date = current_time( 'mysql' );
420
- $post_date_gmt = current_time( 'mysql', 1 );
421
- }
422
-
423
  // Construct the attachment array
424
- $attachment = array(
425
  'post_mime_type' => $type,
426
  'guid' => $url,
427
- 'post_parent' => $post_id,
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 );
443
  if ( !is_wp_error( $id ) ) {
444
  $data = wp_generate_attachment_metadata( $id, $new_file );
445
  wp_update_attachment_metadata( $id, $data );
446
  }
447
- // update_post_meta( $id, '_wp_attached_file', $uploads['subdir'] . '/' . $filename );
448
 
449
  return $id;
450
  }
451
 
452
- // Create the content for the page
453
- function main_content() {
454
- global $pagenow;
455
- $post_id = isset($_REQUEST['post_id']) ? intval( $_REQUEST['post_id'] ) : 0;
456
- $import_to_gallery = isset($_POST['gallery']) && 'on' == $_POST['gallery'];
457
- if ( !$import_to_gallery && !isset($_REQUEST['cwd']) ) {
458
- $import_to_gallery = true; // cwd should always be set, if it's not, and neither is gallery, this must be the first page load.
459
- }
460
- $import_date = isset($_REQUEST['import-date']) ? $_REQUEST['import-date'] : 'current';
461
 
462
- if ( 'upload.php' == $pagenow ) {
463
- $url = admin_url( 'upload.php?page=add-from-server' );
464
- } else {
465
- $url = admin_url( 'media-upload.php?tab=server' );
466
  }
467
 
468
- if ( $post_id ) {
469
- $url = add_query_arg( 'post_id', $post_id, $url );
470
- }
471
-
472
- $cwd = trailingslashit( get_option( 'frmsvr_last_folder' ) ?: WP_CONTENT_DIR );
473
-
474
- if ( isset($_REQUEST['directory']) ) {
475
- $cwd .= stripslashes( urldecode( $_REQUEST['directory'] ) );
476
- }
477
-
478
- if ( isset($_REQUEST['adirectory']) && empty($_REQUEST['adirectory']) ) {
479
- $_REQUEST['adirectory'] = '/'; // For good measure.
480
- }
481
 
482
- if ( isset($_REQUEST['adirectory']) ) {
483
- $cwd = stripslashes( urldecode( $_REQUEST['adirectory'] ) );
484
- }
485
 
486
- $cwd = preg_replace( '![^/]*/\.\./!', '', $cwd );
487
- $cwd = preg_replace( '!//!', '/', $cwd );
488
 
489
- if ( !is_readable( $cwd ) && is_readable( $this->get_root() . '/' . ltrim( $cwd, '/' ) ) ) {
490
- $cwd = $this->get_root() . '/' . ltrim( $cwd, '/' );
 
491
  }
492
 
493
- if ( !is_readable( $cwd ) && get_option( 'frmsvr_last_folder' ) ) {
494
- $cwd = get_option( 'frmsvr_last_folder' );
 
495
  }
496
 
497
- if ( !is_readable( $cwd ) ) {
498
- $cwd = WP_CONTENT_DIR;
 
499
  }
500
 
501
- if ( strpos( $cwd, $this->get_root() ) === false ) {
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 );
 
 
510
  }
511
 
512
- if ( !is_readable( $cwd ) ) {
513
- echo '<div class="error"><p>' . __( '<strong>Error:</strong> This users root directory is not readable. Please have your site administrator correct the <em>Add From Server</em> root directory settings.', 'add-from-server' ) . '</p></div>';
514
- return;
515
- }
516
 
517
- update_option( 'frmsvr_last_folder', $cwd );
 
518
 
519
- $files = $this->find_files( $cwd );
 
 
520
 
521
- $parts = explode( '/', ltrim( str_replace( $this->get_root(), '/', $cwd ), '/' ) );
522
- if ( $parts[0] != '' ) {
523
- $parts = array_merge( (array)'', $parts );
524
- }
525
 
526
- // array_walk() + eAccelerator + anonymous function = bad news
527
- foreach ( $parts as $index => &$item ) {
528
- $this_path = implode( '/', array_slice( $parts, 0, $index + 1 ) );
529
- $this_path = ltrim( $this_path, '/' ) ?: '/';
530
- $item_url = add_query_arg( array( 'adirectory' => $this_path ), $url );
531
 
532
- if ( $index == count( $parts ) - 1 ) {
533
- $item = esc_html( $item ) . '/';
534
- } else {
535
- $item = sprintf( '<a href="%s">%s/</a>', esc_url( $item_url ), esc_html( $item ) );
536
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
  }
538
 
539
- $dirparts = implode( '', $parts );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
 
541
  ?>
542
  <div class="frmsvr_wrap">
543
  <form method="post" action="<?php echo esc_url( $url ); ?>">
544
- <p><?php printf( __( '<strong>Current Directory:</strong> <span id="cwd">%s</span>', 'add-from-server' ), $dirparts ) ?></p>
545
- <?php $this->display_quick_jumps( $url ); ?>
546
- <?php if ( 'media-upload.php' == $GLOBALS['pagenow'] && $post_id > 0 ) : ?>
547
- <p><?php _e( 'Once you have Imported your files, head over to <strong>Insert Media</strong> to add them to your post.', 'add-from-server' ); ?></p>
548
- <?php endif; ?>
 
 
549
  <table class="widefat">
550
  <thead>
551
  <tr>
@@ -555,91 +459,59 @@ class Add_From_Server {
555
  </thead>
556
  <tbody>
557
  <?php
558
- $parent = dirname( $cwd );
559
- if ( $parent != $cwd && (strpos( $parent, $this->get_root() ) === 0) && is_readable( $parent ) ) :
560
- $parent = preg_replace( '!^' . preg_quote( $this->get_root(), '!' ) . '!i', '', $parent );
561
- ?>
562
- <tr>
563
- <td>&nbsp;</td>
564
- <td>
565
- <a href="<?php echo esc_url( add_query_arg( array( 'adirectory' => rawurlencode( $parent ) ), $url ) ); ?>"
566
- title="<?php echo esc_attr( dirname( $cwd ) ) ?>"><?php _e( 'Parent Folder', 'add-from-server' ); ?></a>
567
- </td>
568
- </tr>
569
- <?php endif; ?>
570
- <?php
571
- $directories = array();
572
- foreach ( (array)$files as $key => $file ) {
573
- if ( is_dir( $file ) ) {
574
- $directories[] = $file;
575
- unset($files[$key]);
576
- }
577
- }
578
 
579
- sort( $directories );
580
- sort( $files );
581
-
582
- foreach ( (array)$directories as $file ) :
583
- $filename = preg_replace( '!^' . preg_quote( $cwd ) . '!i', '', $file );
584
- $filename = ltrim( $filename, '/' );
585
- $folder_url = add_query_arg( array( 'directory' => rawurlencode( $filename ), 'import-date' => $import_date, 'gallery' => $import_to_gallery ), $url );
586
- ?>
587
- <tr>
588
- <td>&nbsp;</td>
589
- <td>
590
- <a href="<?php echo esc_url( $folder_url ); ?>"><?php echo esc_html( rtrim( $filename, '/' ) . '/' ); ?></a>
591
- </td>
592
- </tr>
593
- <?php
594
- endforeach;
595
- $names = $rejected_files = $unreadable_files = array();
596
- $unfiltered_upload = current_user_can( 'unfiltered_upload' );
597
- foreach ( (array)$files as $key => $file ) {
598
- if ( !$unfiltered_upload ) {
599
- $wp_filetype = wp_check_filetype( $file );
600
- if ( false === $wp_filetype['type'] ) {
601
- $rejected_files[] = $file;
602
- unset($files[$key]);
603
- continue;
604
- }
605
- }
606
- if ( !is_readable( $file ) ) {
607
- $unreadable_files[] = $file;
608
- unset($files[$key]);
609
  continue;
610
  }
 
 
 
 
 
 
 
 
 
611
  }
612
 
613
- foreach ( array( 'meets_guidelines' => $files, 'unreadable' => $unreadable_files, 'doesnt_meets_guidelines' => $rejected_files ) as $key => $_files ) :
614
- $file_meets_guidelines = $unfiltered_upload || ('meets_guidelines' == $key);
615
- $unreadable = 'unreadable' == $key;
616
- foreach ( $_files as $file_index => $file ) :
617
- $classes = array();
618
-
619
- if ( !$file_meets_guidelines ) {
620
- $classes[] = 'doesnt-meet-guidelines';
621
- }
622
- if ( $unreadable ) {
623
- $classes[] = 'unreadable';
624
- }
625
-
626
- $filename = preg_replace( '!^' . preg_quote( $cwd, '!' ) . '!', '', $file );
627
- $filename = ltrim( $filename, '/' );
628
-
629
- ?>
630
- <tr class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>" title="<?php if ( !$file_meets_guidelines ) {
631
- esc_attr_e( 'Sorry, this file type is not permitted for security reasons. Please see the FAQ.', 'add-from-server' );
632
- } elseif ( $unreadable ) {
633
- esc_attr_e( 'Sorry, but this file is unreadable by your Webserver. Perhaps check your File Permissions?', 'add-from-server' );
634
- } ?>">
635
- <th class='check-column'>
636
- <input type='checkbox' id='file-<?php echo (int)$file_index; ?>' name='files[]' value='<?php echo esc_attr( $filename ); ?>' <?php disabled( !$file_meets_guidelines || $unreadable ); ?> />
637
  </th>
638
- <td>
639
- <label for='file-<?php echo (int)$file_index; ?>'><?php echo esc_html( $filename ); ?></label>
640
- </td>
641
- </tr>
642
- <?php endforeach; endforeach; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
643
  </tbody>
644
  <tfoot>
645
  <tr>
@@ -649,84 +521,14 @@ class Add_From_Server {
649
  </tfoot>
650
  </table>
651
 
652
- <fieldset>
653
- <legend><?php _e( 'Import Options', 'add-from-server' ); ?></legend>
654
-
655
- <?php if ( $post_id ) : ?>
656
- <input type="checkbox" name="gallery" id="gallery-import" <?php checked( $import_to_gallery ); ?> /><label for="gallery-import"><?php _e( 'Attach imported files to this post', 'add-from-server' ) ?></label>
657
- <br class="clear"/>
658
- <?php endif; ?>
659
- <?php _e( 'Set the imported date to the', 'add-from-server' ); ?>
660
- <input type="radio" name="import-date" id="import-time-currenttime" value="current" <?php checked( 'current', $import_date ); ?> /> <label for="import-time-currenttime"><?php _e( 'Current Time', 'add-from-server' ); ?></label>
661
- <input type="radio" name="import-date" id="import-time-filetime" value="file" <?php checked( 'file', $import_date ); ?> /> <label for="import-time-filetime"><?php _e( 'File Time', 'add-from-server' ); ?></label>
662
- <?php if ( $post_id ) : ?>
663
- <input type="radio" name="import-date" id="import-time-posttime" value="post" <?php checked( 'post', $import_date ); ?> /> <label for="import-time-posttime"><?php _e( 'Post Time', 'add-from-server' ); ?></label>
664
- <?php endif; ?>
665
- </fieldset>
666
  <br class="clear"/>
667
  <?php wp_nonce_field( 'afs_import' ); ?>
668
- <input type="hidden" name="cwd" value="<?php echo esc_attr( $cwd ); ?>"/>
669
  <?php submit_button( __( 'Import', 'add-from-server' ), 'primary', 'import', false ); ?>
670
  </form>
671
- <?php $this->language_notice(); ?>
672
  </div>
673
  <?php
674
  }
675
 
676
- function display_quick_jumps( $url ) {
677
- $quickjumps = array();
678
- $quickjumps[] = array(
679
- __( 'WordPress Root', 'add-from-server' ),
680
- ucfirst( wp_normalize_path( ABSPATH ) ) // WP < 4.4 Compat: ucfirt
681
- );
682
- if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) {
683
- $quickjumps[] = array(
684
- __( 'Uploads Folder', 'add-from-server' ),
685
- ucfirst( wp_normalize_path( $uploads['path'] ) ) // WP < 4.4 Compat: ucfirt
686
- );
687
- }
688
- $quickjumps[] = array(
689
- __( 'Content Folder', 'add-from-server' ),
690
- ucfirst( wp_normalize_path( WP_CONTENT_DIR ) ) // WP < 4.4 Compat: ucfirt
691
- );
692
-
693
- $quickjumps = apply_filters( 'frmsvr_quickjumps', $quickjumps );
694
-
695
- if ( empty( $quickjumps ) ) {
696
- return;
697
- }
698
-
699
- $pieces = array();
700
- foreach ( $quickjumps as $jump ) {
701
- list( $text, $adir ) = $jump;
702
- $adir = ucfirst( wp_normalize_path( $adir ) ); // WP < 4.4 Compat: ucfirt
703
-
704
- // Validate it's within the locked directory
705
- if ( strpos( $adir, $this->get_root() ) === false )
706
- continue;
707
-
708
- $adir = preg_replace( '!^' . preg_quote( $this->get_root(), '!' ) . '!i', '', $adir );
709
- if ( strlen( $adir ) > 1 ) {
710
- $adir = ltrim( $adir, '/' );
711
- }
712
-
713
- $durl = add_query_arg( array( 'adirectory' => rawurlencode( $adir ) ), $url );
714
- $pieces[] = sprintf( '<a href="%s">%s</a>', esc_url( $durl ), esc_html( $text ) );
715
- }
716
-
717
- if ( !empty( $pieces ) ) {
718
- printf( '<p>' . __( '<strong>Quick Jump:</strong> %s', 'add-from-server' ) . '<p>', implode( ' | ', $pieces ) );
719
- }
720
- }
721
-
722
- function find_files( $folder ) {
723
- if ( !is_readable( $folder ) ) {
724
- return array();
725
- }
726
-
727
- return glob( rtrim( $folder, '/' ) . '/*' );
728
- }
729
-
730
  function language_notice( $force = false ) {
731
  $message_english = 'Hi there!
732
  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?
@@ -753,4 +555,32 @@ Thanks! Dion.', 'add-from-server' );
753
  echo '<div class="notice notice-info"><p>' . sprintf( nl2br( $message ), get_locale(), $translate_url ) . '</p></div>';
754
  }
755
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
756
  }
1
  <?php
2
+ namespace dd32\WordPress\AddFromServer;
3
+ use WP_Error;
4
 
5
+ const COOKIE = 'frmsvr_path';
6
 
7
+ class Plugin {
 
8
 
9
+ public static function instance() {
10
+ static $instance = false;
11
+ $class = static::class;
12
+
13
+ return $instance ?: ( $instance = new $class );
 
14
  }
15
 
16
+ protected function __construct() {
17
+ add_action( 'admin_init', [ $this, 'admin_init' ] );
18
+ add_action( 'admin_menu', [ $this, 'admin_menu' ] );
19
  }
20
 
21
  function admin_init() {
22
+ // Register JS & CSS
23
+ wp_register_script( 'add-from-server', plugins_url( '/add-from-server.js', __FILE__ ), array( 'jquery' ), VERSION );
24
+ wp_register_style( 'add-from-server', plugins_url( '/add-from-server.css', __FILE__ ), array(), VERSION );
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ add_filter( 'plugin_action_links_' . PLUGIN, [ $this, 'add_upload_link' ] );
 
 
 
 
 
27
 
28
+ // Handle the path selection early.
29
+ $this->path_selection_cookie();
30
  }
31
 
32
  function admin_menu() {
33
+ $page_slug = add_media_page(
34
+ __( 'Add From Server', 'add-from-server' ),
35
+ __( 'Add From Server', 'add-from-server' ),
36
+ 'upload_files',
37
+ 'add-from-server',
38
+ [ $this, 'menu_page' ]
39
+ );
40
+ add_action( 'load-' . $page_slug, function() {
41
+ wp_enqueue_style( 'add-from-server' );
42
+ wp_enqueue_script( 'add-from-server' );
43
+ } );
 
 
 
 
 
44
  }
45
 
46
+ function add_upload_link( $links ) {
47
+ if ( current_user_can( 'upload_files' ) ) {
48
+ array_unshift( $links, '<a href="' . admin_url( 'upload.php?page=add-from-server' ) . '">' . __( 'Import Files', 'add-from-server' ) . '</a>' );
 
49
  }
 
 
50
 
51
+ return $links;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
  function menu_page() {
55
+ // Handle any imports
 
 
 
 
56
  $this->handle_imports();
57
 
58
  echo '<div class="wrap">';
59
  echo '<h1>' . __( 'Add From Server', 'add-from-server' ) . '</h1>';
 
 
 
60
 
61
+ $this->outdated_options_notice();
62
+ $this->main_content();
63
+ $this->language_notice();
 
64
 
65
+ echo '</div>';
 
 
66
  }
67
 
68
+ function get_root() {
69
+ // Lock users to either
70
+ // a) The 'ADD_FROM_SERVER' constant.
71
+ // b) Their home directory.
72
+ // c) The parent directory of the current install or wp-content directory.
73
 
74
+ if ( defined( 'ADD_FROM_SERVER' ) ) {
75
+ $root = ADD_FROM_SERVER;
76
+ } elseif ( str_starts_with( __FILE__, '/home/' ) ) {
77
+ $root = implode( '/', array_slice( explode( '/', __FILE__ ), 0, 3 ) );
78
+ } else {
79
+ if ( str_starts_with( WP_CONTENT_DIR, ABSPATH ) ) {
80
+ $root = dirname( ABSPATH );
81
+ } else {
82
+ $root = dirname( WP_CONTENT_DIR );
 
 
 
83
  }
84
  }
85
 
86
+ // Precautions. The user is using the folder placeholder code. Abort for lower-privledge users.
87
+ if (
88
+ str_contains( get_option( 'frmsvr_root', '%' ), '%' )
89
+ &&
90
+ ! defined( 'ADD_FROM_SERVER' )
91
+ &&
92
+ ! current_user_can( 'unfiltered_html' )
93
+ ) {
94
+ $root = false;
95
  }
96
 
97
  return $root;
98
  }
99
 
100
+ function path_selection_cookie() {
101
+ if ( isset( $_REQUEST['path'] ) && current_user_can( 'upload_files' ) ) {
102
+ $_COOKIE[ COOKIE ] = $_REQUEST['path'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
+ $parts = parse_url( admin_url(), PHP_URL_HOST );
 
 
 
 
105
 
106
+ setcookie(
107
+ COOKIE,
108
+ wp_unslash( $_COOKIE[ COOKIE ] ),
109
+ time() + 30 * DAY_IN_SECONDS,
110
+ parse_url( admin_url(), PHP_URL_PATH ),
111
+ parse_url( admin_url(), PHP_URL_HOST ),
112
+ 'https' === parse_url( admin_url(), PHP_URL_SCHEME ),
113
+ true
114
+ );
 
 
 
 
 
 
 
 
115
  }
 
116
  }
117
 
118
  // Handle the imports
119
  function handle_imports() {
120
 
121
+ if ( !empty( $_POST['files'] ) ) {
122
 
123
  check_admin_referer( 'afs_import' );
124
 
125
  $files = wp_unslash( $_POST['files'] );
126
 
127
+ $root = $this->get_root();
128
+ if ( ! $root ) {
129
+ return false;
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
 
132
  flush();
133
  wp_ob_end_flush_all();
134
 
135
  foreach ( (array)$files as $file ) {
136
+ $filename = trailingslashit( $root ) . ltrim( $file, '/' );
137
+
138
+ if ( $filename !== realpath( $filename ) ) {
139
+ continue;
140
+ }
141
+
142
+ $id = $this->handle_import_file( $filename );
143
+
144
  if ( is_wp_error( $id ) ) {
145
+ echo '<div class="updated error"><p>' . sprintf( __( '<em>%s</em> was <strong>not</strong> imported due to an error: %s', 'add-from-server' ), esc_html( basename( $file ) ), $id->get_error_message() ) . '</p></div>';
146
  } else {
147
+ echo '<div class="updated"><p>' . sprintf( __( '<em>%s</em> has been added to Media library', 'add-from-server' ), esc_html( basename( $file ) ) ) . '</p></div>';
148
  }
149
+
150
  flush();
151
  wp_ob_end_flush_all();
152
  }
154
  }
155
 
156
  // Handle an individual file import.
157
+ function handle_import_file( $file ) {
158
  set_time_limit( 0 );
159
 
160
  // Initially, Base it on the -current- time.
161
  $time = current_time( 'mysql', 1 );
 
 
 
 
 
 
 
 
 
162
 
163
  // A writable uploads dir will pass this test. Again, there's no point overriding this one.
164
+ if ( ! ( ( $uploads = wp_upload_dir( $time ) ) && false === $uploads['error'] ) ) {
165
  return new WP_Error( 'upload_error', $uploads['error'] );
166
  }
167
 
168
  $wp_filetype = wp_check_filetype( $file, null );
169
+ $type = $wp_filetype['type'];
170
+ $ext = $wp_filetype['ext'];
171
+ if ( ( !$type || !$ext ) && !current_user_can( 'unfiltered_upload' ) ) {
 
172
  return new WP_Error( 'wrong_file_type', __( 'Sorry, this file type is not permitted for security reasons.', 'add-from-server' ) );
173
  }
174
 
175
  // Is the file allready in the uploads folder?
176
+ if ( preg_match( '|^' . preg_quote( wp_normalize_path( $uploads['basedir'] ), '|' ) . '(.*)$|i', $file, $mat ) ) {
 
177
 
178
  $filename = basename( $file );
179
  $new_file = $file;
182
 
183
  $attachment = get_posts( array( 'post_type' => 'attachment', 'meta_key' => '_wp_attached_file', 'meta_value' => ltrim( $mat[1], '/' ) ) );
184
  if ( !empty($attachment) ) {
185
+ return new WP_Error( 'file_exists', __( 'Sorry, that file already exists in the WordPress media library.', 'add-from-server' ) );
186
  }
187
 
188
  // Ok, Its in the uploads folder, But NOT in WordPress's media library.
189
+ if ( preg_match( "|(\d+)/(\d+)|", $mat[1], $datemat ) ) { // So lets set the date of the import to the date folder its in, IF its in a date folder.
190
+ $hour = $min = $sec = 0;
191
+ $day = 1;
192
+ $year = $datemat[1];
193
+ $month = $datemat[2];
194
+
195
+ // If the files datetime is set, and it's in the same region of upload directory, set the minute details to that too, else, override it.
196
+ if ( $time && date( 'Y-m', $time ) == "$year-$month" ) {
197
+ list($hour, $min, $sec, $day) = explode( ';', date( 'H;i;s;j', $time ) );
 
 
 
 
 
198
  }
 
199
 
200
+ $time = mktime( $hour, $min, $sec, $month, $day, $year );
201
+ }
202
+ $time = gmdate( 'Y-m-d H:i:s', $time );
203
+
204
+ // A new time has been found! Get the new uploads folder:
205
+ // A writable uploads dir will pass this test. Again, there's no point overriding this one.
206
+ if ( !(($uploads = wp_upload_dir( $time )) && false === $uploads['error']) ) {
207
+ return new WP_Error( 'upload_error', $uploads['error'] );
208
  }
209
+ $url = $uploads['baseurl'] . $mat[1];
210
  } else {
211
  $filename = wp_unique_filename( $uploads['path'], basename( $file ) );
212
 
222
  // Compute the URL
223
  $url = $uploads['url'] . '/' . $filename;
224
 
 
 
 
225
  }
226
 
227
  // Apply upload filters
295
  }
296
  }
297
 
 
 
 
 
 
 
 
 
298
  // Construct the attachment array
299
+ $attachment = [
300
  'post_mime_type' => $type,
301
  'guid' => $url,
302
+ 'post_parent' => 0,
303
  'post_title' => $title,
304
  'post_name' => $title,
305
  'post_content' => $content,
306
  'post_excerpt' => $excerpt,
307
+ 'post_date' => $time,
308
+ 'post_date_gmt' => $time,
309
+ ];
310
 
311
+ $attachment = apply_filters( 'afs-import_details', $attachment, $file, 0, 'current' );
 
 
 
312
 
313
  // Save the data
314
+ $id = wp_insert_attachment( $attachment, $new_file, 0 );
315
  if ( !is_wp_error( $id ) ) {
316
  $data = wp_generate_attachment_metadata( $id, $new_file );
317
  wp_update_attachment_metadata( $id, $data );
318
  }
 
319
 
320
  return $id;
321
  }
322
 
323
+ protected function get_default_dir() {
324
+ $root = $this->get_root();
 
 
 
 
 
 
 
325
 
326
+ if ( false !== str_starts_with( WP_CONTENT_DIR, $root ) ) {
327
+ return WP_CONTENT_DIR;
 
 
328
  }
329
 
330
+ return $root;
331
+ }
 
 
 
 
 
 
 
 
 
 
 
332
 
333
+ // Create the content for the page
334
+ function main_content() {
 
335
 
336
+ $url = admin_url( 'upload.php?page=add-from-server' );
 
337
 
338
+ $root = $this->get_root();
339
+ if ( ! $root ) {
340
+ return; // Intervention required.
341
  }
342
 
343
+ $cwd = $this->get_default_dir();
344
+ if ( ! empty( $_COOKIE[ COOKIE ] ) ) {
345
+ $cwd = realpath( trailingslashit( $root ) . wp_unslash( $_COOKIE[ COOKIE ] ) );
346
  }
347
 
348
+ // Validate it.
349
+ if ( ! str_starts_with( $cwd, $root ) ) {
350
+ $cwd = $root;
351
  }
352
 
353
+ $cwd_relative = substr( $cwd, strlen( $root ) );
 
 
354
 
355
+ // Make a list of the directories the user can enter.
356
+ $dirparts = [
357
+ esc_html( trailingslashit( dirname( $root ) ) ),
358
+ '<a href="' . esc_url( add_query_arg( 'path', '/', $url ) ) . '">' . esc_html( basename( $root ) ) . '</a>'
359
+ ];
360
 
361
+ $dir_path = '';
362
+ foreach ( explode( '/', $cwd_relative ) as $dir ) {
363
+ $dir_path .= '/' . $dir;
364
+ $dirparts[] = '<a href="' . esc_url( add_query_arg( 'path', rawurlencode( $dir_path ), $url ) ) . '">' . esc_html( $dir ) . '/</a> ';
365
  }
366
 
367
+ $dirparts = implode( '', $dirparts );
 
 
 
368
 
369
+ // Get a list of files to show.
370
+ $nodes = glob( rtrim( $cwd, '/' ) . '/*' ) ?: [];
371
 
372
+ $directories = array_flip( array_filter( $nodes, function( $node ) {
373
+ return is_dir( $node );
374
+ } ) );
375
 
376
+ $get_import_root = function( $path ) use ( &$get_import_root ) {
377
+ if ( ! is_readable( $path ) ) {
378
+ return false;
379
+ }
380
 
381
+ $files = glob( $path . '/*' );
382
+ if ( ! $files ) {
383
+ return false;
384
+ }
 
385
 
386
+ if ( 1 === count( $files ) && is_dir( $files[0] ) ) {
387
+ return $get_import_root( $files[0] );
 
 
388
  }
389
+
390
+ return $path;
391
+ };
392
+
393
+ array_walk( $directories, function( &$data, $path ) use( $root, $cwd_relative, $get_import_root ) {
394
+ $import_root = $get_import_root( $path );
395
+
396
+ $data = [
397
+ 'text' => substr(
398
+ substr( $import_root, strlen( $root ) + 1 ),
399
+ strlen( $cwd_relative )
400
+ ) . '/',
401
+ 'path' => substr( $import_root, strlen( $root ) + 1 )
402
+ ];
403
+ } );
404
+
405
+ // Prefix the parent directory.
406
+ if ( str_starts_with( dirname( $cwd ), $root ) ) {
407
+ $directories = array_merge(
408
+ [
409
+ dirname( $cwd ) => [
410
+ 'text' => __( 'Parent Folder', 'add-from-server' ),
411
+ 'path' => substr( dirname( $cwd ), strlen( $root ) + 1 ) ?: '/',
412
+ ]
413
+ ],
414
+ $directories
415
+ );
416
  }
417
 
418
+ $files = array_flip( array_filter( $nodes, function( $node ) {
419
+ return is_file( $node );
420
+ } ) );
421
+ array_walk( $files, function( &$data, $path ) use( $root ) {
422
+ $importable = ( false !== wp_check_filetype( $path )['type'] || current_user_can( 'unfiltered_upload' ) );
423
+ $readable = is_readable( $path );
424
+
425
+ $data = [
426
+ 'text' => basename( $path ),
427
+ 'file' => substr( $path, strlen( $root ) + 1 ),
428
+ 'importable' => $importable,
429
+ 'readable' => $readable,
430
+ 'error' => (
431
+ ! $importable ? 'doesnt-meet-guidelines' : (
432
+ ! $readable ? 'unreadable' : false
433
+ )
434
+ ),
435
+ ];
436
+ } );
437
+
438
+ // Importable files first.
439
+ uasort( $files, function( $a, $b ) {
440
+ return $a['error'] <=> $b['error'];
441
+ } );
442
 
443
  ?>
444
  <div class="frmsvr_wrap">
445
  <form method="post" action="<?php echo esc_url( $url ); ?>">
446
+ <p><?php
447
+ printf(
448
+ __( '<strong>Current Directory:</strong> %s', 'add-from-server' ),
449
+ '<span id="cwd">' . $dirparts . '</span>'
450
+ );
451
+ ?></p>
452
+
453
  <table class="widefat">
454
  <thead>
455
  <tr>
459
  </thead>
460
  <tbody>
461
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
 
463
+ foreach ( $directories as $dir ) {
464
+ if ( ! $dir['path'] ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
465
  continue;
466
  }
467
+
468
+ printf(
469
+ '<tr>
470
+ <td>&nbsp;</td>
471
+ <td><a href="%s">%s</a></td>
472
+ </tr>',
473
+ esc_url( add_query_arg( 'path', $dir['path'], $url ) ),
474
+ esc_html( $dir['text'] )
475
+ );
476
  }
477
 
478
+ $file_id = 0;
479
+ foreach ( $files as $file ) {
480
+ $error_str = '';
481
+ if ( 'doesnt-meet-guidelines' === $file['error'] ) {
482
+ $error_str = __( 'Sorry, this file type is not permitted for security reasons. Please see the FAQ.', 'add-from-server' );
483
+ } else if ( 'unreadable' === $file['error'] ) {
484
+ $error_str = __( 'Sorry, but this file is unreadable by your Webserver. Perhaps check your File Permissions?', 'add-from-server' );
485
+ }
486
+
487
+ printf(
488
+ '<tr class="%1$s" title="%2$s">
489
+ <th class="check-column">
490
+ <input type="checkbox" id="file-%3$d" name="files[]" value="%4$s" %5$s />
 
 
 
 
 
 
 
 
 
 
 
491
  </th>
492
+ <td><label for="file-%3$d">%6$s</label></td>
493
+ </tr>',
494
+ $file['error'] ?: '', // 1
495
+ $error_str, // 2
496
+ $file_id++, // 3
497
+ $file['file'], // 4
498
+ disabled( false, $file['readable'] && $file['importable'], false ), // 5
499
+ esc_html( $file['text'] ) // 6
500
+ );
501
+ }
502
+
503
+ if ( isset( $file ) && $file['error'] ) {
504
+ // The last file was an error, display a expander.
505
+ printf(
506
+ '<tr class="hidden-toggle">
507
+ <td>&nbsp;</td>
508
+ <td><a href="#">%1$s</a></td>
509
+ </tr>',
510
+ __( 'Show hidden files', 'add-from-server' )
511
+ );
512
+ }
513
+
514
+ ?>
515
  </tbody>
516
  <tfoot>
517
  <tr>
521
  </tfoot>
522
  </table>
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  <br class="clear"/>
525
  <?php wp_nonce_field( 'afs_import' ); ?>
 
526
  <?php submit_button( __( 'Import', 'add-from-server' ), 'primary', 'import', false ); ?>
527
  </form>
 
528
  </div>
529
  <?php
530
  }
531
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
532
  function language_notice( $force = false ) {
533
  $message_english = 'Hi there!
534
  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?
555
  echo '<div class="notice notice-info"><p>' . sprintf( nl2br( $message ), get_locale(), $translate_url ) . '</p></div>';
556
  }
557
 
558
+ function outdated_options_notice() {
559
+ $old_root = get_option( 'frmsvr_root', '' );
560
+
561
+ if (
562
+ str_contains( $old_root, '%' )
563
+ &&
564
+ ! defined( 'ADD_FROM_SERVER' )
565
+ ) {
566
+ printf(
567
+ '<div class="notice error"><p>%s</p></div>',
568
+ 'You previously used the "Root Directory" option with a placeholder, such as "%username% or "%role%".<br>' .
569
+ 'Unfortunately this feature is no longer supported. As a result, Add From Server has been disabled for users who have restricted upload privledges.<br>' .
570
+ 'To make this warning go away, empty the "frmsvr_root" option on <a href="options.php#frmsvr_root">options.php</a>.'
571
+ );
572
+ }
573
+
574
+ if ( $old_root && ! str_starts_with( $old_root, $this->get_root() ) ) {
575
+ printf(
576
+ '<div class="notice error"><p>%s</p></div>',
577
+ 'Warning: Root Directory changed. You previously used <code>' . esc_html( $old_root ) . '</code> as your "Root Directory", ' .
578
+ 'this has been changed to <code>' . esc_html( $this->get_root() ) . '</code>.<br>' .
579
+ 'To restore your previous settings, add the following line to your <code>wp-config.php</code> file:<br>' .
580
+ '<code>define( "ADD_FROM_SERVER", "' . $old_root . '" );</code><br>' .
581
+ 'To make this warning go away, empty the "frmsvr_root" option on <a href="options.php#frmsvr_root">options.php</a>.'
582
+ );
583
+ }
584
+ }
585
+
586
  }
compat.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Symfony Polyfill https://github.com/symfony/polyfill/blob/master/src/Php80/Php80.php
3
+
4
+ if ( ! function_exists( 'str_starts_with' ) ) {
5
+ function str_starts_with( $haystack, $needle ) {
6
+ return 0 === strncmp( $haystack, $needle, strlen( $needle ) );
7
+ }
8
+ }
9
+
10
+ if ( ! function_exists( 'str_ends_with' ) ) {
11
+ function str_ends_with( $haystack, $needle ) {
12
+ return '' === $needle || ( '' !== $haystack && 0 === substr_compare( $haystack, $needle, -strlen( $needle ) ) );
13
+ }
14
+ }
15
+
16
+ if ( ! function_exists( 'str_contains' ) ) {
17
+ function str_contains( $haystack, $needle ) {
18
+ return '' === $needle || false !== strpos($haystack, $needle );
19
+ }
20
+ }
old-versions.php CHANGED
@@ -1,15 +1,22 @@
1
  <?php
2
 
3
- 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' ),
11
- ADD_FROM_SERVER_WP_REQUIREMENT,
12
- ADD_FROM_SERVER_PHP_REQUIREMENT,
13
  $GLOBALS['wp_version'],
14
  phpversion()
15
  ) );
@@ -19,14 +26,13 @@ class Add_From_Server {
19
  }
20
 
21
  function unsupported_plugins_notice( $var ) {
22
- load_plugin_textdomain( 'add-from-server' );
23
  printf(
24
  '<div class="error"><p><strong>%s</strong>: %s</p></div>',
25
  __( 'Add From Server', 'add-from-server' ),
26
  sprintf(
27
  __( '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' ),
28
- ADD_FROM_SERVER_WP_REQUIREMENT,
29
- ADD_FROM_SERVER_PHP_REQUIREMENT,
30
  $GLOBALS['wp_version'],
31
  phpversion()
32
  )
1
  <?php
2
 
3
+ class Plugin {
4
+ function __construct() {
5
 
6
  // Handle activation gracefully with a block screen.
7
+ if (
8
+ isset( $_REQUEST['action'] ) &&
9
+ (
10
+ 'activate' == $_REQUEST['action'] ||
11
+ 'error_scrape' == $_REQUEST['action']
12
+ ) &&
13
+ isset( $_REQUEST['plugin'] ) &&
14
+ PLUGIN == $_REQUEST['plugin']
15
+ ) {
16
  die( sprintf(
17
  __( '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' ),
18
+ MIN_WP,
19
+ MIN_PHP,
20
  $GLOBALS['wp_version'],
21
  phpversion()
22
  ) );
26
  }
27
 
28
  function unsupported_plugins_notice( $var ) {
 
29
  printf(
30
  '<div class="error"><p><strong>%s</strong>: %s</p></div>',
31
  __( 'Add From Server', 'add-from-server' ),
32
  sprintf(
33
  __( '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' ),
34
+ MIN_WP,
35
+ MIN_PHP,
36
  $GLOBALS['wp_version'],
37
  phpversion()
38
  )
readme.md ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Add From Server
2
+ ===============
3
+ * Contributors: dd32
4
+ * Tags: admin, media, uploads, post, import, files
5
+ * Requires at least: 5.0
6
+ * Tested up to: 5.2
7
+ * Requires PHP: 7.0
8
+ * Stable tag: 3.4
9
+
10
+ Add From Server is designed to help ease the pain of bad web hosts, allowing you to upload files via FTP or SSH and later import them into WordPress.
11
+
12
+ ## Description
13
+
14
+ This plugin is officially unsupported. Please do not expect new features or bugfixes. Features may be removed at any time.
15
+
16
+ Add From Server is designed to help ease the pain of bad web hosts, allowing you to upload files via FTP or SSH and later import them into WordPress.
17
+
18
+ This plugin is NOT designed to..
19
+ * Be used as a replacement for the file uploader
20
+ * Be used for migration of websites
21
+ * Re-import your files after moving webhosting
22
+ * Batch import media
23
+
24
+ This plugins IS designed to..
25
+ * Import files which are larger than your hosting allows to be uploaded.
26
+ * Import files which are too large for your internet connections upload speed.
27
+
28
+ WordPress does a better job of file uploads than this plugin, so please consider your needs before you use it.
29
+
30
+ You may also want to look at using WP-CLI for media import purposes:
31
+ https://developer.wordpress.org/cli/commands/media/import/
32
+
33
+ ## Changelog
34
+
35
+ ### 3.4
36
+ * The plugin now requires WordPress 5.1+ and PHP 7.0+. No reason other than why not.
37
+ * Bumps the version to stop the invalid vulnerability warnings.
38
+ * Cleans up code.
39
+ * Removes the User Access Control. Any user with File Upload ability can now use the plugin.
40
+ * Removes the Root Directory Control. The root directory is now assumed. You can use the ADD_FROM_SERVER constant to change it.
41
+ * Removes the Quick Jump functionality.
42
+ * Removes the ability to be able to select the date for imported media. It's always today. Or, the 1st of the month if it's stored in a dated folder.
43
+ * Removed Media Manager integration, as it's no longer shown with the WordPress Block Editor. Classic Editor is not supported by this plugin.
44
+
45
+ ## Frequently Asked Questions
46
+
47
+ ### How can I import files from other folders?
48
+ In 3.4, the plugin changed to limit the directories you can import files from.
49
+ If you wish to import files from other folders, you need to add the ADD_FROM_SERVER constant to your wp-config.php file.
50
+ For example:
51
+ `define( 'ADD_FROM_SERVER', '/www/' );`
52
+
53
+ ### Why does the file I want to import have a red background?
54
+ WordPress only allows the importing/uploading of certain file types to improve your security.
55
+ If you wish to add extra file types, you can use a plugin such as: http://wordpress.org/extend/plugins/pjw-mime-config/ You can also enable "Unfiltered uploads" globally for WordPress if you'd like to override this security function. Please see the WordPress support forum for details.
56
+
57
+ ### Where are the files saved?
58
+ If you import a file which is outside your standard upload directory (usually wp-content/uploads/) then it will be copied to your current upload directory setting as normal.
59
+ If you however import a file which **is already within the uploads directory** (for example, wp-content/uploads/2011/02/superplugin.zip) then the file will not be copied, and will be used as-is.
60
+
61
+ ### I have a a bug report
62
+ You can report bugs on <a href="https://github.com/dd32/add-from-server">GitHub</a> and get support in the <a href="https://wordpress.org/support/plugin/add-from-server/">WordPress.org Support Forums</a>.
readme.txt DELETED
@@ -1,69 +0,0 @@
1
- === Add From Server ===
2
- Contributors: dd32
3
- Tags: admin, media, uploads, post, import, files
4
- Requires at least: 4.5
5
- Tested up to: 4.9
6
- Stable tag: 3.3.2
7
-
8
- "Add From Server" is a quick plugin which allows you to import media & files into the WordPress uploads manager from the Webservers filesystem
9
-
10
- == Description ==
11
-
12
- ** Support for this plugin is NOT offered, This plugin still however works. Please don't expect support requests to be answered, or "This doesn't work" reviews to be responded to. **
13
-
14
- Please Note: This plugin is not designed to replace the media uploader. This plugin is not designed to be used for migration of sites. This plugin is not designed to re-import your media upload history. This plugin is not designed to Batch import your media. Etc. This plugin is 8 years old and designed for importing singular large files which could not be uploaded through the administration interface.
15
-
16
- The heart of a CMS is the ability to upload and insert content, WordPress does a fantastic job at this, unfortunately, some web hosts have limited servers, or users simply do not have the ability to upload large files through their web browser.
17
- Add From Server is designed to help ease this pain, You can upload a bunch of files via FTP (Or your favourite transmission method) and simply import those files from the webserver directly into WordPress.
18
-
19
- == Changelog ==
20
-
21
- = 3.3.3 =
22
- * Fixes some scenario's where the translation warning sticks around for translated (and other english locales)
23
- * Fixes a PHP Warning
24
- * Support per-user locales
25
- * Bumps required version of WordPress to 4.5+
26
-
27
- = 3.3.2 =
28
- * 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)
29
- * Fix a typo that caused subsequent plugin activations to fail if the server doesn't meet the Add From Server requirements
30
- * Fix a path mismatch on certain windows configurations (No longer need to specify uppercase disk markers)
31
- * Import Audio metadata and store image/audio metadata in the same manner as core.
32
-
33
- = 3.3.1 =
34
- * Fix plugin activation
35
-
36
- = 3.3 =
37
- * The plugin now requires WordPress 4.0 and PHP 5.4 as a minumum requirement.
38
- * Updated to use WordPress.org translation system, please submit translations through https://translate.wordpress.org/projects/wp-plugins/add-from-server/stable
39
- * Updated to WordPress 4.3 styles
40
-
41
- == Upgrade Notice ==
42
-
43
- = 3.3.1 =
44
- Warning: This plugin now requires WordPress 4.0 & PHP 5.4. Updates to support WordPress 4.3 & WordPress.org Language Pack Translations
45
-
46
- = 3.3 =
47
- Warning: This plugin now requires WordPress 4.0 & PHP 5.4. Updates to support WordPress 4.3 & WordPress.org Language Pack Translations
48
-
49
- == FAQ ==
50
-
51
- = What placeholders can I use in the Root path option? =
52
- You can use `%role%` and `%username%` only.
53
- In the case of `%role%`, the first role which the user has is used, this can mean that in complex installs where a user has many roles that using %role% could be unreliable.
54
-
55
- = Why does the file I want to import have a red background? =
56
- WordPress only allows the importing/uploading of certain file types to improve your security.
57
- If you wish to add extra file types, you can use a plugin such as: http://wordpress.org/extend/plugins/pjw-mime-config/ You can also enable "Unfiltered uploads" globally for WordPress if you'd like to override this security function. Please see the WordPress support forum for details.
58
-
59
- = Where are the files saved? =
60
- If you import a file which is outside your standard upload directory (usually wp-content/uploads/) then it will be copied to your current upload directory setting as normal.
61
- If you however import a file which **is already within the uploads directory** (for example, wp-content/uploads/2011/02/superplugin.zip) then the file will not be copied, and will be used as-is.
62
-
63
- = I have a a bug report =
64
- You can report bugs in the <a href="https://wordpress.org/support/plugin/add-from-server">plugins Support Forum here</a>
65
-
66
- == Screenshots ==
67
-
68
- 1. The import manager, This allows you to select which files to import. Note that files which cannot be imported are Red.
69
- 2. The Options panel, This allows you to specify what users can access Add From Server, and which folders users can import files from.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
screenshot-1.png DELETED
Binary file
screenshot-2.png DELETED
Binary file