dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxEditor.class.php
Go to the documentation of this file.
1<?php
2namespace dbx\dbxEditor;
3
4
5
6class dbxEditor {
7
15 private function editor_form(): \dbxForm {
16 dbx()->get_system_obj('dbxForm');
17 $form = new \dbxForm();
18 $form->init('dbx-editor-file');
19 $form->_msg_info = '';
20 $form->set_form_help_enabled(false);
21 return $form;
22 }
23
29 private function mutation_state(): array {
30 $form = $this->editor_form();
31 return array(
32 'submitted' => (bool)$form->submit(),
33 'security' => $form->get_security_data(),
34 );
35 }
36
42 private function json_result(bool $ok, string $msg, array $security): void {
43 header('Content-Type: application/json; charset=utf-8');
44 echo json_encode(array(
45 'ok' => $ok ? 1 : 0,
46 'msg' => $msg,
47 'security' => $security,
48 ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
49 exit;
50 }
51
52 public function run() {
53
54 $modul = dbx()->get_system_var('dbx_modul');
55 $run1 = dbx()->get_modul_var('dbx_run1','dbx');
56 $file = dbx()->get_modul_var('file','none','*');
57 $base = dbx()->get_base_dir();
58 $ajax = dbx()->get_system_var('dbx_ajax',0,'int');
59 $xedit = dbx()->get_system_var('dbx_edit',0,'int');
60 dbx()->set_system_var('dbx_edit',0);
61
62 $content='';
63 $mutation = null;
64
65 if (in_array($run1, array('save', 'delete', 'rename', 'copy'), true)) {
66 $mutation = $this->mutation_state();
67 if (!$mutation['submitted']) {
68 dbx()->sys_msg(
69 'security',
70 'dbxEditor',
71 $run1,
72 'Editor-Mutation ohne gueltigen dbxForm-Token abgewiesen',
73 'ip=' . (string)($_SERVER['REMOTE_ADDR'] ?? '')
74 );
75 $this->json_result(false, 'security_check_failed', $mutation['security']);
76 }
77 }
78
79 switch ($run1) {
80
81 case 'tree':
82 $content = $this->render_tree($base);
83 break;
84
85 case 'edit':
86
87 // 🔒 Sicherheit
88 if (!$this->is_valid_file($file)) {
89 return "invalid file";
90 }
91
92 $full = $base.$file;
93
94 if (!file_exists($full)) {
95 return "file not found ($file)";
96 }
97
98 $txt = file_get_contents($full);
99 $data['file']=$file;
100 $data['txt'] = dbx()->norep(htmlspecialchars($txt, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'));
101 $security = $this->editor_form()->get_security_data();
102 $data['security_name'] = htmlspecialchars($security['name'], ENT_QUOTES, 'UTF-8');
103 $data['security_value'] = htmlspecialchars($security['value'], ENT_QUOTES, 'UTF-8');
104
105 $oTPL = dbx()->get_system_obj('dbxTPL');
106 $content = $oTPL->get_tpl('dbxEditor|editor', $data);
107
108 break;
109
110
111 case 'save':
112
113 if (!$this->is_valid_file($file)) {
114 $this->json_result(false, 'invalid_file', $mutation['security']);
115 }
116
117 $full = $base.$file;
118 // Der Quelltext darf PHP, HTML, JavaScript und CSS enthalten. Nur
119 // der Dateipfad und der dbxForm-Token werden als Eingaben geprüft.
120 $data = $_POST['content'] ?? '';
121
122 if (file_put_contents($full, $data) === false) {
123 $this->json_result(false, 'save_failed', $mutation['security']);
124 }
125 $this->clear_dd_file_cache($file);
126 $this->json_result(true, 'saved', $mutation['security']);
127
128 case 'delete':
129 $content="delete ($base) ($file) ajax=($ajax)";
130 dbx()->debug($content);
131
132 if (!$this->is_valid_file($file)) {
133 $this->json_result(false, 'invalid file', $mutation['security']);
134 }
135
136 $full = $base.$file;
137
138 if (!file_exists($full)) {
139 $this->json_result(false, 'file not found', $mutation['security']);
140 }
141
142 if (!unlink($full)) {
143 $this->json_result(false, 'delete failed', $mutation['security']);
144 }
145
146 $this->clear_dd_file_cache($file);
147 $this->json_result(true, 'deleted', $mutation['security']);
148
149
150 break;
151
152 case 'rename':
153
154 $old = dbx()->get_modul_var('old','','alphanum+/');
155 $new = dbx()->get_modul_var('new','','alphanum+/');
156
157 if (!$this->is_valid_file($old) || !$this->is_valid_file($new)) {
158 $this->json_result(false, 'invalid file', $mutation['security']);
159 }
160
161 $fullOld = $base.$old;
162 $fullNew = $base.$new;
163
164 if (!file_exists($fullOld)) {
165 $this->json_result(false, 'source not found', $mutation['security']);
166 }
167
168 if (file_exists($fullNew)) {
169 $this->json_result(false, 'target exists', $mutation['security']);
170 }
171
172 if (!rename($fullOld, $fullNew)) {
173 $this->json_result(false, 'rename failed', $mutation['security']);
174 }
175 $this->clear_dd_file_cache($old);
176 $this->clear_dd_file_cache($new);
177 $this->json_result(true, 'renamed', $mutation['security']);
178
179 break;
180
181 case 'copy':
182
183 $old = dbx()->get_modul_var('old','','alphanum+/.');
184 $new = dbx()->get_modul_var('new','','alphanum+/.');
185
186 if (!$this->is_valid_file($old) || !$this->is_valid_file($new)) {
187 $this->json_result(false, 'invalid file', $mutation['security']);
188 }
189
190 $fullOld = $base . $old;
191 $fullNew = $base . $new;
192
193 if (!file_exists($fullOld)) {
194 $this->json_result(false, 'source not found', $mutation['security']);
195 }
196
197 if (file_exists($fullNew)) {
198 $this->json_result(false, 'target exists', $mutation['security']);
199 }
200
201 if (!copy($fullOld, $fullNew)) {
202 $this->json_result(false, 'copy failed', $mutation['security']);
203 }
204
205 $this->clear_dd_file_cache($new);
206 $this->json_result(true, 'copied', $mutation['security']);
207
208 break;
209
210
211 default:
212 $oTPL=dbx()->get_system_obj('dbxTPL');
213 $msg['msg']="Modul=($modul) Action=($run1) is undef.";
214 $content=$oTPL->get_tpl('dbx|alert-warning',$msg);
215 } // switch
216 dbx()->set_system_var('dbx_edit',$xedit);
217 return $content;
218 }
219
220 private function clear_dd_file_cache($file) {
221 $file = str_replace('\\', '/', (string)$file);
222
223 if (preg_match('#(?:^|/)dbx/modules/([^/]+)/dd/([^/]+)\.dd\.php$#', $file, $match)) {
224 $oDD = dbx()->get_system_obj('dbxDD');
225 $oDD->clear_dd_cache($match[1] . '|' . $match[2]);
226 }
227 }
228
229 private function is_valid_file($file) {
230 if (strpos($file,'..') !== false) return false;
231
232 $ext = pathinfo($file, PATHINFO_EXTENSION);
233 return in_array($ext, ['css','htm','js','php']);
234 }
235
236 private function render_tree($dir, $base = null) {
237
238 if ($base === null) $base = $dir;
239
240 $html = '<ul>';
241
242 $items = scandir($dir);
243
244 foreach ($items as $item) {
245
246 if ($item === '.' || $item === '..') continue;
247
248 $full = $dir . '/' . $item;
249 $rel = str_replace($base . '/', '', $full);
250
251 if (is_dir($full)) {
252
253 $html .= '<li>';
254 $html .= '<span>' . $item . '</span>';
255 $html .= $this->render_tree($full, $base);
256 $html .= '</li>';
257
258 } else {
259
260 if (!$this->is_valid_file($item)) continue;
261
262 $html .= '<li>';
263 $html .= '<a href="?dbx_modul=dbxEditor&dbx_run1=edit&file=' . urlencode($rel) . '">';
264 $html .= $item;
265 $html .= '</a>';
266 $html .= '</li>';
267 }
268 }
269
270 $html .= '</ul>';
271
272 return $html;
273 }
274
275
276
277
278}
$_SERVER['REQUEST_METHOD']
exit
Definition index.php:146
if( $demoId<=0) foreach(array('create_date', 'create_uid', 'update_date', 'update_uid', 'owner',) as $systemField) $items
DBX schema administration.