/var/www/html_it/wp-content/plugins/loco-translate/src/ajax/FsConnectController.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php
/**
 * Ajax service that provides remote server authentication for file system *write* operations
 */
class Loco_ajax_FsConnectController extends Loco_mvc_AjaxController {
    
    
/**
     * @var Loco_api_WordPressFileSystem 
     */
    
private $api;
    
    
    
/**
     * @param Loco_fs_File existing file path (must exist)
     * @return bool
     */
    
private function authorizeDeleteLoco_fs_File $file ){
        
$files = new Loco_fs_Siblings($file);
        
// require remote authentication if at least one dependant file is not deletable directly
        
foreach( $files->expand() as $file ){
            if( ! 
$this->api->authorizeDelete($file) ){
                return 
false;
            }
        }
        
// else no dependants failed deletable test
        
return true;
    }
    
    
    
/**
     * @param Loco_fs_File file being moved (must exist)
     * @param Loco_fs_File target path (should not exist)
     * @return bool
     */
    
private function authorizeMoveLoco_fs_File $source, ?Loco_fs_File $target null ){
        return 
$this->api->authorizeMove($source,$target);
    }


    
/**
     * @param Loco_fs_File $file new file path (should not exist)
     * @return bool
     */
    
private function authorizeCreateLoco_fs_File $file ){
        return 
$this->api->authorizeCreate($file);
    }


    
/**
     * @param Loco_fs_File $file path to update (should exist)
     * @return bool
     */
    
private function authorizeUpdateLoco_fs_File $file ){
        if( ! 
$this->api->authorizeUpdate($file) ){
            return 
false;
        }
        
// if backups are enabled, we need to be able to create new files too (i.e. update parent directory)
        
if( Loco_data_Settings::get()->num_backups && ! $this->api->authorizeCopy($file) ){
            return 
false;
        }
        
// updating file will also recompile binary, which may or may not exist
        
$files = new Loco_fs_Siblings($file);
        
$mofile $files->getBinary();
        if( 
$mofile && ! $this->api->authorizeSave($mofile) ){
            return 
false;
        }
        
// else no dependants to update
        
return true;
    }


    
/**
     * @param Loco_fs_File $file path which may exist (update it) or may not (create it)
     * @return bool
     */
    
private function authorizeUploadLoco_fs_File $file ){
        if( 
$file->exists() ){
            return 
$this->api->authorizeUpdate($file);
        }
        else {
            return 
$this->api->authorizeCreate($file);
        }
    }


    
/**
     * {@inheritdoc}
     */
    
public function render(){
        
// establish operation being authorized (create,delete,etc..)
        
$post $this->validate();
        
$type $post->auth;
        
$func 'authorize'.ucfirst($type);
        
$auth = [ $this$func ];
        if( ! 
is_callable($auth) ){
            throw new 
Loco_error_Exception('Unexpected file operation');
        }
        
// all auth methods require at least one file argument
        
$file = new Loco_fs_File$post->path );
        
$base loco_constant('WP_CONTENT_DIR');
        
$file->normalize($base);
        
$args = [$file];
        
// some auth methods also require a destination/target (move,copy,etc..)
        
if( $dest $post->dest ){
            
$file = new Loco_fs_File($dest);
            
$file->normalize($base);
            
$args[] = $file;
        }
        
// call auth method and respond with status and prompt HTML if connect required
        
try {
            
$this->api = new Loco_api_WordPressFileSystem;
            if( 
call_user_func_array($auth,$args) ){
                
$this->set'authed'true );
                
$this->set'valid'$this->api->getOutputCredentials() );
                
$this->set'creds'$this->api->getInputCredentials() );
                
$this->set'method'$this->api->getFileSystem()->method );
                
$this->set'success'__('Connected to remote file system','loco-translate') );
                
// warning when writing to this location is risky (overwrites during wp update)
                
if( Loco_data_Settings::get()->fs_protect && $file->getUpdateType() ){
                    if( 
'create' === $type ){
                        
$message __('This file may be overwritten or deleted when you update WordPress','loco-translate');
                    }
                    else if( 
'delete' === $type ){
                        
$message __('This directory is managed by WordPress, be careful what you delete','loco-translate');
                    }
                    else if( 
'move' === $type ){
                        
$message __('This directory is managed by WordPress. Removed files may be restored during updates','loco-translate');
                    }
                    else {
                        
$message __('Changes to this file may be overwritten or deleted when you update WordPress','loco-translate');
                    }
                    
$this->set('warning',$message);
                }
            }
            else {
                
$this->set'authed'false );
                
// HTML form should be set when authorization failed
                
$html $this->api->getForm();
                if( 
'' === $html || ! is_string($html) ){
                    
// this is the only non-error case where form will not be set.
                    
if( 'direct' === loco_constant('FS_METHOD') ){
                        
$html 'Remote connections are prevented by your WordPress configuration. Direct access only.';
                    }
                    
// else an unknown error occurred when fetching output from request_filesystem_credentials
                    
else {
                        
$html 'Failed to get credentials form';
                    }
                    
// displaying error after clicking "connect" to avoid unnecessary warnings when operation may not be required
                    
$html '<form><h2>Connection problem</h2><p>'.$html.'.</p></form>';
                }
                
$this->set'prompt'$html );
                
// supporting text based on file operation type explains why auth is required
                
if( 'create' === $type ){
                    
$message __('Creating this file requires permission','loco-translate');
                }
                else if( 
'delete' === $type ){
                    
$message __('Deleting this file requires permission','loco-translate');
                }
                else if( 
'move' === $type ){
                    
$message __('This move operation requires permission','loco-translate');
                }
                else {
                    
$message __('Saving this file requires permission','loco-translate');
                }
                
// message is printed before default text, so needs delimiting.
                
$this->set('message',$message.'.');
            }
        }
        catch( 
Loco_error_WriteException $e ){
            
$this->set('authed'false );
            
$this->set('reason'$e->getMessage() );
        }

        return 
parent::render();
    }


}