0
|
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 }
|