PluginProbe
WPIDE – File Manager & Code Editor / 1.0.6
WPIDE – File Manager & Code Editor v1.0.6
3.5.8 3.5.7 2.0.14 2.0.15 2.0.16 2.0.2 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1 2.2 2.3 2.3.1 2.3.2 2.4.0 2.5 2.6 3.0 3.1 3.2 3.3 3.4 All 54 releases
← All changes | WPide.php +199 -791 2.21.0.6 View file →
@@ -1,844 +1,252 @@
1 1 <?php
2 2 /*
3 +
3 4 Plugin Name: WPide
4 5 Plugin URI: https://github.com/WPsites/WPide
5 -Description: WordPress code editor with auto completion of both WordPress and PHP functions with reference, syntax highlighting, line numbers, tabbed editing, automatic backup.
6 -Version: 2.2
7 -Author: Simon @ WPsites
6 +Description: Replace the default WordPress code editor for plugins and themes. Adding syntax highlighting, autocomplete of WordPress functions + PHP, line numbers, auto backup of files before editing.
7 +Version: 1.0.6
8 +Author: Simon Dunton
8 9 Author URI: http://www.wpsites.co.uk
10 +
9 11 */
10 12
11 -// Exit if accessed directly
12 -if ( !defined( 'ABSPATH' ) ) exit;
13 13
14 14
15 -if ( !class_exists( 'wpide' ) ) :
16 -class wpide
15 +class WPide
17 16
18 17 {
19 18
20 - public $site_url, $plugin_url;
21 -
22 - /**
23 - * The main WPide loader (PHP4 compatable)
24 - *
25 - * @uses wpide::__construct() Setup the globals needed
26 - */
27 - public function wpide() {
28 - $this->__construct();
29 - }
30 -
19 +
31 20 function __construct() {
32 -
33 - //add WPide to the menu
34 - add_action( 'admin_menu', array( $this, 'add_my_menu_page' ) );
35 -
36 - //hook for processing incoming image saves
37 - if ( isset($_GET['wpide_save_image']) ){
38 -
39 - //force local file method for testing - you could force other methods 'direct', 'ssh', 'ftpext' or 'ftpsockets'
40 - $this->override_fs_method('direct');
41 -
42 - add_action('admin_init', array( $this, 'wpide_save_image') );
43 -
44 - }
45 -
46 -
47 - //only include this plugin if on theme editor, plugin editor or an ajax call
48 - if ( (isset($_GET['page']) && $_GET['page'] === 'wpide') ||
49 - preg_match('#admin-ajax\.php$#', $_SERVER['PHP_SELF']) ){
50 -
51 -
52 - // force local file method until I've worked out how to implement the other methods
53 - // main problem being password wouldn't/isn't saved between requests
54 - // you could force other methods 'direct', 'ssh', 'ftpext' or 'ftpsockets'
55 - $this->override_fs_method('direct');
56 21
57 - // Uncomment any of these calls to add the functionality that you need.
58 - add_action('admin_init', array( $this, 'add_admin_js' ) );
59 - add_action('admin_init', array( $this, 'add_admin_styles' ) );
60 -
61 - //setup jqueryFiletree list callback
62 - add_action('wp_ajax_jqueryFileTree', array( $this, 'jqueryFileTree_get_list' ) );
63 - //setup ajax function to get file contents for editing
64 - add_action('wp_ajax_wpide_get_file', array( $this, 'wpide_get_file' ) );
65 - //setup ajax function to save file contents and do automatic backup if needed
66 - add_action('wp_ajax_wpide_save_file', array( $this, 'wpide_save_file' ) );
67 - //setup ajax function to create new item (folder, file etc)
68 - add_action('wp_ajax_wpide_create_new', array( $this, 'wpide_create_new' ) );
69 -
70 - //setup ajax function to create new item (folder, file etc)
71 - add_action('wp_ajax_wpide_image_edit_key', array( $this, 'wpide_image_edit_key' ) );
72 -
73 - //setup ajax function for startup to get some debug info, checking permissions etc
74 - add_action('wp_ajax_wpide_startup_check', array( $this, 'wpide_startup_check' ) );
75 -
76 - //add a warning when navigating away from WPide
77 - //it has to go after WordPress scripts otherwise WP clears the binding
78 - add_action('admin_print_footer_scripts', array( $this, 'add_admin_nav_warning' ), 99 );
79 -
80 - // Add body class to collapse the wp sidebar nav
81 - add_filter('admin_body_class', array( $this, 'hide_wp_sidebar_nav' ), 11);
82 -
83 - //hide the update nag
84 - add_action('admin_menu', array( $this, 'hide_wp_update_nag' ));
85 -
86 - }
22 + // Uncomment any of these calls to add the functionality that you need.
23 + add_action('admin_head', 'WPide::add_admin_head');
24 + add_action('admin_init', 'WPide::add_admin_js');
25 +
26 + //setup ajax function to save a backup
27 + add_action('wp_ajax_ace_backup_call', 'WPide::ace_backup_call');
87 28
88 29
89 -
30 + }
31 +
32 + public static function add_admin_head()
33 + {
90 34
91 -
92 - $this->site_url = get_bloginfo('url');
93 -
35 + ?>
94 36
37 + <style type="text/css">
38 + #quicktags, #post-status-info, #editor-toolbar, #newcontent, .ace_print_margin { display: none; }
39 + #fancyeditordiv {
40 + position: relative;
41 + width: 500px;
42 + height: 400px;
95 43 }
44 + #template div{margin-right:0 !important;}
45 + </style>
96 46
47 + <?php
97 48
98 - public function override_fs_method($method = 'direct'){
99 -
100 -
101 - if ( defined('FS_METHOD') ){
102 -
103 - define('WPIDE_FS_METHOD_FORCED_ELSEWHERE', FS_METHOD); //make a note of the forced method
104 -
105 - }else{
106 -
107 - define('FS_METHOD', $method); //force direct
108 -
109 - }
110 -
111 49 }
112 -
113 50
114 - public function hide_wp_sidebar_nav($classes) {
115 -
116 - return str_replace("auto-fold", "", $classes) . ' folded';
51 + public static function add_admin_js()
52 + {
53 + $plugin_path = get_bloginfo('url').'/wp-content/plugins/' . basename(dirname(__FILE__)) .'/';
54 + //include ace
55 + wp_enqueue_script('ace', $plugin_path . 'ace-0.2.0/src/ace.js');
56 + //include ace modes for css, javascript & php
57 + wp_enqueue_script('ace-mode-css', $plugin_path . 'ace-0.2.0/src/mode-css.js');
58 + wp_enqueue_script('ace-mode-javascript', $plugin_path . 'ace-0.2.0/src/mode-javascript.js');
59 + wp_enqueue_script('ace-mode-php', $plugin_path . 'ace-0.2.0/src/mode-php.js');
60 + //include ace theme
61 + wp_enqueue_script('ace-theme', $plugin_path . 'ace-0.2.0/src/theme-dawn.js');//monokai is nice
62 + // html tags for completion
63 + wp_enqueue_script('wpide-editor-completion', $plugin_path . 'js/html-tags.js');
64 + // load & prepare editor
65 + wp_enqueue_script('wpide-editor-load', $plugin_path . 'js/load-editor.js');
117 66 }
118 -
119 - public function hide_wp_update_nag() {
120 - remove_action( 'admin_notices', 'update_nag', 3 );
121 - }
122 67
123 - public static function add_admin_nav_warning()
124 - {
125 - ?>
126 - <script type="text/javascript">
127 -
128 - jQuery(document).ready(function($) {
129 - window.onbeforeunload = function() {
130 - return 'You are attempting to navigate away from WPide. Make sure you have saved any changes made to your files otherwise they will be forgotten.' ;
131 - }
132 - });
133 -
134 - </script>
135 - <?php
136 - }
137 68
69 + public static function ace_backup_call() {
138 70
71 + $backup_path = get_bloginfo('url').'/wp-content/plugins/' . basename(dirname(__FILE__)) .'/backups/';
72 + $file_name = $_POST['filename'];
73 + $edit_type = $_POST['edittype'];
139 74
75 + if ($edit_type==='theme'){
76 + $theme_root = get_theme_root();
77 + $short_path = str_replace($theme_root, '', $file_name);
140 78
79 + $new_file_path_daily = WP_PLUGIN_DIR.'/wpide/backups/themes'.$short_path.'.'.date("Ymd");
80 + $new_file_path_hourly = WP_PLUGIN_DIR.'/wpide/backups/themes'.$short_path.'.'.date("YmdH");
141 81
82 + $new_file_info = pathinfo($new_file_path_daily);
142 83
143 - public static function add_admin_js(){
144 -
145 - $plugin_path = plugin_dir_url( __FILE__ );
146 - //include file tree
147 - wp_enqueue_script('jquery-file-tree', plugins_url("jqueryFileTree.js", __FILE__ ) );
148 - //include ace
149 - wp_enqueue_script('ace', plugins_url("ace-0.2.0/src/ace.js", __FILE__ ) );
150 - //include ace modes for css, javascript & php
151 - wp_enqueue_script('ace-mode-css', $plugin_path . 'ace-0.2.0/src/mode-css.js');
152 - wp_enqueue_script('ace-mode-less', $plugin_path . 'ace-0.2.0/src/mode-less.js');
153 - wp_enqueue_script('ace-mode-javascript', $plugin_path . 'ace-0.2.0/src/mode-javascript.js');
154 - wp_enqueue_script('ace-mode-php', $plugin_path . 'ace-0.2.0/src/mode-php.js');
155 - //include ace theme
156 - wp_enqueue_script('ace-theme', plugins_url("ace-0.2.0/src/theme-dawn.js", __FILE__ ) );//monokai is nice
157 - // wordpress-completion tags
158 - wp_enqueue_script('wpide-wordpress-completion', plugins_url("js/autocomplete/wordpress.js", __FILE__ ) );
159 - // php-completion tags
160 - wp_enqueue_script('wpide-php-completion', plugins_url("js/autocomplete/php.js", __FILE__ ) );
161 - // load editor
162 - wp_enqueue_script('wpide-load-editor', plugins_url("js/load-editor.js", __FILE__ ) );
163 - // load autocomplete dropdown
164 - wp_enqueue_script('wpide-dd', plugins_url("js/jquery.dd.js", __FILE__ ) );
165 -
166 - // load jquery ui
167 - wp_enqueue_script('jquery-ui', plugins_url("js/jquery-ui-1.9.2.custom.min.js", __FILE__ ), array('jquery'), '1.9.2');
168 -
169 - // load color picker
170 - wp_enqueue_script('ImageColorPicker', plugins_url("js/ImageColorPicker.js", __FILE__ ), array('jquery'), '0.3');
171 -
172 -
173 -
174 - }
175 -
176 - public static function add_admin_styles(){
84 + if (!is_dir($new_file_info['dirname'])) mkdir($new_file_info['dirname'], 0777, true); //make directory if not exist
177 85
178 - //main wpide styles
179 - wp_register_style( 'wpide_style', plugins_url('wpide.css', __FILE__) );
180 - wp_enqueue_style( 'wpide_style' );
181 - //filetree styles
182 - wp_register_style( 'wpide_filetree_style', plugins_url('jqueryFileTree.css', __FILE__) );
183 - wp_enqueue_style( 'wpide_filetree_style' );
184 - //autocomplete dropdown styles
185 - wp_register_style( 'wpide_dd_style', plugins_url('dd.css', __FILE__) );
186 - wp_enqueue_style( 'wpide_dd_style' );
187 -
188 - //jquery ui styles
189 - wp_register_style( 'wpide_jqueryui_style', plugins_url('css/flick/jquery-ui-1.8.20.custom.css', __FILE__) );
190 - wp_enqueue_style( 'wpide_jqueryui_style' );
191 -
192 -
193 - }
194 -
195 -
196 -
197 - public static function jqueryFileTree_get_list() {
198 - //check the user has the permissions
199 - check_admin_referer('plugin-name-action_wpidenonce');
200 - if ( !current_user_can('edit_themes') )
201 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
202 -
203 - //setup wp_filesystem api
204 - global $wp_filesystem;
205 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
206 - $form_fields = null; // for now, but at some point the login info should be passed in here
207 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
208 - // no credentials yet, just produced a form for the user to fill in
209 - return true; // stop the normal page form from displaying
210 - }
211 -
212 - if ( ! WP_Filesystem($creds) )
213 - return false;
214 -
215 - $_POST['dir'] = urldecode($_POST['dir']);
216 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
217 -
218 - if( $wp_filesystem->exists($root . $_POST['dir']) ) {
219 - //$files = scandir($root . $_POST['dir']);
220 - //print_r($files);
221 - $files = $wp_filesystem->dirlist($root . $_POST['dir']);
222 - //print_r($files);
223 -
224 - echo "<ul class=\"jqueryFileTree\" style=\"display: none;\">";
225 - if( count($files) > 0 ) {
226 -
227 - // All dirs
228 - foreach( $files as $file => $file_info ) {
229 - if( $file != '.' && $file != '..' && $file_info['type']=='d' ) {
230 - echo "<li class=\"directory collapsed\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file) . "/\">" . htmlentities($file) . "</a></li>";
231 - }
86 + //check for todays backup if non existant then create
87 + if (!file_exists($new_file_path_daily)){
88 + $backup_result = copy($file_name, $new_file_path_daily); //make a copy of the file
89 +
90 + //check for a backup this hour if doesn't exist then create
91 + }else if(!file_exists($new_file_path_hourly)){
92 + $backup_result = copy($file_name, $new_file_path_hourly); //make a copy of the file
232 93 }
233 - // All files
234 - foreach( $files as $file => $file_info ) {
235 - if( $file != '.' && $file != '..' && $file_info['type']!='d') {
236 - $ext = preg_replace('/^.*\./', '', $file);
237 - echo "<li class=\"file ext_$ext\"><a href=\"#\" rel=\"" . htmlentities($_POST['dir'] . $file) . "\">" . htmlentities($file) . "</a></li>";
238 - }
94 +
95 + //do no further backups since one intial backup for today and an hourly one is plenty!
96 +
97 + }else if ($edit_type==='plugin'){
98 +
99 + $plugin_root = WP_PLUGIN_DIR;
100 + $short_path = str_replace($plugin_root, '', $file_name);
101 +
102 + $new_file_path_daily = WP_PLUGIN_DIR.'/wpide/backups/plugins/'.$short_path.'.'.date("Ymd");
103 + $new_file_path_hourly = WP_PLUGIN_DIR.'/wpide/backups/plugins/'.$short_path.'.'.date("YmdH");
104 +
105 + $new_file_info = pathinfo($new_file_path_daily);
106 +
107 + if (!is_dir($new_file_info['dirname'])) mkdir($new_file_info['dirname'], 0777, true); //make directory if not exist
108 +
109 + //check for todays backup if non existant then create
110 + if (!file_exists($new_file_path_daily)){
111 + $backup_result = copy($plugin_root.'/'.$file_name, $new_file_path_daily); //make a copy of the file
112 +
113 + //check for a backup this hour if doesn't exist then create
114 + }else if(!file_exists($new_file_path_hourly)){
115 + $backup_result = copy($plugin_root.'/'.$file_name, $new_file_path_hourly); //make a copy of the file
116 +
239 117 }
240 - }
241 - //output toolbar for creating new file, folder etc
242 - echo "<li class=\"create_new\"><a class='new_directory' title='Create a new directory here.' href=\"#\" rel=\"{type: 'directory', path: '" . htmlentities($_POST['dir']) . "'}\"></a> <a class='new_file' title='Create a new file here.' href=\"#\" rel=\"{type: 'file', path: '" . htmlentities($_POST['dir']) . "'}\"></a><br style='clear:both;' /></li>";
243 - echo "</ul>";
118 +
119 + //do no further backups since one intial backup for today and an hourly one is plenty!
120 +
244 121 }
245 -
246 - die(); // this is required to return a proper result
247 - }
248 122
249 -
250 - public static function wpide_get_file() {
251 - //check the user has the permissions
252 - check_admin_referer('plugin-name-action_wpidenonce');
253 - if ( !current_user_can('edit_themes') )
254 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
255 -
256 - //setup wp_filesystem api
257 - global $wp_filesystem;
258 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
259 - $form_fields = null; // for now, but at some point the login info should be passed in here
260 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
261 - // no credentials yet, just produced a form for the user to fill in
262 - return true; // stop the normal page form from displaying
263 - }
264 - if ( ! WP_Filesystem($creds) )
265 - return false;
266 -
267 -
268 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
269 - $file_name = $root . stripslashes($_POST['filename']);
270 - echo $wp_filesystem->get_contents($file_name);
271 - die(); // this is required to return a proper result
272 - }
273 -
274 -
275 -
276 - public static function wpide_image_edit_key() {
277 -
278 - //check the user has the permissions
279 - check_admin_referer('plugin-name-action_wpidenonce');
280 - if ( !current_user_can('edit_themes') )
281 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
282 -
283 - //create a nonce based on the image path
284 - echo wp_create_nonce( 'wpide_image_edit' . $_POST['file'] );
285 -
286 - }
287 -
288 - public static function wpide_create_new() {
289 - //check the user has the permissions
290 - check_admin_referer('plugin-name-action_wpidenonce');
291 - if ( !current_user_can('edit_themes') )
292 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
293 -
294 - //setup wp_filesystem api
295 - global $wp_filesystem;
296 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
297 - $form_fields = null; // for now, but at some point the login info should be passed in here
298 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
299 - // no credentials yet, just produced a form for the user to fill in
300 - return true; // stop the normal page form from displaying
301 - }
302 - if ( ! WP_Filesystem($creds) )
303 - return false;
304 -
305 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
306 -
307 - //check all required vars are passed
308 - if (strlen($_POST['path'])>0 && strlen($_POST['type'])>0 && strlen($_POST['file'])>0){
309 -
310 -
311 - $filename = sanitize_file_name( $_POST['file'] );
312 - $path = $_POST['path'];
313 -
314 - if ($_POST['type'] == "directory"){
315 -
316 - $write_result = $wp_filesystem->mkdir($root . $path . $filename, FS_CHMOD_DIR);
317 -
318 - if ($write_result){
319 - die("1"); //created
320 - }else{
321 - echo "Problem creating directory" . $root . $path . $filename;
322 - }
323 -
324 - }else if ($_POST['type'] == "file"){
325 -
326 - //write the file
327 - $write_result = $wp_filesystem->put_contents(
328 - $root . $path . $filename,
329 - '',
330 - FS_CHMOD_FILE // predefined mode settings for WP files
331 - );
332 -
333 - if ($write_result){
334 - die("1"); //created
335 - }else{
336 - echo "Problem creating file " . $root . $path . $filename;
337 - }
338 -
339 - }
340 -
341 -
342 - //print_r($_POST);
343 -
344 -
123 + if ($backup_result){
124 + echo "success";
345 125 }
346 - echo "0";
126 +
127 + //echo "final debug info : " . WP_PLUGIN_DIR.'/wpide/backups/'.$short_path.'.backup';
347 128 die(); // this is required to return a proper result
129 +
348 130 }
349 -
350 - public static function wpide_save_file() {
351 - //check the user has the permissions
352 - check_admin_referer('plugin-name-action_wpidenonce');
353 - if ( !current_user_can('edit_themes') )
354 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
355 -
356 - $is_php = false;
357 -
358 - //check file syntax of PHP files by parsing the PHP
359 - if ( preg_match("#\.php$#i", $_POST['filename']) ){
360 -
361 - $is_php = true;
362 -
363 - require('PHP-Parser/lib/bootstrap.php');
364 - ini_set('xdebug.max_nesting_level', 2000);
365 -
366 - $code = stripslashes($_POST['content']);
367 -
368 - $parser = new PHPParser_Parser(new PHPParser_Lexer);
369 -
370 - try {
371 - $stmts = $parser->parse($code);
372 - } catch (PHPParser_Error $e) {
373 - echo 'Parse Error: ', $e->getMessage();
374 - die();
375 - }
376 - }
377 131
378 - //setup wp_filesystem api
379 - global $wp_filesystem;
380 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
381 - $form_fields = null; // for now, but at some point the login info should be passed in here
382 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
383 - // no credentials yet, just produced a form for the user to fill in
384 - return true; // stop the normal page form from displaying
385 - }
386 - if ( ! WP_Filesystem($creds) )
387 - echo "Cannot initialise the WP file system API";
132 +}
133 +
134 +//only include this plugin if on theme or plugin editors (Or Multisite network equivalents) or an ajax call
135 +$is_ms = '';
136 +if ( is_multisite() )
137 + $is_ms = 'network/';
138 +
139 +if ( $_SERVER['PHP_SELF'] === '/wp-admin/' . $is_ms . 'plugin-editor.php' ||
140 + $_SERVER['PHP_SELF'] === '/wp-admin/' . $is_ms . 'theme-editor.php' ||
141 + $_SERVER['PHP_SELF'] === '/wp-admin/admin-ajax.php' ){
142 +
143 + add_action( 'init', create_function( '', 'new WPide();' ) );
144 +}
145 +
388 146
389 - //save a copy of the file and create a backup just in case
390 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
391 - $file_name = $root . stripslashes($_POST['filename']);
392 -
393 - //set backup filename
394 - $backup_path = 'backups' . preg_replace( "#\.php$#i", "_".date("Y-m-d-H").".php", $_POST['filename'] );
395 - $backup_path_full = plugin_dir_path(__FILE__) . $backup_path;
396 - //create backup directory if not there
397 - $new_file_info = pathinfo($backup_path_full);
398 - if (!$wp_filesystem->is_dir($new_file_info['dirname'])) wp_mkdir_p( $new_file_info['dirname'] ); //should use the filesytem api here but there isn't a comparable command right now
399 -
147 + add_filter("plugin_row_meta", 'wpide_dev_links', 10, 2);
400 148
401 -
402 - if ($is_php){
403 - //create the backup file adding some php to the file to enable direct restore
404 - global $current_user;
405 - get_currentuserinfo();
406 - $user_md5 = md5( serialize($current_user) );
407 -
408 - $restore_php = '<?php /* start WPide restore code */
409 - if ($_POST["restorewpnonce"] === "'. $user_md5.$_POST['_wpnonce'] .'"){
410 - if ( file_put_contents ( "'.$file_name.'" , preg_replace("#<\?php /\* start WPide(.*)end WPide restore code \*/ \?>#s", "", file_get_contents("'.$backup_path_full.'") ) ) ){
411 - echo "Your file has been restored, overwritting the recently edited file! \n\n The active editor still contains the broken or unwanted code. If you no longer need that content then close the tab and start fresh with the restored file.";
412 - }
413 - }else{
414 - echo "-1";
415 - }
416 - die();
417 - /* end WPide restore code */ ?>';
418 -
419 - file_put_contents ( $backup_path_full , $restore_php . file_get_contents($file_name) );
420 -
421 - }else{
422 - //do normal backup
423 - $wp_filesystem->copy( $file_name, $backup_path_full );
424 - }
425 -
426 - //save file
427 - if( $wp_filesystem->put_contents( $file_name, stripslashes($_POST['content'])) ) {
428 -
429 - //lets create an extra long nonce to make it less crackable
430 - global $current_user;
431 - get_currentuserinfo();
432 - $user_md5 = md5( serialize($current_user) );
433 -
434 - $result = "\"". $backup_path . ":::" . $user_md5 ."\"";
435 - }
436 -
437 - die($result); // this is required to return a proper result
149 + function wpide_dev_links($links, $file) {
150 + static $this_plugin;
151 +
152 + if (!$this_plugin) {
153 + $this_plugin = plugin_basename(__FILE__);
154 + }
155 +
156 + // check to make sure we are on the correct plugin
157 + if ($file === $this_plugin) {
158 + // the anchor tag and href to the URL we want. For a "Settings" link, this needs to be the url of your settings page
159 + $settings_link = '<a href="' . get_bloginfo('wpurl') . '/wp-admin/plugins.php?page=install-required-plugins" style="font-weight:bold;">Download and install V2 Development version</a>';
160 + // add the link to the list
161 + array_push($links, $settings_link);
162 + }
163 + return $links;
438 164 }
439 -
440 - public static function wpide_save_image() {
441 -
442 - $filennonce = split("::", $_POST["opt"]); //file::nonce
443 -
444 - //check the user has a valid nonce
445 - //we are checking two variations of the nonce, one as-is and another that we have removed a trailing zero from
446 - //this is to get around some sort of bug where a nonce generated on another page has a trailing zero and a nonce generated/checked here doesn't have the zero
447 - if (! wp_verify_nonce( $filennonce[1], 'wpide_image_edit' . $filennonce[0]) &&
448 - ! wp_verify_nonce( rtrim($filennonce[1], "0") , 'wpide_image_edit' . $filennonce[0])) {
449 - die('Security check'); //die because both checks failed
450 - }
451 - //check the user has the permissions
452 - if ( !current_user_can('edit_themes') )
453 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
454 -
455 -
456 - $_POST['content'] = base64_decode($_POST["data"]); //image content
457 - $_POST['filename'] = $filennonce[0]; //filename
458 -
459 - //setup wp_filesystem api
460 - global $wp_filesystem;
461 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
462 - $form_fields = null; // for now, but at some point the login info should be passed in here
463 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
464 - // no credentials yet, just produced a form for the user to fill in
465 - return true; // stop the normal page form from displaying
466 - }
467 - if ( ! WP_Filesystem($creds) )
468 - echo "Cannot initialise the WP file system API";
469 -
470 - //save a copy of the file and create a backup just in case
471 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
472 - $file_name = $root . stripslashes($_POST['filename']);
473 -
474 - //set backup filename
475 - $backup_path = 'backups' . preg_replace( "#\.php$#i", "_".date("Y-m-d-H").".php", $_POST['filename'] );
476 - $backup_path = plugin_dir_path(__FILE__) . $backup_path;
477 -
478 - //create backup directory if not there
479 - $new_file_info = pathinfo($backup_path);
480 - if (!$wp_filesystem->is_dir($new_file_info['dirname'])) wp_mkdir_p( $new_file_info['dirname'] ); //should use the filesytem api here but there isn't a comparable command right now
481 -
482 - //do backup
483 - $wp_filesystem->move( $file_name, $backup_path );
484 -
485 -
486 - //save file
487 - if( $wp_filesystem->put_contents( $file_name, $_POST['content']) ) {
488 - $result = "success";
489 - }
490 -
491 - if ($result == "success"){
492 - wp_die('<p>'.__('<strong>Image saved.</strong> <br />You may <a href="JavaScript:window.close();">close this window / tab</a>.').'</p>');
493 - }else{
494 - wp_die('<p>'.__('<strong>Problem saving image.</strong> <br /><a href="JavaScript:window.close();">Close this window / tab</a> and try editing the image again.').'</p>');
495 - }
496 - //print_r($_POST);
497 -
498 -
499 - //return;
500 - }
501 -
502 -
503 - public static function wpide_startup_check() {
504 - global $wp_filesystem, $wp_version;
505 -
506 - echo "\n\n\n\nWPIDE STARTUP CHECKS \n";
507 - echo "___________________ \n\n";
508 -
509 - //WordPress version
510 - if ($wp_version > 3){
511 - echo "WordPress version = " . $wp_version . "\n\n";
512 - }else{
513 - echo "WordPress version = " . $wp_version . " (which is too old to run WPide) \n\n";
514 - }
515 -
516 - //check the user has the permissions
517 - check_admin_referer('plugin-name-action_wpidenonce');
518 - if ( !current_user_can('edit_themes') )
519 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
520 -
521 - if ( defined( 'WPIDE_FS_METHOD_FORCED_ELSEWHERE' ) ){
522 - echo "WordPress filesystem API has been forced to use the " . WPIDE_FS_METHOD_FORCED . " method by another plugin/WordPress. \n\n";
523 - }
524 -
525 - //setup wp_filesystem api
526 - $wpide_filesystem_before = $wp_filesystem;
527 -
528 - $url = wp_nonce_url('admin.php?page=wpide','plugin-name-action_wpidenonce');
529 - $form_fields = null; // for now, but at some point the login info should be passed in here
530 - ob_start();
531 - if (false === ($creds = request_filesystem_credentials($url, FS_METHOD, false, false, $form_fields) ) ) {
532 - // if we get here, then we don't have credentials yet,
533 - // but have just produced a form for the user to fill in,
534 - // so stop processing for now
535 - //return true; // stop the normal page form from displaying
536 - }
537 - ob_end_clean();
538 - if ( ! WP_Filesystem($creds) ) {
539 -
540 - echo "There has been a problem initialising the filesystem API \n\n";
541 - echo "Filesystem API before this plugin ran: \n\n" . print_r($wpide_filesystem_before, true);
542 - echo "Filesystem API now: \n\n" . print_r($wp_filesystem, true);
543 -
544 - }
545 - unset($wpide_filesystem_before);
546 -
547 165
548 - $root = apply_filters( 'wpide_filesystem_root', WP_CONTENT_DIR );
549 - if ( isset($wp_filesystem) ){
550 -
551 - //Running webservers user and group
552 - echo "Web server user/group = " . getenv('APACHE_RUN_USER') . ":" . getenv('APACHE_RUN_GROUP') . "\n";
553 - //wp-content user and group
554 - echo "wp-content owner/group = " . $wp_filesystem->owner( $root ) . ":" . $wp_filesystem->group( $root ) . "\n\n";
555 -
556 -
557 - //check we can list wp-content files
558 - if( $wp_filesystem->exists( $root ) ){
559 -
560 - $files = $wp_filesystem->dirlist( $root );
561 - if ( count($files) > 0){
562 - echo "wp-content folder exists and contains ". count($files) ." files \n";
563 - }else{
564 - echo "wp-content folder exists but we cannot read it's contents \n";
565 - }
566 - }
567 -
568 - // $wp_filesystem->owner() $wp_filesystem->group() $wp_filesystem->is_writable() $wp_filesystem->is_readable()
569 - echo "\nUsing the ".$wp_filesystem->method." method of the WP filesystem API\n";
570 -
571 - //wp-content editable?
572 - echo "The wp-content folder ". ( $wp_filesystem->is_readable( $root )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
573 -
574 -
575 - //plugins folder editable
576 - echo "The wp-content/plugins folder ". ( $wp_filesystem->is_readable( $root."/plugins" )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root."/plugins" )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
577 -
578 166
579 - //themes folder editable
580 - echo "The wp-content/themes folder ". ( $wp_filesystem->is_readable( $root."/themes" )==1 ? "IS":"IS NOT" ) ." readable and ". ( $wp_filesystem->is_writable( $root."/themes" )==1 ? "IS":"IS NOT" ) ." writable by this method \n";
581 -
582 - }
583 -
584 - echo "___________________ \n\n\n\n";
585 -
586 - echo " If the file tree to the right is empty there is a possibility that your server permissions are not compatible with this plugin. \n The startup information above may shed some light on things. \n Paste that information into the support forum for further assistance.";
587 -
588 -
589 - die();
590 167
591 - }
592 -
593 -
594 -
595 -
596 - public function add_my_menu_page() {
597 - //add_menu_page("wpide", "wpide","edit_themes", "wpidesettings", array( &$this, 'my_menu_page') );
598 - add_menu_page('WPide', 'WPide', 'edit_themes', "wpide", array( &$this, 'my_menu_page' ));
599 - }
600 -
601 - public function my_menu_page() {
602 - if ( !current_user_can('edit_themes') )
603 - wp_die('<p>'.__('You do not have sufficient permissions to edit templates for this site. SORRY').'</p>');
604 -
605 - $app_url = get_bloginfo('url'); //need to make this https if we are currently looking on the site using https (even though https for admin might not be forced it can still cause issues)
606 - if (is_ssl()) $app_url = str_replace("http:", "https:", $app_url);
607 -
608 - ?>
609 - <script>
610 168
611 - var wpide_app_path = "<?php echo plugin_dir_url( __FILE__ ); ?>";
612 - //dont think this is needed any more.. var wpide_file_root_url = "<?php echo apply_filters("wpide_file_root_url", WP_CONTENT_URL );?>";
613 - var user_nonce_addition = '';
614 -
615 - function the_filetree() {
616 - jQuery('#wpide_file_browser').fileTree({ script: ajaxurl }, function(parent, file) {
617 -
618 - if ( jQuery(parent).hasClass("create_new") ){ //create new file/folder
619 - //to create a new item we need to know the name of it so show input
620 -
621 - var item = eval('('+file+')');
622 -
623 - //hide all inputs just incase one is selected
624 - jQuery(".new_item_inputs").hide();
625 - //show the input form for this
626 - jQuery("div.new_" + item.type).show();
627 - jQuery("div.new_" + item.type + " input[name='new_" + item.type + "']").focus();
628 - jQuery("div.new_" + item.type + " input[name='new_" + item.type + "']").attr("rel", file);
629 -
630 -
631 - }else if ( jQuery(".wpide_tab[rel='"+file+"']").length > 0) { //focus existing tab
632 - jQuery(".wpide_tab[sessionrel='"+ jQuery(".wpide_tab[rel='"+file+"']").attr("sessionrel") +"']").click();//focus the already open tab
633 - }else{ //open file
634 -
635 - var image_patern =new RegExp("(\.jpg|\.gif|\.png|\.bmp)");
636 - if ( image_patern.test(file) ){
637 - //it's an image so open it for editing
638 -
639 - //using modal+iframe
640 - if ("lets not" == "use the modal for now"){
641 -
642 - var NewDialog = jQuery('<div id="MenuDialog">\
643 - <iframe src="http://www.sumopaint.com/app/?key=ebcdaezjeojbfgih&target=<?php echo get_bloginfo('url') . "?action=wpide_image_save";?>&url=<?php echo get_bloginfo('url') . "/wp-content";?>' + file + '&title=Edit image&service=Save back to WPide" width="100%" height="600px"> </iframe>\
644 - </div>');
645 - NewDialog.dialog({
646 - modal: true,
647 - title: "title",
648 - show: 'clip',
649 - hide: 'clip',
650 - width:'800',
651 - height:'600'
652 - });
653 -
654 - }else{ //open in new tab/window
655 -
656 - var data = { action: 'wpide_image_edit_key', file: file, _wpnonce: jQuery('#_wpnonce').val(), _wp_http_referer: jQuery('#_wp_http_referer').val() };
657 - var image_data = '';
658 - jQuery.ajaxSetup({async:false}); //we need to wait until we get the response before opening the window
659 - jQuery.post(ajaxurl, data, function(response) {
660 -
661 - //with the response (which is a nonce), build the json data to pass to the image editor. The edit key (nonce) is only valid to edit this image
662 - image_data = file+'::'+response;
663 -
664 - });
665 -
666 - jQuery.ajaxSetup({async:true});//enable async again
667 -
668 -
669 - window.open('http://www.sumopaint.com/app/?key=ebcdaezjeojbfgih&url=<?php echo $app_url. "/wp-content";?>' + file + '&opt=' + image_data + '&title=Edit image&service=Save back to WPide&target=<?php echo urlencode( $app_url . "/wp-admin/admin.php?wpide_save_image=yes" ) ;?>');
670 -
671 - }
672 -
673 - }else{
674 - jQuery(parent).addClass('wait');
675 -
676 - wpide_set_file_contents(file, function(){
677 -
678 - //once file loaded remove the wait class/indicator
679 - jQuery(parent).removeClass('wait');
680 -
681 - });
682 -
683 - jQuery('#filename').val(file);
684 - }
685 -
686 - }
687 -
688 - });
689 - }
690 -
691 -
692 -
693 - jQuery(document).ready(function($) {
694 -
695 - $("#fancyeditordiv").css("height", ($('body').height()-120) + 'px' );
696 -
697 - // Handler for .ready() called.
698 - the_filetree() ;
699 -
700 - //inialise the color assist
701 - $("#wpide_color_assist img").ImageColorPicker({
702 - afterColorSelected: function(event, color){
703 - jQuery("#wpide_color_assist_input").val(color);
704 - }
705 - });
706 - $("#wpide_color_assist").hide(); //hide it until it's needed
707 -
708 - $("#wpide_color_assist_send").click(function(e){
709 - e.preventDefault();
710 - editor.insert( jQuery("#wpide_color_assist_input").val().replace('#', '') );
711 -
712 - $("#wpide_color_assist").hide(); //hide it until it's needed again
713 - });
714 -
715 - $(".close_color_picker a").click(function(e){
716 - e.preventDefault();
717 - $("#wpide_color_assist").hide(); //hide it until it's needed again
718 - });
719 -
720 - $("#wpide_toolbar_buttons").on('click', "a.restore", function(e){
721 - e.preventDefault();
722 - var file_path = jQuery(".wpide_tab.active", "#wpide_toolbar").data( "backup" );
723 -
724 - jQuery("#wpide_message").hide(); //might be shortly after a save so a message may be showing, which we don't need
725 - jQuery("#wpide_message").html('<span><strong>File available for restore</strong><p> ' + file_path + '</p><a class="button red restore now" href="'+ wpide_app_path + file_path +'">Restore this file now &#10012;</a><a class="button restore cancel" href="#">Cancel &#10007;</a><br /><em class="note"><strong>note: </strong>You can browse all file backups if you navigate to the backups folder (plugins/WPide/backups/..) using the filetree.</em></span>');
726 - jQuery("#wpide_message").show();
727 - });
728 - $("#wpide_toolbar_buttons").on('click', "a.restore.now", function(e){
729 - e.preventDefault();
730 -
731 - var data = { restorewpnonce: user_nonce_addition + jQuery('#_wpnonce').val() };
732 - jQuery.post( wpide_app_path + jQuery(".wpide_tab.active", "#wpide_toolbar").data( "backup" )
733 - , data, function(response) {
734 -
735 - if (response == -1){
736 - alert("Problem restoring file.");
737 - }else{
738 - alert( response);
739 - jQuery("#wpide_message").hide();
740 - }
741 -
742 - });
743 -
744 - });
745 - $("#wpide_toolbar_buttons" ).on('click', "a.cancel", function(e){
746 - e.preventDefault();
747 -
748 - jQuery("#wpide_message").hide(); //might be shortly after a save so a message may be showing, which we don't need
749 - });
750 -
751 -
752 - });
753 - </script>
754 -
755 169
756 -
757 - <div id="poststuff" class="metabox-holder has-right-sidebar">
758 -
759 - <div id="side-info-column" class="inner-sidebar">
760 -
761 - <div id="wpide_info">
762 - <div id="wpide_info_content"></div>
763 - </div>
764 - <br style="clear:both;" />
765 - <div id="wpide_color_assist">
766 - <div class="close_color_picker"><a href="close-color-picker">x</a></div>
767 - <h3>Colour Assist</h3>
768 - <img src='<?php echo plugins_url("images/color-wheel.png", __FILE__ ); ?>' />
769 - <input type="button" class="button" id="wpide_color_assist_send" value="&lt; Send to editor" />
770 - <input type="text" id="wpide_color_assist_input" name="wpide_color_assist_input" value="" />
771 -
772 - </div>
773 -
774 -
775 -
776 - <div id="submitdiv" class="postbox ">
777 - <h3 class="hndle"><span>Files</span></h3>
778 - <div class="inside">
779 - <div class="submitbox" id="submitpost">
780 - <div id="minor-publishing">
781 - </div>
782 - <div id="major-publishing-actions">
783 - <div id="wpide_file_browser"></div>
784 - <br style="clear:both;" />
785 - <div class="new_file new_item_inputs">
786 - <label for="new_folder">File name</label><input class="has_data" name="new_file" type="text" rel="" value="" placeholder="Filename.ext" />
787 - <a href="#" id="wpide_create_new_file" class="button-primary">CREATE</a>
788 - </div>
789 - <div class="new_directory new_item_inputs">
790 - <label for="new_directory">Directory name</label><input class="has_data" name="new_directory" type="text" rel="" value="" placeholder="Filename.ext" />
791 - <a href="#" id="wpide_create_new_directory" class="button-primary">CREATE</a>
792 - </div>
793 - <div class="clear"></div>
794 - </div>
795 - </div>
796 - </div>
797 - </div>
798 -
799 -
800 - </div>
801 -
802 - <div id="post-body">
803 - <div id="wpide_toolbar" class="quicktags-toolbar">
804 - <div id="wpide_toolbar_tabs"> </div>
805 - <div id="dialog_window_minimized_container"></div>
806 - </div>
807 -
808 - <div id="wpide_toolbar_buttons">
809 - <div id="wpide_message"></div>
810 - <a class="button restore" style="display:none;" title="Restore the active tab" href="#">Restore &#10012;</a>
811 -
812 - </div>
813 -
814 -
815 - <div id='fancyeditordiv'></div>
816 -
817 - <form id="wpide_save_container" action="" method="get">
818 - <div id="wpide_footer_message"></div>
819 - <div id="wpide_footer_message_last_saved"></div>
820 - <div id="wpide_footer_message_unsaved"></div>
821 - <a href="#" id="wpide_save" alt="Keyboard shortcut to save [Ctrl/Cmd + S]" title="Keyboard shortcut to save [Ctrl/Cmd + S]" class="button-primary">SAVE
822 - FILE</a>
823 - <input type="hidden" id="filename" name="filename" value="" />
824 - <?php
825 - if ( function_exists('wp_nonce_field') )
826 - wp_nonce_field('plugin-name-action_wpidenonce');
827 - ?>
828 - </form>
829 - </div>
830 -
831 -
832 -
833 - </div>
834 -
835 - <?php
836 - }
837 170
838 -}
171 +/**
172 + * Include the TGM_Plugin_Activation class.
173 + */
174 +require_once dirname( __FILE__ ) . '/tgm-plugin-activation/class-tgm-plugin-activation.php';
839 175
840 -$wpide = new wpide();
176 +add_action( 'tgmpa_register', 'wpide_run_dev' );
177 +/**
178 + * Register the required plugins for this theme.
179 + *
180 + * In this example, we register two plugins - one included with the TGMPA library
181 + * and one from the .org repo.
182 + *
183 + * The variable passed to tgmpa_register_plugins() should be an array of plugin
184 + * arrays.
185 + *
186 + * This function is hooked into tgmpa_init, which is fired within the
187 + * TGM_Plugin_Activation class constructor.
188 + */
189 +function wpide_run_dev() {
841 190
842 -endif; // class_exists check
191 + /**
192 + * Array of plugin arrays. Required keys are name and slug.
193 + * If the source is NOT from the .org repo, then source is also required.
194 + */
195 + $plugins = array(
843 196
197 + // This is an example of how to include a plugin from the WordPress Plugin Repository
198 + array(
199 + 'name' => 'WPide V2 Dev',
200 + 'slug' => 'WPideV2',
201 + 'version' => '2.0',
202 + 'required' => false,
203 + 'external_url' => 'https://github.com/WPsites/WPide/tree/v2dev',
204 + 'source' => 'https://github.com/WPsites/WPide/zipball/v2dev',
205 + ),
206 +
207 + );
208 +
209 + // Change this to your theme text domain, used for internationalising strings
210 + $theme_text_domain = 'tgmpa';
211 +
212 + /**
213 + * Array of configuration settings. Amend each line as needed.
214 + * If you want the default strings to be available under your own theme domain,
215 + * leave the strings uncommented.
216 + * Some of the strings are added into a sprintf, so see the comments at the
217 + * end of each line for what each argument will be.
218 + */
219 + $config = array(
220 + 'domain' => $theme_text_domain, // Text domain - likely want to be the same as your theme.
221 + 'default_path' => '', // Default absolute path to pre-packaged plugins
222 + 'parent_menu_slug' => 'plugins.php', // Default parent menu slug
223 + 'parent_url_slug' => 'plugins.php', // Default parent URL slug
224 + 'menu' => 'install-required-plugins', // Menu slug
225 + 'has_notices' => true, // Show admin notices or not
226 + 'is_automatic' => true, // Automatically activate plugins after installation or not
227 + 'message' => '', // Message to output right before the plugins table
228 + 'strings' => array(
229 + 'page_title' => __( 'Install Suggested Plugins', $theme_text_domain ),
230 + 'menu_title' => __( 'Install Plugins', $theme_text_domain ),
231 + 'installing' => __( 'Installing Plugin: %s', $theme_text_domain ), // %1$s = plugin name
232 + 'oops' => __( 'Something went wrong with the plugin API.', $theme_text_domain ),
233 + 'notice_can_install_required' => _n_noop( 'This theme requires the following plugin: %1$s.', 'This theme requires the following plugins: %1$s.' ), // %1$s = plugin name(s)
234 + 'notice_can_install_recommended' => _n_noop( 'The V2 Development branch of WPide is available for testing - With new features such as multi tab editing.<br />Word of warning: this is the cutting edge development version which could contain bugs so use at your own risk! ', 'WPide recommends the following plugins: %1$s.' ), // %1$s = plugin name(s)
235 + 'notice_cannot_install' => _n_noop( 'Sorry, but you do not have the correct permissions to install the %s plugin. Contact the administrator of this site for help on getting the plugin installed.', 'Sorry, but you do not have the correct permissions to install the %s plugins. Contact the administrator of this site for help on getting the plugins installed.' ), // %1$s = plugin name(s)
236 + 'notice_can_activate_required' => _n_noop( 'The following required plugin is currently inactive: %1$s.', 'The following required plugins are currently inactive: %1$s.' ), // %1$s = plugin name(s)
237 + 'notice_can_activate_recommended' => _n_noop( 'The following recommended plugin is currently inactive: %1$s.', 'The following recommended plugins are currently inactive: %1$s.' ), // %1$s = plugin name(s)
238 + 'notice_cannot_activate' => _n_noop( 'Sorry, but you do not have the correct permissions to activate the %s plugin. Contact the administrator of this site for help on getting the plugin activated.', 'Sorry, but you do not have the correct permissions to activate the %s plugins. Contact the administrator of this site for help on getting the plugins activated.' ), // %1$s = plugin name(s)
239 + 'notice_ask_to_update' => _n_noop( 'The following plugin needs to be updated to its latest version to ensure maximum compatibility with this theme: %1$s.', 'The following plugins need to be updated to their latest version to ensure maximum compatibility with this theme: %1$s.' ), // %1$s = plugin name(s)
240 + 'notice_cannot_update' => _n_noop( 'Sorry, but you do not have the correct permissions to update the %s plugin. Contact the administrator of this site for help on getting the plugin updated.', 'Sorry, but you do not have the correct permissions to update the %s plugins. Contact the administrator of this site for help on getting the plugins updated.' ), // %1$s = plugin name(s)
241 + 'install_link' => _n_noop( 'Begin installing the development version of WPide', 'Begin installing plugins' ),
242 + 'activate_link' => _n_noop( 'Activate WPide V2 Dev', 'Activate installed plugins' ),
243 + 'return' => __( 'Return to Suggested Plugins Installer', $theme_text_domain ),
244 + 'plugin_activated' => __( 'Plugin activated successfully.', $theme_text_domain ),
245 + 'complete' => __( 'All plugins installed and activated successfully. %s', $theme_text_domain ) // %1$s = dashboard link
246 + )
247 + );
248 +
249 + tgmpa( $plugins, $config );
250 +
251 +}
844 252 ?>