Mercurial
comparison .cms/mod/admin.mod.php @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 <?php | |
2 | |
3 $cms["modules"]["admin.mod.php"] = array( | |
4 "name" => "admin_module_name", | |
5 "description" => "admin_module_description", | |
6 "files" => array( | |
7 ".cms/admin.cms/html.php", | |
8 ".cms/mod/admin.mod.php", | |
9 ".cms/js/admin.js", | |
10 ".cms/css/admin.css", | |
11 ".cms/lang/ru_RU.UTF-8/admin.mod.php", | |
12 ".cms/lang/en_US.UTF-8/admin.mod.php", | |
13 ".cms/lang/uk_UA.UTF-8/admin.mod.php", | |
14 ), | |
15 ); | |
16 | |
17 // Return if module disabled | |
18 if ( ! empty( $cms["config"]["admin.mod.php"]["disabled"] ) ) { | |
19 | |
20 return; | |
21 | |
22 } else { | |
23 | |
24 if ( ! empty( $cms["config"]["locale"] ) ) { | |
25 $translit = "{$cms['cms_dir']}/lang/{$cms['config']['locale']}/translit.php"; | |
26 if ( is_file( $translit ) ) { | |
27 include_once( $translit ); | |
28 } | |
29 } | |
30 | |
31 // on install admin_url == base_path | |
32 if ( ! isset( $cms["config"]["admin.mod.php"]["admin_url"] ) ) { | |
33 $cms["config"]["admin.mod.php"]["admin_url"] = ""; | |
34 } | |
35 | |
36 | |
37 if ( empty( $cms["config"]["admin.mod.php"]["api_url"] ) ) { | |
38 $cms["config"]["admin.mod.php"]["api_url"] = "api" . cms_uid(); | |
39 //cms_save_config(); | |
40 } | |
41 | |
42 if ( empty( $cms["config"]["admin.mod.php"]["cron_url"] ) ) { | |
43 $cms["config"]["admin.mod.php"]["cron_url"] = "cron" . cms_uid(); | |
44 //cms_save_config(); | |
45 } | |
46 | |
47 if ( ! empty( $cms["config"]["admin.mod.php"]["clear_cache"] ) ) { | |
48 hook_add_fn( "template", "cms_admin_clear_cache", 4 ); | |
49 } | |
50 | |
51 | |
52 $cms["urls"]["^{$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}$"] = "admin"; | |
53 | |
54 $cms["urls"]["^{$cms['base_path']}{$cms['config']['admin.mod.php']['api_url']}$"] = "api"; | |
55 | |
56 $cms["urls"]["^{$cms['base_path']}{$cms['config']['admin.mod.php']['cron_url']}$"] = "cron"; | |
57 | |
58 // Authorized admin and not authorized admin | |
59 if ( is_admin() ) { | |
60 hook_add_fn( "admin_header", "cms_admin_admin_header" ); | |
61 hook_add_fn( "api", "cms_admin_api" ); | |
62 } | |
63 hook_add_fn( "admin", "cms_admin_admin", 9999 ); | |
64 | |
65 } | |
66 | |
67 | |
68 function cms_admin_clear_cache() { | |
69 global $cms; | |
70 header( "Clear-Site-Data: \"cache\"" ); | |
71 unset( $cms["config"]["admin.mod.php"]["clear_cache"] ); | |
72 cms_save_config(); | |
73 } | |
74 | |
75 | |
76 function cms_admin_admin_header() { | |
77 global $cms; | |
78 echo "<script src='{$cms['base_path']}js/admin.js'></script>"; | |
79 } | |
80 | |
81 | |
82 function is_admin() { | |
83 global $cms; | |
84 return isset( $_COOKIE["sess"] ) && isset( $cms["config"]["logged"][ $_COOKIE["sess"] ] ); | |
85 } | |
86 | |
87 | |
88 // Боковое меню в админке | |
89 function cms_admin_menu() { | |
90 global $cms; | |
91 | |
92 // Сохраненные настройки боковой панели: $cms["config"]["admin_sections"] | |
93 // Текущее состояние настроек формируемое динамически: $cms["admin_sections"] | |
94 if ( ! empty( $cms["config"]["admin_sections"] ) ) { | |
95 $cms["admin_sections"] = $cms["config"]["admin_sections"]; | |
96 } else { | |
97 $cms["admin_sections"] = array(); | |
98 } | |
99 | |
100 // Настройки пунктов сохраняются в настройках модулей, а не в секции, | |
101 // чтобы отключение модуля прятало пункт из боковой панели | |
102 foreach( $cms["config"] as $mod => $mod_cfg ) { | |
103 if ( substr( $mod, -8, 8 ) === ".mod.php" && empty( $mod_cfg["disabled"] ) && isset( $mod_cfg["menu"] ) ) { | |
104 foreach( $mod_cfg["menu"] as $menu => $menu_cfg ) { | |
105 $section = $menu_cfg["section"]; | |
106 $menu_cfg["module"] = $mod; // для последующей локализации | |
107 $cms["admin_sections"][$section]["items"][$menu] = $menu_cfg; | |
108 | |
109 // Локализация заголовка секции | |
110 $locale = $cms["config"]["locale"]; | |
111 if ( ! isset( $cms["admin_sections"][$section]["title"] ) && isset( $cms["lang"][$mod][$locale][$section] ) ) { | |
112 $cms["admin_sections"][$section]["title"] = $cms["lang"][$mod][$locale][$section]; | |
113 } | |
114 | |
115 // default section sort | |
116 if ( isset( $menu_cfg["section_sort"] ) && ! isset( $cms["admin_sections"][$section]["sort"] ) ) { | |
117 $cms["admin_sections"][$section]["sort"] = $menu_cfg["section_sort"]; | |
118 } | |
119 } | |
120 } | |
121 } | |
122 // Затем эти данные используются в .cms/admin.cms/html.php | |
123 | |
124 // Sort & Translate | |
125 $default_sort = array( | |
126 "content" => 100, | |
127 "settings" => 1000, | |
128 ); | |
129 foreach( $cms["admin_sections"] as $section => $sec_conf ) { | |
130 // Сортировка. Установить порядковый номер если не установлен. | |
131 if ( ! isset( $cms["admin_sections"][$section]["sort"] ) ) { | |
132 if ( isset( $default_sort[$section] ) ) { | |
133 $cms["admin_sections"][$section]["sort"] = $default_sort[$section]; | |
134 } else { | |
135 $cms["admin_sections"][$section]["sort"] = 500; | |
136 } | |
137 } | |
138 | |
139 // translate | |
140 if ( ! isset( $cms["admin_sections"][$section]["title"] ) ) { | |
141 $cms["admin_sections"][$section]["title"] = __( $section ); | |
142 } | |
143 } | |
144 | |
145 // Sort sections | |
146 cms_asort( $cms["admin_sections"] ); | |
147 | |
148 // Sort items inside sections | |
149 foreach( $cms["admin_sections"] as $section_name => $section ) { | |
150 cms_asort( $cms["admin_sections"][$section_name]["items"] ); | |
151 } | |
152 } | |
153 | |
154 function cms_admin_admin() { | |
155 global $cms; | |
156 $cms["template"] = "admin.cms"; | |
157 $cms["status"] = "200"; | |
158 $cms["hooks"]["write"]["disabled"] = true; | |
159 | |
160 // Not required code if not authorized | |
161 if ( ! is_admin() ) return; | |
162 | |
163 $conf = $cms["config"]["admin.mod.php"]["menu"]["auth"]; | |
164 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) { | |
165 | |
166 // Save settings | |
167 if ( ! empty( $_POST["change_admin_login"] ) ) { | |
168 $login = trim( $_POST["admin_login"] ); | |
169 $password = trim( $_POST["admin_password"] ); | |
170 $cms["config"]["admin.mod.php"]["admin_login"] = $login; | |
171 $cms["config"]["admin.mod.php"]["admin_password"] = $password; | |
172 $cms["config"]["admin.mod.php"]["admin_url"] = trim( $_POST["admin_url"] ); | |
173 cms_save_config(); | |
174 header( "Location: {$cms['base_path']}{$cms['config']['admin.mod.php']['admin_url']}" ); | |
175 $cms["hooks"]["admin"]["next"] = ""; // Предотвратить выдачу админки | |
176 return; | |
177 } | |
178 | |
179 $rows = ""; | |
180 foreach ( $cms["config"]["logged"] as $login => $attr ) { | |
181 if ( $login === $_COOKIE["sess"] ) { | |
182 $current = "class=current"; | |
183 } else { | |
184 $current = ""; | |
185 } | |
186 $rows .= " | |
187 <div {$current}> | |
188 <div class=del-sess data-login='{$login}'></div> | |
189 <div class=date>{$attr['date']}</div> | |
190 <div class=ip>{$attr['ip']}</div> | |
191 <div class=agent>{$attr['user_agent']}</div> | |
192 </div>"; | |
193 } | |
194 | |
195 $logouts = ""; | |
196 if ( ! empty( $cms["config"]["logouted"] ) ) { | |
197 // Перебираем закрытые сессии в прямом порядки | |
198 // и очередную добавляем в начало списка, | |
199 // чтобы получить обратный порядок отображения. | |
200 foreach ( $cms["config"]["logouted"] as $attr ) { | |
201 $logouts = " | |
202 <div> | |
203 <div></div> | |
204 <div class=date>{$attr['date']}</div> | |
205 <div class=ip>{$attr['ip']}</div> | |
206 <div class=agent>{$attr['user_agent']}</div> | |
207 </div> | |
208 {$logouts}"; | |
209 } | |
210 } | |
211 | |
212 // Display settings | |
213 $tr_login = __( "login_or_password" ); | |
214 $tr_passw = __( "password" ); | |
215 $tr_set = __( "set_password" ); | |
216 $tr_current = __( "current_logins" ); | |
217 $tr_history = __( "logins_history" ); | |
218 $tr_admin_url = __( "admin_url" ); | |
219 $form = " | |
220 <form method=post> | |
221 <div class=admin-url>{$tr_admin_url}</div> | |
222 <input name=admin_url type=text value='{$cms['config']['admin.mod.php']['admin_url']}' autocomplete=off size=10> | |
223 <div class=login-title>{$tr_login}</div> | |
224 <input name=admin_login type=text value='{$cms['config']['admin.mod.php']['admin_login']}' autocomplete=off size=22> | |
225 <div class=passwd-title>{$tr_passw}</div> | |
226 <div class=password-widget> | |
227 <input name=admin_password type=password value='{$cms['config']['admin.mod.php']['admin_password']}' autocomplete=off size=10> | |
228 <div class=password-eye></div> | |
229 </div> | |
230 <div></div> | |
231 <button value=save name=change_admin_login>{$tr_set}</button> | |
232 </form> | |
233 | |
234 <div class=current-sess> | |
235 <div class=table-title>{$tr_current}</div> | |
236 <div class=sess-table>{$rows}</div> | |
237 </div> | |
238 | |
239 <div class=history-sess> | |
240 <div class=table-title>{$tr_history}</div> | |
241 <div class=sess-table>{$logouts}</div> | |
242 </div> | |
243 "; | |
244 // Create menu item if not exists | |
245 if ( empty( $cms["config"]["admin.mod.php"]["menu"]["auth"] ) ) { | |
246 $cms["config"]["admin.mod.php"]["menu"]["auth"] = array( | |
247 "title" => "auth", | |
248 "sort" => 10, | |
249 "section" => "settings", | |
250 ); | |
251 cms_save_config(); | |
252 } | |
253 $cms["admin_pages"]["auth"] = $form; | |
254 | |
255 } | |
256 | |
257 | |
258 $conf = $cms["config"]["admin.mod.php"]["menu"]["phpinfo"]; | |
259 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) { | |
260 | |
261 // PHP Info | |
262 if ( empty( $cms["config"]["admin.mod.php"]["menu"]["phpinfo"]["hide"] ) ) { | |
263 ob_start(); | |
264 phpinfo(); | |
265 preg_match( "/<body>(.+)<\/body>/us", ob_get_clean(), $m ); | |
266 $page = $m[1]; | |
267 // Create menu item if not exists | |
268 if ( empty( $cms["config"]["admin.mod.php"]["menu"]["phpinfo"] ) ) { | |
269 $cms["config"]["admin.mod.php"]["menu"]["phpinfo"] = array( | |
270 "title" => "php_info", | |
271 "sort" => 30, | |
272 "section" => "settings", | |
273 ); | |
274 cms_save_config(); | |
275 } | |
276 $cms["admin_pages"]["phpinfo"] = $page; | |
277 } | |
278 | |
279 } | |
280 | |
281 | |
282 // Modules List | |
283 $conf = $cms["config"]["admin.mod.php"]["menu"]["modules"]; | |
284 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) { | |
285 | |
286 if ( empty( $cms["config"]["admin.mod.php"]["update"]["last_version"] ) ) { | |
287 $last_version = __( "unknown" ); | |
288 } else { | |
289 $last_version = $cms["config"]["admin.mod.php"]["update"]["last_version"]; | |
290 if ( $cms["kernel_compat"] !== $cms["config"]["admin.mod.php"]["update"]["compat"] ) { | |
291 $last_version .= ". " . __( "incompatible_v" ); | |
292 } | |
293 } | |
294 | |
295 if ( empty( $cms["config"]["admin.mod.php"]["last_check"] ) ) { | |
296 $last_check = __( "never" ); | |
297 } else { | |
298 $last_check = date( "d.m.Y H:i", $cms["config"]["admin.mod.php"]["last_check"] ); | |
299 } | |
300 if ( file_exists( $cms["cms_dir"] . "/man/" . $cms["config"]["locale"] . "/book.html" ) ) { | |
301 $book_href = $cms["base_path"] . "man/" . $cms["config"]["locale"] . "/book.html"; | |
302 $book_link = "<a href={$book_href} target=_blank>" . __( "book" ) . "</a>"; | |
303 } else { | |
304 $book_link = ""; | |
305 } | |
306 $admin_menu = " | |
307 <div class=header> | |
308 | |
309 <div class=update-window> | |
310 <div>" . __( "update_core" ) . "</div> | |
311 <div class=check-answer> | |
312 <p>" . __( "current_v" ) . " {$cms['kernel_version']}</p> | |
313 <p>" . __( "last_v" ) . " {$last_version}</p> | |
314 <p>" . __( "checked" ) . " {$last_check}</p> | |
315 </div> | |
316 <div class=buttons> | |
317 <button data-fn=cms_check_update>" . __( "check" ) . "</button> | |
318 <button data-fn=cms_update>" . __( "update" ) . "</button> | |
319 {$book_link} | |
320 <button data-show-dev>" . __( "for_dev" ) . "</button> | |
321 </div> | |
322 </div> | |
323 | |
324 <div class='dev-window developers_only'> | |
325 <div class=buttons> | |
326 <button data-fn=cms_check_dev_update>" . __( "check_dev" ) . "</button> | |
327 <button data-fn=cms_changed_files>" . __( "changed_files" ) . "</button> | |
328 <button data-fn=create_zip style='display:none'>" . __( "create_zip" ) . "</button> | |
329 </div> | |
330 </div> | |
331 | |
332 <div class=changed-files style='display:none'></div> | |
333 | |
334 <div class=upload_dnd> | |
335 <input id=module-upload type=file name='myfile[]' multiple class=files> | |
336 " . __( "mod_install" ) . " | |
337 </div> | |
338 </div> | |
339 <div class=modules-grid>"; | |
340 | |
341 // Сортировка модулей | |
342 function modules_sort( $a, $b ) { | |
343 return ( $a["name"] < $b["name"] ) ? -1 : 1; | |
344 } | |
345 uasort( $cms["modules"], "modules_sort" ); | |
346 | |
347 $tr_on = __( "mod_on" ); | |
348 $tr_off = __( "mod_off" ); | |
349 $tr_del = __( "mod_del" ); | |
350 foreach( $cms["modules"] as $mod => $mod_cfg ) { | |
351 if ( ! empty( $cms["config"][$mod]["disabled"] ) ) { | |
352 $status = "disabled"; | |
353 $tr_sw = $tr_on; | |
354 } else { | |
355 $status = "enabled"; | |
356 $tr_sw = $tr_off; | |
357 } | |
358 if ( empty( $mod_cfg["version"] ) ) { | |
359 $mod_version = ""; | |
360 } else { | |
361 $mod_version = "<div class=module-version>{$mod_cfg['version']}</div>"; | |
362 } | |
363 // переводы имен модулей вынесены сюда чтобы не было варнингов при установке | |
364 $admin_menu .= " | |
365 <div class={$status} data-module={$mod}> | |
366 <div class=module-name>" . __( $mod_cfg['name'], $mod ) . "</div> | |
367 {$mod_version} | |
368 <div class=module-description>" . __( $mod_cfg['description'], $mod ) . "</div> | |
369 <a class=module-sw-btn>{$tr_sw}</a> | |
370 <a class=module-del-btn>{$tr_del}</a> | |
371 </div>"; | |
372 } | |
373 $admin_menu .= "</div>"; | |
374 | |
375 // Create menu item if not exists | |
376 if ( empty( $cms["config"]["admin.mod.php"]["menu"]["modules"] ) ) { | |
377 $cms["config"]["admin.mod.php"]["menu"]["modules"] = array( | |
378 "title" => "modules", | |
379 "sort" => 50, | |
380 "section" => "settings", | |
381 ); | |
382 cms_save_config(); | |
383 } | |
384 $cms["admin_pages"]["modules"] = $admin_menu; | |
385 } | |
386 | |
387 | |
388 // Admin | |
389 | |
390 // Create menu item if not exists | |
391 if ( empty( $cms["config"]["admin.mod.php"]["menu"]["admin_menu"] ) ) { | |
392 $cms["config"]["admin.mod.php"]["menu"]["admin_menu"] = array( | |
393 "title" => "admin_module_name", | |
394 "sort" => 40, | |
395 "section" => "settings", | |
396 ); | |
397 cms_save_config(); | |
398 } | |
399 | |
400 cms_admin_menu(); | |
401 | |
402 $conf = $cms["config"]["admin.mod.php"]["menu"]["admin_menu"]; | |
403 if ( empty( $conf["hide"] ) && empty( $cms["config"]["admin_sections"][ $conf["section"] ]["hide"] ) ) { | |
404 | |
405 $tr_show = __( "show" ); | |
406 $tr_hide = __( "hide" ); | |
407 $tr_save = __( "save" ); | |
408 $tr_del_section = __( "delete" ); | |
409 $tr_reset = __( "reset" ); | |
410 | |
411 | |
412 $options = ""; | |
413 foreach( $cms["admin_sections"] as $section_name => $section ) { | |
414 $options .= "<div class=option value='{$section_name}'>{$section["title"]}</div>"; | |
415 } | |
416 | |
417 // Admin Sections | |
418 $admin_menu = " | |
419 <div class=main-main> | |
420 <div class=am-grid>"; | |
421 foreach( $cms["admin_sections"] as $section_name => $section ) { | |
422 if ( empty( $section["hide"] ) ) { | |
423 $status = "showed"; | |
424 $tr_sw = $tr_hide; | |
425 } else { | |
426 $status = "hidden"; | |
427 $tr_sw = $tr_show; | |
428 } | |
429 $admin_menu .= " | |
430 <div> | |
431 | |
432 <div class={$status} data-am-type=section data-am-item='{$section_name}'> | |
433 <input name=title type=text value='{$section['title']}'> | |
434 <input name=sort type=text value='{$section['sort']}'> | |
435 <div class=buttons> | |
436 <a data-am-save>{$tr_save}</a> | |
437 <a data-am-delete>{$tr_del_section}</a> | |
438 <a data-am-sw>{$tr_sw}</a> | |
439 </div> | |
440 </div> | |
441 | |
442 <div class=items-grid data-am-childs='{$section_name}'>"; | |
443 | |
444 // Admin Items | |
445 if ( ! empty( $cms["admin_sections"][$section_name]["items"] ) ) | |
446 foreach( $cms["admin_sections"][$section_name]["items"] as $iname => $item ) { | |
447 if ( empty( $item["hide"] ) ) { | |
448 $status = "showed"; | |
449 $tr_sw = $tr_hide; | |
450 } else { | |
451 $status = "hidden"; | |
452 $tr_sw = $tr_show; | |
453 } | |
454 | |
455 $admin_menu .= " | |
456 <div class={$status} data-am-type=item data-am-module={$item['module']} data-am-item={$iname}> | |
457 <div class=item-name>" . __( $item["title"], $item["module"] ) . "</div> | |
458 <input name=sort type=text value='{$item['sort']}'> | |
459 <div class=section-select-grid> | |
460 <div class=field-select data-section='{$section_name}'> | |
461 <div class=value>{$cms['admin_sections'][$section_name]['title']}</div> | |
462 <div class=icon></div> | |
463 </div> | |
464 <div class=field-options> | |
465 {$options} | |
466 </div> | |
467 </div> | |
468 <div class=buttons> | |
469 <a data-am-save>{$tr_save}</a> | |
470 <a data-am-save data-am-reset>{$tr_reset}</a> | |
471 <a data-am-sw>{$tr_sw}</a> | |
472 </div> | |
473 </div>"; | |
474 } | |
475 | |
476 $admin_menu .= " | |
477 </div> <!-- class=status --> | |
478 </div> <!-- class= -->"; | |
479 } | |
480 | |
481 | |
482 $admin_menu .= " | |
483 </div> <!-- class=am-grid --> | |
484 </div> <!-- class=main-main --> | |
485 <div class=main-footer> | |
486 <div class=add-section>" . __( "add_section" ) . "</div> | |
487 <div class=reset-all>" . __( "reset_all" ) . "</div> | |
488 </div>"; | |
489 | |
490 $cms["admin_pages"]["admin_menu"] = $admin_menu; | |
491 | |
492 } | |
493 | |
494 } | |
495 | |
496 | |
497 function cms_admin_api() { | |
498 global $cms; | |
499 | |
500 // Cookie, Logout, Admin, Modules | |
501 if ( ! empty( $_POST["fn"] ) && is_admin() ) { | |
502 switch ( $_POST["fn"] ) { | |
503 | |
504 case "logout": | |
505 $cms["status"] = "200"; | |
506 if ( empty( $_POST["sess"] ) ) { | |
507 if ( PHP_VERSION_ID < 70300 ) { | |
508 setcookie( "sess", "", 365 * 24 * 60 * 60 ); | |
509 } else { | |
510 setcookie( "sess", "", array( "SameSite" => "Lax", "expires" => time() + 365 * 24 * 60 * 60 ) ); | |
511 } | |
512 $login = $_COOKIE["sess"]; | |
513 $result = "refresh"; | |
514 } else { | |
515 $login = $_POST["sess"]; | |
516 if ( $_POST["sess"] === $_COOKIE["sess"] ) { | |
517 $result = "refresh"; | |
518 } else { | |
519 $result = "ok"; | |
520 } | |
521 } | |
522 | |
523 if ( ! isset($cms["config"]["logouted"]) ) { | |
524 $cms["config"]["logouted"] = array(); | |
525 } | |
526 // Добавляем закрытую сессию в конец массива в историю | |
527 array_push( $cms["config"]["logouted"], $cms["config"]["logged"][$login] ); | |
528 // Оставим только последние 10 выходов в истории | |
529 $cms["config"]["logouted"] = array_slice( $cms["config"]["logouted"], -10 ); | |
530 unset( $cms["config"]["logged"][$login] ); | |
531 cms_save_config(); | |
532 | |
533 echo( json_encode( array( | |
534 "info_text" => __( "logout_completed" ), | |
535 "info_class" => "info-success", | |
536 "info_time" => 5000, | |
537 "result" => $result, | |
538 ) ) ); | |
539 return; | |
540 break; | |
541 | |
542 case "admin_menu_save": | |
543 switch ( $_POST["type"] ) { | |
544 case "section": | |
545 if ( empty( $_POST["title"] ) ) { | |
546 unset ( $cms["config"]["admin_sections"][ $_POST["item"] ]["title"] ); | |
547 } else { | |
548 $cms["config"]["admin_sections"][ $_POST["item"] ]["title"] = $_POST["title"]; | |
549 } | |
550 $n = (int) $_POST["sort"]; | |
551 if ( $n ) { | |
552 $cms["config"]["admin_sections"][ $_POST["item"] ]["sort"] = $n; | |
553 } else { | |
554 unset( $cms["config"]["admin_sections"][ $_POST["item"] ]["sort"] ); | |
555 } | |
556 break; | |
557 | |
558 // Настройки пунктов сохраняются в настройках модулей, а не в секции | |
559 case "item": | |
560 if ( $_POST["reset"] === "true" ) { | |
561 unset( $cms["config"][ $_POST["module"] ]["menu"][ $_POST["item"] ] ); | |
562 } else { | |
563 $cms["config"][ $_POST["module"] ]["menu"][ $_POST["item"] ]["section"] = $_POST["section"]; | |
564 $cms["config"][ $_POST["module"] ]["menu"][ $_POST["item"] ]["sort"] = (int) $_POST["sort"]; | |
565 } | |
566 break; | |
567 } | |
568 cms_save_config(); | |
569 echo( json_encode( array( | |
570 "ok" => "true", | |
571 ) ) ); | |
572 return; | |
573 break; | |
574 | |
575 case "admin_menu_hide": | |
576 $hide = $_POST["hide"] === "true"; | |
577 switch ( $_POST["type"] ) { | |
578 case "section": | |
579 $cms["config"]["admin_sections"][ $_POST["item"] ]["hide"] = $hide; | |
580 break; | |
581 case "item": | |
582 $cms["config"][ $_POST["module"] ]["menu"][ $_POST["item"] ]["hide"] = $hide; | |
583 break; | |
584 } | |
585 cms_save_config(); | |
586 echo( json_encode( array( | |
587 "ok" => "true", | |
588 ) ) ); | |
589 return; | |
590 break; | |
591 | |
592 case "admin_menu_add_section": | |
593 $n = 1; | |
594 while ( isset( $cms["config"]["admin_sections"]["section_".$n] ) ) { | |
595 $n++; | |
596 } | |
597 $cms["config"]["admin_sections"]["section_".$n] = array( | |
598 "title" => __( "add_section" ), | |
599 "sort" => 99, | |
600 ); | |
601 cms_save_config(); | |
602 echo( json_encode( array( | |
603 "info_text" => __( "section_added" ), | |
604 "info_class" => "info-success", | |
605 "info_time" => 3000, | |
606 ) ) ); | |
607 return; | |
608 break; | |
609 | |
610 case "admin_menu_del": | |
611 $cms["status"] = "200"; | |
612 unset( $cms["config"]["admin_sections"][ $_POST["item"] ]); | |
613 cms_save_config(); | |
614 echo( json_encode( array( | |
615 "info_text" => __( "deleted" ), | |
616 "info_class" => "info-success", | |
617 "info_time" => 1000, | |
618 ) ) ); | |
619 return; | |
620 break; | |
621 | |
622 case "module_disable": | |
623 if ( $_POST["module"] == "admin.mod.php" || $_POST["module"] == "template.mod.php" ) { | |
624 echo( json_encode( array( | |
625 "info_text" => __( "not_disabled" ), | |
626 "info_class" => "info-error", | |
627 "info_time" => 5000, | |
628 ) ) ); | |
629 return; | |
630 } | |
631 if ( $_POST["disable"] === "true" ) { | |
632 $cms["config"][$_POST["module"]]["disabled"] = true; | |
633 } else { | |
634 unset( $cms["config"][$_POST["module"]]["disabled"] ); | |
635 } | |
636 cms_save_config(); | |
637 echo( json_encode( array( | |
638 "ok" => "true", | |
639 ) ) ); | |
640 return; | |
641 break; | |
642 | |
643 case "module_del": | |
644 $text = __( "delete_this_files" ); | |
645 foreach( $cms["modules"][$_POST["module"]]["files"] as $file ) { | |
646 $text .= "<br>{$file}"; | |
647 } | |
648 echo( json_encode( array( | |
649 "info_text" => $text, | |
650 "info_class" => "info-error", | |
651 "info_time" => 60000, | |
652 ) ) ); | |
653 return; | |
654 break; | |
655 | |
656 case "install_module": | |
657 $success = true; | |
658 foreach ( $_FILES["myfile"]["name"] as $n => $name ) { | |
659 if ( $_FILES["myfile"]["error"][$n] ) { | |
660 $success = false; | |
661 $text = str_replace( "xxx", $name, __( "upload_error_xxx" ) ); | |
662 break; | |
663 } else { | |
664 // Unpack Module | |
665 // Object Oriented Style for future compability with PHP 8 | |
666 $zip = new ZipArchive; | |
667 $zip_file = $_FILES["myfile"]["tmp_name"][$n]; | |
668 if ( $zip->open( $zip_file ) === TRUE ) { | |
669 $ok = $zip->extractTo( $cms["site_dir"] ); | |
670 $zip->close(); | |
671 if ( ! $ok ) { | |
672 $success = false; | |
673 $text = str_replace( "xxx", $name, __( "cant_extract_xxx" ) ); | |
674 break; | |
675 } else { | |
676 // Load modules | |
677 // В одном zip может быть множество модулей | |
678 foreach( glob( "{$cms['cms_dir']}/mod/*.mod.php" ) as $mod_file ) { | |
679 include_once( $mod_file ); | |
680 $module_name = str_replace( ".mod.php", "", basename( $mod_file ) ); | |
681 $sql_file = "{$cms['cms_dir']}/mod/{$module_name}.update.sql"; | |
682 if ( is_file( $sql_file ) ) { | |
683 $q = file_get_contents( $sql_file ); | |
684 $res = mysqli_multi_query( $cms["base"], $q ); | |
685 } | |
686 } | |
687 | |
688 do_hook( "create_tables" ); | |
689 | |
690 $text = __( "install_success" ); | |
691 } | |
692 } else { | |
693 $success = false; | |
694 $text = str_replace( "xxx", $name, __( "cant_open_zip_xxx" ) ); | |
695 break; | |
696 } | |
697 } | |
698 } | |
699 | |
700 if ( $success ) { | |
701 if ( function_exists( "cms_clear_cache" ) ) { | |
702 cms_clear_cache(); | |
703 } | |
704 $cms["config"]["admin.mod.php"]["clear_cache"] = true; | |
705 cms_save_config(); | |
706 echo( json_encode( array( | |
707 "info_text" => $text, | |
708 "info_class" => "info-success", | |
709 "info_time" => 5000, | |
710 ) ) ); | |
711 return; | |
712 } else { | |
713 echo( json_encode( array( | |
714 "info_text" => $text, | |
715 "info_class" => "info-error", | |
716 "info_time" => 10000, | |
717 ) ) ); | |
718 return; | |
719 } | |
720 break; | |
721 | |
722 case "no_translation": | |
723 if ( ! empty( $cms["config"]["debug"] ) ) { | |
724 $new_debug = array( | |
725 "translate to {$cms["config"]["locale"]}" => array( | |
726 "{$_POST["module"]}:js" => $_POST["str"], | |
727 ), | |
728 ); | |
729 $debug_file = $cms["cms_dir"] . "/debug.log.php"; | |
730 if ( $handle = fopen( $debug_file, "r" ) ) { | |
731 flock( $handle, LOCK_SH ); | |
732 include( $debug_file ); | |
733 $cms["debug"] = array_replace_recursive( $cms["debug"], $new_debug ); | |
734 flock( $handle, LOCK_UN ); | |
735 file_put_contents( $debug_file, '<?php $cms["debug"] = ' . var_export( $cms["debug"], true) . ";\n", LOCK_EX ); | |
736 } else { | |
737 file_put_contents( $debug_file, '<?php $cms["debug"] = ' . var_export( $cms["debug"], true) . ";\n", LOCK_EX ); | |
738 } | |
739 } | |
740 echo( '{ "result": "ok" }' ); | |
741 return; | |
742 break; | |
743 | |
744 case "reset_admin_menu_items": | |
745 reset_admin_menu_items(); | |
746 echo( json_encode( array( | |
747 "info_text" => __( "reset_all_ok" ), | |
748 "info_class" => "info-success", | |
749 "info_time" => 3000, | |
750 ) ) ); | |
751 return; | |
752 break; | |
753 | |
754 case "create_zip": | |
755 cms_update_create_zip(); | |
756 break; | |
757 | |
758 case "cms_check_update": | |
759 cms_update_check( "https://coffee-cms.ru/update.json" ); | |
760 break; | |
761 | |
762 case "cms_check_dev_update": | |
763 cms_update_check( "https://dev.coffee-cms.ru/update_dev.json" ); | |
764 break; | |
765 | |
766 case "cms_update": | |
767 cms_update_cms_update(); | |
768 break; | |
769 | |
770 case "cms_changed_files": | |
771 cms_changed_files(); | |
772 break; | |
773 } | |
774 | |
775 } | |
776 } | |
777 | |
778 | |
779 function reset_admin_menu_items() { | |
780 global $cms; | |
781 unset( $cms["config"]["admin_sections"] ); | |
782 foreach( $cms["modules"] as $mod => $val ) { | |
783 if ( isset( $cms["config"][$mod]["menu"] ) ) { | |
784 unset( $cms["config"][$mod]["menu"] ); | |
785 } | |
786 } | |
787 cms_save_config(); | |
788 }//unset( $cms["config"][ $_POST["module"] ]["menu"][ $_POST["item"] ] ); | |
789 | |
790 | |
791 function cms_update_create_filelist() { | |
792 global $cms; | |
793 | |
794 $logs = ""; | |
795 | |
796 $queue = array( | |
797 "{$cms['site_dir']}/uploads/.keep", | |
798 "{$cms['site_dir']}/.htaccess", | |
799 "{$cms['site_dir']}/.nginx.conf", | |
800 "{$cms['site_dir']}/.cms/admin.cms", | |
801 "{$cms['site_dir']}/.cms/css/base.css", | |
802 "{$cms['site_dir']}/.cms/css/menu.css", | |
803 "{$cms['site_dir']}/.cms/css/pages.css", | |
804 "{$cms['site_dir']}/.cms/css/sitemap.css", | |
805 "{$cms['site_dir']}/.cms/css/rss.css", | |
806 "{$cms['site_dir']}/.cms/css/template.css", | |
807 "{$cms['site_dir']}/.cms/css/admin.css", | |
808 "{$cms['site_dir']}/.cms/filelist.php", | |
809 "{$cms['site_dir']}/.cms/img", | |
810 "{$cms['site_dir']}/.cms/js/admin.js", | |
811 "{$cms['site_dir']}/.cms/js/menu.js", | |
812 "{$cms['site_dir']}/.cms/js/pages.js", | |
813 "{$cms['site_dir']}/.cms/js/sitemap.js", | |
814 "{$cms['site_dir']}/.cms/js/rss.js", | |
815 "{$cms['site_dir']}/.cms/js/template.js", | |
816 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/admin.mod.php", | |
817 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/base.mod.php", | |
818 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/menu.mod.php", | |
819 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/pages.mod.php", | |
820 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/sitemap.mod.php", | |
821 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/rss.mod.php", | |
822 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/template.mod.php", | |
823 "{$cms['site_dir']}/.cms/lang/ru_RU.UTF-8/translit.php", | |
824 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/admin.mod.php", | |
825 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/base.mod.php", | |
826 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/menu.mod.php", | |
827 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/pages.mod.php", | |
828 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/sitemap.mod.php", | |
829 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/rss.mod.php", | |
830 "{$cms['site_dir']}/.cms/lang/en_US.UTF-8/template.mod.php", | |
831 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/admin.mod.php", | |
832 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/base.mod.php", | |
833 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/menu.mod.php", | |
834 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/pages.mod.php", | |
835 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/sitemap.mod.php", | |
836 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/rss.mod.php", | |
837 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/template.mod.php", | |
838 "{$cms['site_dir']}/.cms/lang/uk_UA.UTF-8/translit.php", | |
839 | |
840 "{$cms['site_dir']}/.cms/lib/codemirror", | |
841 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/book.html", | |
842 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/codemirror.html", | |
843 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/example.html", | |
844 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/hint_css.html", | |
845 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/hint_html.html", | |
846 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/hint_php.html", | |
847 "{$cms['site_dir']}/.cms/man/ru_RU.UTF-8/menu.html", | |
848 "{$cms['site_dir']}/.cms/man/css/prism.css", | |
849 "{$cms['site_dir']}/.cms/man/css/styles.css", | |
850 "{$cms['site_dir']}/.cms/man/js/prism.js", | |
851 | |
852 // Файлы шаблона | |
853 "{$cms['site_dir']}/.cms/mini/html.php", | |
854 "{$cms['site_dir']}/.cms/mini/404.en_US.UTF-8.php", | |
855 "{$cms['site_dir']}/.cms/mini/404.ru_RU.UTF-8.php", | |
856 "{$cms['site_dir']}/.cms/mini/404.uk_UA.UTF-8.php", | |
857 "{$cms['site_dir']}/.cms/mini/banner.jpg", | |
858 "{$cms['site_dir']}/.cms/mini/blog.php", | |
859 "{$cms['site_dir']}/.cms/mini/favicon.svg", | |
860 "{$cms['site_dir']}/.cms/mini/frontpage.php", | |
861 "{$cms['site_dir']}/.cms/mini/instruction.ru_RU.UTF-8.html", | |
862 "{$cms['site_dir']}/.cms/mini/page.php", | |
863 "{$cms['site_dir']}/.cms/mini/page.teaser.php", | |
864 "{$cms['site_dir']}/.cms/mini/post.php", | |
865 "{$cms['site_dir']}/.cms/mini/styles.css", | |
866 "{$cms['site_dir']}/.cms/mini/template.settings.php", | |
867 "{$cms['site_dir']}/.cms/mini/tpl.mod.php", | |
868 | |
869 "{$cms['site_dir']}/.cms/mod/admin.mod.php", | |
870 "{$cms['site_dir']}/.cms/mod/base.mod.php", | |
871 "{$cms['site_dir']}/.cms/mod/menu.mod.php", | |
872 "{$cms['site_dir']}/.cms/mod/pages.mod.php", | |
873 "{$cms['site_dir']}/.cms/mod/sitemap.mod.php", | |
874 "{$cms['site_dir']}/.cms/mod/rss.mod.php", | |
875 "{$cms['site_dir']}/.cms/mod/template.mod.php", | |
876 "{$cms['site_dir']}/.cms/index.fn.php", | |
877 "{$cms['site_dir']}/.cms/index.php", | |
878 "{$cms['site_dir']}/.cms/update.sql", | |
879 "{$cms['site_dir']}/.cms/update.php", | |
880 "{$cms['site_dir']}/.cms/.unlicense.txt", | |
881 ); | |
882 $no_sha1 = array( | |
883 "{$cms['site_dir']}/.cms/filelist.php", | |
884 ); | |
885 | |
886 $list = array(); | |
887 | |
888 while ( $cur = array_shift( $queue ) ) { | |
889 if ( is_dir( $cur ) ) { | |
890 $queue = array_merge( $queue, glob( $cur . "/*" ) ); | |
891 } elseif ( is_file( $cur ) ) { | |
892 if ( in_array( $cur, $no_sha1 ) ) { | |
893 $sha1 = ""; | |
894 $size = ""; | |
895 } else { | |
896 $sha1 = sha1_file( $cur ); | |
897 $size = filesize( $cur ); | |
898 } | |
899 $file = str_replace( "{$cms['site_dir']}/", "", $cur ); | |
900 $list[$file] = array( | |
901 "sha1" => $sha1, | |
902 "size" => $size, | |
903 ); | |
904 } else { | |
905 $logs .= "<p>" . __( "file_or_dir_not_exists" ) . " '{$cur}'</p>"; | |
906 } | |
907 } | |
908 | |
909 // Список файлов которые разрешено редактировать. | |
910 // И если они отредактированы, то не будут обновляться. | |
911 $allow_change = array( | |
912 ".htaccess", | |
913 ); | |
914 | |
915 file_put_contents( "{$cms['cms_dir']}/filelist.php", | |
916 "<?php\n\$allow_change = " . var_export( $allow_change, true ) . ";\n" . | |
917 '$list = ' . var_export( $list, true ) . ";\n" | |
918 ); | |
919 | |
920 $logs .= "<p>".__( "files" )." " . count( $list ) . "</p>"; | |
921 | |
922 return $logs; | |
923 | |
924 } | |
925 | |
926 | |
927 function cms_update_check( $url ) { | |
928 global $cms; | |
929 | |
930 // prevent warning | |
931 if ( empty( $cms["config"]["admin.mod.php"]["last_check"] ) ) { | |
932 $cms["config"]["admin.mod.php"]["last_check"] = 0; | |
933 } | |
934 | |
935 $t = time(); | |
936 $dt = $t - $cms["config"]["admin.mod.php"]["last_check"]; | |
937 $time_min = 1; | |
938 if ( $dt < $time_min * 60 ) { | |
939 $n = ceil( ( $time_min * 60 - $dt ) / 60 ); | |
940 $msg = __( "try_later" ); | |
941 $msg = str_replace( "xxx", $n, $msg ); | |
942 echo( json_encode( array( | |
943 "info_text" => $msg, | |
944 "info_class" => "info-error", | |
945 "info_time" => 5000, | |
946 ) ) ); | |
947 return; | |
948 } | |
949 | |
950 if ( ! $update = file_get_contents( $url ) ) { | |
951 echo( json_encode( array( | |
952 "info_text" => __( "cant_get" ) . " " . $url, | |
953 "info_class" => "info-error", | |
954 "info_time" => 5000, | |
955 ) ) ); | |
956 return; | |
957 } | |
958 | |
959 if ( ! $update = json_decode( $update, true ) ) { | |
960 echo( json_encode( array( | |
961 "info_text" => __( "json_error" ) . " " . $url, | |
962 "info_class" => "info-error", | |
963 "info_time" => 5000, | |
964 ) ) ); | |
965 return; | |
966 } | |
967 | |
968 $cms["config"]["admin.mod.php"]["last_check"] = $t; | |
969 $cms["config"]["admin.mod.php"]["update"] = $update; | |
970 cms_save_config(); | |
971 | |
972 $last_check = date( "d.m.Y H:i", $cms["config"]["admin.mod.php"]["last_check"] ); | |
973 | |
974 $last_version = $cms["config"]["admin.mod.php"]["update"]["last_version"]; | |
975 | |
976 if ( $cms["kernel_compat"] !== $cms["config"]["admin.mod.php"]["update"]["compat"] ) { | |
977 $last_version .= ". " . __( "incompatible_v" ); | |
978 } | |
979 | |
980 $update_info = "<p>" . __( "current_v" ) . " {$cms['kernel_version']}</p>"; | |
981 $update_info .= "<p>" . __( "last_v" ) . " {$last_version}</p>"; | |
982 $update_info .= "<p>" . __( "checked" ) . " {$last_check}</p>"; | |
983 | |
984 echo( json_encode( array( | |
985 "info_text" => __( "last_v" ) . " {$last_version}", | |
986 "info_class" => "info-success", | |
987 "info_time" => 5000, | |
988 "answer" => $update_info, | |
989 ) ) ); | |
990 return; | |
991 | |
992 } | |
993 | |
994 | |
995 function cms_changed_files() { | |
996 global $cms; | |
997 | |
998 $fl = "{$cms['cms_dir']}/filelist.php"; | |
999 require( $fl ); | |
1000 | |
1001 $errors = array(); | |
1002 $max_errors = 100; | |
1003 | |
1004 // Проверка файлов текущей версии | |
1005 // по чексуммам и размерам | |
1006 foreach( $list as $fn => $file ) { | |
1007 $f = $cms["site_dir"] . "/" . $fn; | |
1008 if ( ! is_file( $f ) ) { | |
1009 if ( count( $errors ) >= $max_errors ) { | |
1010 break; | |
1011 } else { | |
1012 array_push( $errors, __( "file_not_exists" ) . " " . $f ); | |
1013 } | |
1014 } | |
1015 $sha1 = sha1_file( $f ); | |
1016 $size = filesize( $f ); | |
1017 if ( ! empty( $file["sha1"] ) && ! empty( $file["size"] ) && is_file( $f ) ) { | |
1018 if ( $file["sha1"] !== $sha1 || $file["size"] !== $size ) { | |
1019 if ( ! in_array( $fn, $allow_change ) ) { | |
1020 if ( count( $errors ) >= $max_errors ) { | |
1021 break; | |
1022 } else { | |
1023 array_push( $errors, __( "file_changed" ) . " " . $f ); | |
1024 } | |
1025 } | |
1026 } | |
1027 } | |
1028 } | |
1029 | |
1030 // Возвращаем список недочетов | |
1031 if ( count( $errors ) ) { | |
1032 $files = implode( "<br>", $errors ); | |
1033 } else { | |
1034 $files = __( "no_files_changed" ); | |
1035 } | |
1036 echo( json_encode( array( | |
1037 "answer" => $files, | |
1038 ) ) ); | |
1039 return; | |
1040 | |
1041 } | |
1042 | |
1043 function cms_update_cms_update() { | |
1044 global $cms; | |
1045 | |
1046 // Не проверялись обновления вообще | |
1047 if ( empty( $cms["config"]["admin.mod.php"]["update"] ) ) { | |
1048 echo( json_encode( array( | |
1049 "info_text" => __( "check_updates" ), | |
1050 "info_class" => "info-error", | |
1051 "info_time" => 5000, | |
1052 ) ) ); | |
1053 return; | |
1054 } | |
1055 | |
1056 // Отсутствует файл со списком файлов | |
1057 $fl = "{$cms['cms_dir']}/filelist.php"; | |
1058 if ( ! file_exists( $fl ) ) { | |
1059 echo( json_encode( array( | |
1060 "info_text" => __( "file_list_missing" ) . " " . $fl, | |
1061 "info_class" => "info-error", | |
1062 "info_time" => 5000, | |
1063 ) ) ); | |
1064 return; | |
1065 } | |
1066 | |
1067 require( $fl ); | |
1068 | |
1069 $update = $cms["config"]["admin.mod.php"]["update"]; | |
1070 | |
1071 // Может нечего обновлять | |
1072 if ( $update["last_version"] <= $cms["kernel_version"] ) { | |
1073 echo( json_encode( array( | |
1074 "info_text" => __( "already_updated" ), | |
1075 "info_class" => "info-success", | |
1076 "info_time" => 5000, | |
1077 ) ) ); | |
1078 return; | |
1079 } | |
1080 | |
1081 // Может несовместимая версия | |
1082 if ( $update["compat"] !== $cms["kernel_compat"] ) { | |
1083 echo( json_encode( array( | |
1084 "info_text" => __( "impossible" ), | |
1085 "info_class" => "info-error", | |
1086 "info_time" => 15000, | |
1087 ) ) ); | |
1088 return; | |
1089 } | |
1090 | |
1091 // Копить по 10 ошибок | |
1092 // чтобы не мучить по одной | |
1093 $errors = array(); | |
1094 $max_errors = 10; | |
1095 | |
1096 // Проверка файлов текущей версии | |
1097 // по чексуммам и размерам | |
1098 foreach( $list as $fn => $file ) { | |
1099 $f = $cms["site_dir"] . "/" . $fn; | |
1100 if ( ! is_file( $f ) ) { | |
1101 if ( count( $errors ) >= $max_errors ) { | |
1102 break; | |
1103 } else { | |
1104 array_push( $errors, __( "file_not_exists" ) . " " . $f ); | |
1105 } | |
1106 } | |
1107 $sha1 = sha1_file( $f ); | |
1108 $size = filesize( $f ); | |
1109 if ( ! empty( $file["sha1"] ) && ! empty( $file["size"] ) && is_file( $f ) ) { | |
1110 if ( $file["sha1"] !== $sha1 || $file["size"] !== $size ) { | |
1111 if ( ! in_array( $fn, $allow_change ) ) { | |
1112 if ( count( $errors ) >= $max_errors ) { | |
1113 break; | |
1114 } else { | |
1115 array_push( $errors, __( "file_changed" ) . " " . $f ); | |
1116 } | |
1117 } | |
1118 } | |
1119 } | |
1120 } | |
1121 | |
1122 // Возвращаем список недочетов | |
1123 if ( count( $errors ) ) { | |
1124 echo( json_encode( array( | |
1125 "info_text" => implode( "<br>", $errors ), | |
1126 "info_class" => "info-error", | |
1127 "info_time" => 50000, | |
1128 ) ) ); | |
1129 return; | |
1130 } | |
1131 | |
1132 // Check Rights | |
1133 $rights = array(); | |
1134 foreach( $list as $fn => $file ) { | |
1135 $file_path = $cms["site_dir"] . "/" . $fn; | |
1136 $e = ! is_file( $file_path ) || ! is_writable( $file_path ); | |
1137 if ( $e ) { | |
1138 if ( count( $rights ) >= $max_errors ) { | |
1139 break; | |
1140 } else { | |
1141 array_push( $rights, $file_path ); | |
1142 } | |
1143 } | |
1144 } | |
1145 | |
1146 // Возвращаем список недочетов | |
1147 if ( count( $rights ) ) { | |
1148 echo( json_encode( array( | |
1149 "info_text" => __( "update_error_rights" ) . "<br>" . implode( "<br>", $rights ), | |
1150 "info_class" => "info-error", | |
1151 "info_time" => 50000, | |
1152 ) ) ); | |
1153 return; | |
1154 } | |
1155 | |
1156 if ( empty( $cms["config"]["admin.mod.php"]["last_update"] ) ) { | |
1157 $cms["config"]["admin.mod.php"]["last_update"] = 0; | |
1158 } | |
1159 | |
1160 $t = time(); | |
1161 $dt = $t - $cms["config"]["admin.mod.php"]["last_update"]; | |
1162 $time_min = 1; | |
1163 if ( $dt < $time_min * 60 ) { | |
1164 $n = ceil( ( $time_min * 60 - $dt ) / 60 ); | |
1165 $msg = __( "try_later" ); | |
1166 $msg = str_replace( "xxx", $n, $msg ); | |
1167 echo( json_encode( array( | |
1168 "info_text" => $msg, | |
1169 "info_class" => "info-error", | |
1170 "info_time" => 5000, | |
1171 ) ) ); | |
1172 return; | |
1173 } | |
1174 | |
1175 // Download New Version | |
1176 if ( ! $content = file_get_contents( $update["download"] ) ) { | |
1177 echo( json_encode( array( | |
1178 "info_text" => __( "download_error" ), | |
1179 "info_class" => "info-error", | |
1180 "info_time" => 5000, | |
1181 ) ) ); | |
1182 return; | |
1183 } | |
1184 $tmp = $cms["site_dir"] . "/.tmp"; | |
1185 if ( is_dir( $tmp ) ) { | |
1186 recurse_rm( $tmp ); | |
1187 } | |
1188 if ( ! mkdir( $tmp ) ) { | |
1189 echo( json_encode( array( | |
1190 "info_text" => __( "cant_create_tmp_dir" ) . " " . $tmp, | |
1191 "info_class" => "info-error", | |
1192 "info_time" => 5000, | |
1193 ) ) ); | |
1194 return; | |
1195 } | |
1196 $fn = preg_replace( "/.*\//u", "", $update["download"] ); | |
1197 $file = $tmp . "/" . $fn; | |
1198 if ( ! file_put_contents( $file, $content ) ) { | |
1199 echo( json_encode( array( | |
1200 "info_text" => __( "cant_write_file" ) . " " . $file, | |
1201 "info_class" => "info-error", | |
1202 "info_time" => 50000, | |
1203 ) ) ); | |
1204 return; | |
1205 } | |
1206 | |
1207 // Unpack New Version | |
1208 // Object Oriented Style for future compability with PHP 8 | |
1209 $zip = new ZipArchive; | |
1210 if ( $zip->open( $file ) === TRUE ) { | |
1211 $ok = $zip->extractTo( $tmp ); | |
1212 $zip->close(); | |
1213 if ( ! $ok ) { | |
1214 echo( json_encode( array( | |
1215 "info_text" => __( "cant_extract" ) . " " . $file, | |
1216 "info_class" => "info-error", | |
1217 "info_time" => 5000, | |
1218 ) ) ); | |
1219 return; | |
1220 } | |
1221 } else { | |
1222 echo( json_encode( array( | |
1223 "info_text" => __( "cant_open_zip" ) . " " . $file, | |
1224 "info_class" => "info-error", | |
1225 "info_time" => 5000, | |
1226 ) ) ); | |
1227 return; | |
1228 } | |
1229 | |
1230 // Check New Version | |
1231 $fl = "{$tmp}/.cms/filelist.php"; | |
1232 if ( ! is_file( $fl ) ) { | |
1233 echo( json_encode( array( | |
1234 "info_text" => __( "file_list_missing" ) . " " . $fl, | |
1235 "info_class" => "info-error", | |
1236 "info_time" => 5000, | |
1237 ) ) ); | |
1238 return; | |
1239 } | |
1240 $oldlist = $list; | |
1241 require( $fl ); | |
1242 foreach( $list as $fn => $file ) { | |
1243 $f = $tmp . "/" . $fn; | |
1244 if ( ! is_file( $f ) ) { | |
1245 echo( json_encode( array( | |
1246 "info_text" => __( "file_not_exists" ) . " " . $f, | |
1247 "info_class" => "info-error", | |
1248 "info_time" => 5000, | |
1249 ) ) ); | |
1250 return; | |
1251 } | |
1252 $sha1 = sha1_file( $f ); | |
1253 $size = filesize( $f ); | |
1254 if ( ! empty( $file["sha1"] ) ) { | |
1255 if ( $file["sha1"] !== $sha1 ) { | |
1256 echo( json_encode( array( | |
1257 "info_text" => __( "file_changed" ) . " " . $f, | |
1258 "info_class" => "info-error", | |
1259 "info_time" => 5000, | |
1260 ) ) ); | |
1261 return; | |
1262 } | |
1263 } | |
1264 if ( ! empty( $file["size"] ) ) { | |
1265 if ( $file["size"] !== $size ) { | |
1266 echo( json_encode( array( | |
1267 "info_text" => __( "file_changed" ) . " " . $f, | |
1268 "info_class" => "info-error", | |
1269 "info_time" => 5000, | |
1270 ) ) ); | |
1271 return; | |
1272 } | |
1273 } | |
1274 } | |
1275 | |
1276 // Удаление файлов текущей цмс | |
1277 $removed = true; | |
1278 foreach( $oldlist as $fn => $file ) { | |
1279 $from = $cms["site_dir"] . "/" . $fn; | |
1280 | |
1281 if ( in_array( $fn, $allow_change ) and | |
1282 sha1_file( $from ) !== $oldlist[$fn]["sha1"] ) { | |
1283 // Если файл в списке разрешенных на изменение | |
1284 // и sha1 не совпадает, то оставляем его не тронутым | |
1285 } else { | |
1286 $c = unlink( $from ); | |
1287 $removed = $removed && $c; | |
1288 } | |
1289 // try remove dir | |
1290 $rdir = preg_replace( "/\/[^\/]+$/u", "", $from ); | |
1291 if ( is_dir_and_empty( $rdir ) ) { | |
1292 rmdir( $rdir ); | |
1293 } | |
1294 } | |
1295 | |
1296 if ( ! $removed ) { | |
1297 echo( json_encode( array( | |
1298 "info_text" => __( "update_error_remove" ), | |
1299 "info_class" => "info-error", | |
1300 "info_time" => 5000, | |
1301 ) ) ); | |
1302 return; | |
1303 } | |
1304 | |
1305 // Перемещение новой версии в текущую | |
1306 // Разрешенные измененные файлы не перезаписываются | |
1307 $moved = true; // по умолчанию нет ошибок | |
1308 foreach( $list as $file_name => $none ) { | |
1309 $old_file_path = $cms["site_dir"] . "/" . $file_name; | |
1310 if ( | |
1311 is_file( $old_file_path ) and | |
1312 in_array( $file_name, $allow_change ) and | |
1313 sha1_file( $old_file_path ) !== $oldlist[$file_name]["sha1"] | |
1314 ) { | |
1315 // Если файл в списке разрешенных на изменение | |
1316 // и sha1 не совпадает, то оставляем его не тронутым | |
1317 } else { | |
1318 $from = $tmp . "/" . $file_name; | |
1319 $to = $cms["site_dir"] . "/" . $file_name; | |
1320 $ndir = preg_replace( "/\/[^\/]+$/u", "", $to ); | |
1321 if ( ! is_dir( $ndir ) ) { | |
1322 mkdir( $ndir, 0777, true ); | |
1323 } | |
1324 $c = copy( $from, $to ); | |
1325 $moved = $moved && $c; | |
1326 } | |
1327 } | |
1328 | |
1329 if ( ! $moved ) { | |
1330 echo( json_encode( array( | |
1331 "info_text" => __( "update_error_move" ), | |
1332 "info_class" => "info-error", | |
1333 "info_time" => 5000, | |
1334 ) ) ); | |
1335 return; | |
1336 } | |
1337 | |
1338 recurse_rm( $tmp ); | |
1339 | |
1340 // Выполнить запросы в БД, находящиеся в файле update.sql | |
1341 // Не будем обращать внимания на результат запроса, | |
1342 // ведь если идет многократное обновление из dev-ветки, | |
1343 // то скорее всего будут ошибки его выполнения. | |
1344 $update_sql = "{$cms['cms_dir']}/update.sql"; | |
1345 $q = ""; | |
1346 if ( is_file( $update_sql ) ) { | |
1347 $q = file_get_contents( $update_sql ); | |
1348 } | |
1349 if ( $q ) { | |
1350 cms_base_connect(); | |
1351 if ( $cms["base"] ) { | |
1352 $res = mysqli_multi_query( $cms["base"], $q ); | |
1353 } | |
1354 } | |
1355 | |
1356 $cms["config"]["admin.mod.php"]["last_update"] = time(); | |
1357 | |
1358 // Обновить конфиг | |
1359 $update_config = "{$cms['cms_dir']}/update.php"; | |
1360 if ( is_file( $update_config ) ) { | |
1361 include( $update_config ); | |
1362 } | |
1363 | |
1364 $cms["config"]["admin.mod.php"]["clear_cache"] = true; | |
1365 cms_save_config(); | |
1366 | |
1367 cms_clear_cache(); | |
1368 | |
1369 echo( json_encode( array( | |
1370 "info_text" => __( "successfull_update" ), | |
1371 "info_class" => "info-success", | |
1372 "info_time" => 5000, | |
1373 "reload" => true, | |
1374 ) ) ); | |
1375 return; | |
1376 | |
1377 } | |
1378 | |
1379 | |
1380 function cms_update_create_zip() { | |
1381 global $cms; | |
1382 | |
1383 // Данная функция сообщит об отсутствующих файлах | |
1384 $files = cms_update_create_filelist(); | |
1385 | |
1386 require( "{$cms['cms_dir']}/filelist.php" ); | |
1387 $zip = new ZipArchive(); | |
1388 $v = $cms['kernel_version'] . date( "_Y.m.d_Hi" ); | |
1389 $name = "coffee-cms-{$v}.zip"; | |
1390 $download_url = "{$cms['url']['scheme']}://{$cms['url']['host']}/{$name}"; | |
1391 $zipname = "{$cms["site_dir"]}/{$name}"; | |
1392 | |
1393 if ( $zip->open( $zipname, ZipArchive::CREATE ) !== true ) { | |
1394 echo( json_encode( array( | |
1395 "answer" => __( "cant_create_zip" ) . " {$zipname}", | |
1396 ) ) ); | |
1397 return; | |
1398 } | |
1399 | |
1400 foreach( $list as $fn => $file ) { | |
1401 $from = "{$cms['site_dir']}/{$fn}"; | |
1402 $zip->addFile( $from, $fn ); | |
1403 } | |
1404 | |
1405 $zip->close(); | |
1406 | |
1407 file_put_contents( "{$cms["site_dir"]}/update_dev.json", json_encode( array( | |
1408 "last_version" => $v, | |
1409 "compat" => $cms["kernel_compat"], | |
1410 "download" => $download_url, | |
1411 ) ) ); | |
1412 | |
1413 echo( json_encode( array( | |
1414 "answer" => $files . "<p>" . __( "archive_created" ) . ": <a href='{$download_url}'>{$download_url}</a></p>", | |
1415 ) ) ); | |
1416 return; | |
1417 } |