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 }