comparison .cms/index.fn.php @ 1:1d486627aa1e draft default tip

24.10
author Coffee CMS <info@coffee-cms.ru>
date Sat, 12 Oct 2024 02:51:39 +0000
parents
children
comparison
equal deleted inserted replaced
0:78edf6b517a0 1:1d486627aa1e
1 <?php
2
3
4 // Add function to selected hook with default priority 10
5 function hook_add_fn( $hook, $function, $priority = 10 ) {
6 global $cms;
7 $cms["hooks"][$hook][$priority][$function] = true; // true - enabled
8 // fix warning
9 if ( ! isset( $cms["hooks"][$hook]["next"] ) ) {
10 $cms["hooks"][$hook]["next"] = "";
11 }
12 }
13
14
15 function do_hook( $hook = "" ) {
16 global $cms;
17
18 if ( empty( $cms["hooks"][$hook] ) || ! empty( $cms["hooks"][$hook]["disabled"] ) ) {
19 return;
20 }
21
22 ksort( $cms["hooks"][$hook] );
23
24 foreach ( $cms["hooks"][$hook] as $priority => &$value ) {
25 if ( is_array( $cms["hooks"][$hook][$priority] ) ) {
26 foreach ( $cms["hooks"][$hook][$priority] as $function => &$enabled ) {
27 if ( $enabled && function_exists( $function ) ) {
28 $function();
29 }
30 }
31 }
32 }
33
34 }
35
36
37 function cms_save_config() {
38 global $cms;
39 $r = file_put_contents( $cms["config_file"], '<?php $cms["config"] = ' . var_export( $cms["config"], true) . ";\n", LOCK_EX );
40 if ( $r && function_exists( "opcache_invalidate" ) ) {
41 opcache_invalidate( $cms["config_file"] );
42 }
43 return $r;
44 }
45
46
47 #region Функции отправки письма - это комментарий для схлопывания всех фукнций письма
48
49 function cms_email_callback2( $matches ) {
50 global $email_images;
51 $n = count( $email_images );
52 $email_images[$n] = array( "ext" => $matches[1], "base64" => $matches[2] );
53 return "cid:{$n}.{$matches[1]}";
54 }
55
56 function cms_email_callback1( $matches ) {
57 $r2 = preg_replace_callback( "/data:image\/(\w+);base64,(.+)/u", "cms_email_callback2", $matches[1] );
58 return "<img src=\"$r2\"";
59 }
60
61 // $data["to_name"]
62 // $data["to_email"]
63 // $data["subject"]
64 // $data["email_body"]
65 // $data["from_name"]
66 // $data["from_email"]
67 // $data["reply_name"]
68 // $data["reply_to"]
69 // $data["files"]
70 // $data["type"] ( text/html or text/plain (default) )
71 // $data["sender"] if empty, then noreply@$_SERVER["SERVER_NAME"]
72 // $data["bcc"]
73 // return "" if success of "error:..." if error
74 function cms_email( $data ) {
75 global $email_images;
76
77 // На пустую to_email не надо проверять, потому что возможна рассылка через скрытые копии
78 if ( isset( $data["to_name"] ) ) {
79 $to = "=?utf-8?b?" . base64_encode( $data["to_name"] ) . "?= <" . $data["to_email"] . ">";
80 } else {
81 $to = $data["to_email"];
82 }
83
84 $subject = "=?utf-8?b?" . base64_encode( $data["subject"] ) . "?=";
85
86 if ( isset( $data["from_name"] ) ) {
87 $from = "=?utf-8?b?" . base64_encode( $data["from_name"] ) . "?= <" . $data["from_email"] . ">";
88 } else {
89 $from = $data["from_email"];
90 }
91
92 if ( empty( $data["reply_to"] ) ) {
93 $reply = $from;
94 } else {
95 $reply = $data["reply_to"];
96 if ( ! empty( $data["reply_name"] ) ) {
97 $reply = "=?utf-8?b?" . base64_encode( $data["reply_name"] ) . "?= <" . $data["reply_to"] . ">";
98 }
99 }
100
101 $boundary = md5( uniqid( time() - 25 ) );
102 $boundary_id = md5( uniqid( time() ) );
103
104 if ( empty( $data["sender"] ) ) {
105 $sender = "noreply@{$_SERVER['SERVER_NAME']}";
106 } else {
107 $sender = $data["sender"];
108 }
109
110 $headers = "";
111 $headers .= "Sender: {$sender}\r\n";
112 $headers .= "From: {$from}\r\n";
113 $headers .= "Reply-To: {$reply}\r\n";
114 $headers .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n";
115
116 if ( ! empty( $data["bcc"] ) ) {
117 $headers .= "Bcc: {$data['bcc']}\r\n";
118 }
119
120 $email_images = array();
121 $body2 = preg_replace_callback( '/<img\s[^>]*src="([^"]+)"/u', "cms_email_callback1", $data["email_body"] );
122
123 if ( empty( $data["type"] ) ) {
124 $type = "text/plain";
125 } else {
126 $type = $data["type"];
127 }
128
129 $body_all = "";
130 $body_all .= "--{$boundary}\r\n";
131 $body_all .= "Content-Type: multipart/related; boundary=\"{$boundary_id}\"\r\n";
132 $body_all .= "\r\n";
133
134 $body_all .= "--{$boundary_id}\r\n";
135 $body_all .= "Content-Type: {$type}; charset=utf-8;\r\n";
136 $body_all .= "Content-Transfer-Encoding: base64\r\n";
137 $body_all .= "\r\n";
138 $body_all .= chunk_split( base64_encode( $body2 ) ) . "\r\n";
139 $body_all .= "\r\n";
140
141 foreach( $email_images as $ind => $image ) {
142 $body_all .= "--{$boundary_id}\r\n";
143 $body_all .= "Content-Type: image/{$image['ext']}; name=\"{$ind}.{$image['ext']}\"\r\n";
144 $body_all .= "Content-ID: <{$ind}.{$image['ext']}>\r\n";
145 $body_all .= "Content-Disposition: inline; filename=\"{$ind}.{$image['ext']}\"\r\n";
146 $body_all .= "Content-transfer-encoding: base64\r\n";
147 $body_all .= "\r\n";
148 $body_all .= chunk_split( $image["base64"] ) . "\r\n";
149 $body_all .= "\r\n";
150 }
151
152 if ( isset( $data["files"] ) && is_array( $data["files"] ) )
153 foreach( $data["files"] as $file ) {
154 $mime = mime_content_type( $file );
155 $name = preg_replace( "/.*\//u", "", $file );
156 $body_all .= "--{$boundary_id}\r\n";
157 $body_all .= "Content-Type: {$mime}; name=\"{$name}\"\r\n";
158 $body_all .= "Content-Transfer-Encoding: base64\r\n";
159 $body_all .= "Content-Disposition: attachment; filename=\"{$name}\"\r\n";
160 $body_all .= "\r\n";
161 $body_all .= chunk_split( base64_encode( file_get_contents( $file ) ) ) . "\r\n";
162 $body_all .= "\r\n";
163 }
164
165 $body_all .= "--{$boundary_id}--\r\n";
166 $body_all .= "\r\n";
167 $body_all .= "--{$boundary}--\r\n";
168 $body_all .= "\r\n";
169
170 if ( mail( $to, $subject, $body_all, $headers, "-f{$data['from_email']}" ) ) {
171 return "";
172 } else {
173 return "error mail() function";
174 }
175 }
176
177 // $data["to_name"]
178 // $data["to_email"]
179 // $data["subject"]
180 // $data["email_body"]
181 // $data["from_name"]
182 // $data["from_email"]
183 // $data["reply_name"]
184 // $data["reply_to"]
185 // $data["files"]
186 // $data["type"] ( text/plain (default) or text/html )
187 // $data["sender"] if empty, then noreply@$_SERVER["SERVER_NAME"]
188 // $data["bcc"]
189 // $data["smtp_host"]
190 // $data["smtp_port"]
191 // $data["smtp_login"]
192 // $data["smtp_password"]
193 // return "" if success of "error:..." if error
194 function cms_smtp_email( $data ) {
195 global $email_images, $cms;
196
197 if ( isset( $data["to_name"] ) ) {
198 $to = "=?utf-8?b?" . base64_encode( $data["to_name"] ) . "?= <" . $data["to_email"] . ">";
199 } else {
200 $to = $data["to_email"];
201 }
202
203 if ( isset( $data["from_name"] ) ) {
204 $from = "=?utf-8?b?" . base64_encode( $data["from_name"] ) . "?= <" . $data["from_email"] . ">";
205 } else {
206 $from = $data["from_email"];
207 }
208
209 if ( empty( $data["reply_to"] ) ) {
210 $reply = $from;
211 } else {
212 $reply = $data["reply_to"];
213 if ( ! empty( $data["reply_name"] ) ) {
214 $reply = "=?utf-8?b?" . base64_encode( $data["reply_name"] ) . "?= <" . $data["reply_to"] . ">";
215 }
216 }
217
218 $boundary = md5( uniqid( time() - 25 ) );
219 $boundary_id = md5( uniqid( time() ) );
220
221 if ( empty( $data["sender"] ) ) {
222 $sender = $data["from_email"];
223 } else {
224 $sender = $data["sender"];
225 }
226
227 if ( empty( $data["return_path"] ) ) {
228 $return_path = $data["from_email"];
229 } else {
230 $return_path = $data["return_path"];
231 }
232
233
234 /* start headers */
235 $SEND = "Date: " . date( "r" ) . "\r\n";
236 $SEND .= "Sender: {$sender}\r\n";
237 $SEND .= "Return-Path: {$return_path}\r\n";
238 $SEND .= "Reply-To: {$reply}\r\n";
239 $SEND .= "From: {$from}\r\n";
240 $SEND .= "To: {$to}\r\n";
241 if ( ! empty( $data["bcc"] ) ) { $SEND .= "Bcc: {$data['bcc']}\r\n"; }
242 $SEND .= "Subject: =?utf-8?b?" . base64_encode( $data["subject"] ) . "?=\r\n";
243 $SEND .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\r\n";
244 $SEND .= "\r\n";
245 /* end headers */
246
247 /* Move images to appendix */
248 $email_images = array();
249 $body2 = preg_replace_callback( '/<img +src="([^"]+)"/u', "cms_email_callback1", $data["email_body"] );
250
251 if ( empty( $data["type"] ) ) {
252 $type = "text/plain";
253 } else {
254 $type = $data["type"];
255 }
256
257 $SEND .= "--{$boundary}\r\nContent-Type: multipart/related; boundary=\"{$boundary_id}\"\r\n\r\n";
258 $SEND .= "--{$boundary_id}\r\nContent-Type: {$type}; charset=utf-8;\r\nContent-Transfer-Encoding: base64\r\n\r\n" . chunk_split( base64_encode( $body2 ) ) . "\r\n\r\n";
259
260 foreach( $email_images as $ind => $image ) {
261 $SEND .= "--{$boundary_id}\r\n";
262 $SEND .= "Content-Type: image/{$image['ext']}; name=\"{$ind}.{$image['ext']}\"\r\n";
263 $SEND .= "Content-ID: <{$ind}.{$image['ext']}>\r\n";
264 $SEND .= "Content-Disposition: inline; filename=\"{$ind}.{$image['ext']}\"\r\n";
265 $SEND .= "Content-transfer-encoding: base64\r\n\r\n";
266 $SEND .= chunk_split( $image['base64'] );
267 $SEND .= "\r\n\r\n";
268 }
269
270 if ( isset( $data["files"] ) && is_array( $data["files"] ) ) {
271 foreach( $data["files"] as $file ) {
272 $mime = mime_content_type( $file );
273 $name = preg_replace( "/.*\//u", "", $file );
274 $SEND .= "--{$boundary_id}\r\n";
275 $SEND .= "Content-Type: {$mime}; name=\"{$name}\"\r\n";
276 $SEND .= "Content-Transfer-Encoding: base64\r\n";
277 $SEND .= "Content-Disposition: attachment; filename=\"{$name}\"\r\n\r\n";
278 $SEND .= chunk_split( base64_encode( file_get_contents( $file ) ) ) . "\r\n\r\n";
279 }
280 }
281
282 $SEND .= "--{$boundary_id}--\r\n\r\n";
283 $SEND .= "--{$boundary}--\r\n\r\n";
284
285 $debug_file = "{$cms['cms_dir']}/smtp_debug.txt";
286 cms_debug( $debug_file, "\n---" );
287
288 // Connect
289 cms_debug( $debug_file, "fsockopen {$data['smtp_host']} {$data['smtp_port']}" );
290 $socket = fsockopen( $data["smtp_host"], $data["smtp_port"], $errno, $errstr, 10 ); // 10 sec timeout
291 if( $socket === false ) {
292 cms_debug( $debug_file, "fsockopen error {$errno} {$errstr}" );
293 return "{$errno} {$errstr}";
294 }
295 cms_debug( $debug_file, "fsockopen ok" );
296
297 stream_set_timeout( $socket, 3 );
298
299 // Receive data after connection
300 $ok = false;
301 while ( $r = fgets( $socket, 1000 ) ) {
302 cms_debug( $debug_file, "SERVER: {$r}" );
303 if ( substr( $r, 0, 3 ) === "220" ) { $ok = true; }
304 if ( substr( $r, 3, 1 ) === " " ) { break; }
305 }
306 if ( $ok === false ) {
307 return $r;
308 }
309
310 // HELLO
311 cms_debug( $debug_file, "ME: EHLO {$_SERVER['SERVER_NAME']}" );
312 fputs( $socket, "EHLO {$_SERVER['SERVER_NAME']}\r\n");
313
314 // Receive data after HELLO
315 $ok = false;
316 while ( $r = fgets( $socket, 1000 ) ) {
317 cms_debug( $debug_file, "SERVER: {$r}" );
318 if ( preg_match( '/250.AUTH/', $r ) ) { $ok = true; }
319 if ( substr( $r, 3, 1 ) === " " ) { break; }
320 }
321 if ( $ok === false ) {
322 fclose( $socket );
323 cms_debug( $debug_file, "The server does not greet us." );
324 return $r."\nThe server does not greet us.";
325 }
326
327 // AUTH
328 cms_debug( $debug_file, "ME: AUTH LOGIN" );
329 fputs( $socket, "AUTH LOGIN\r\n" );
330
331 // Receive data
332 $ok = false;
333 while ( $r = fgets( $socket, 1000 ) ) {
334 cms_debug( $debug_file, "SERVER: {$r}" );
335 if ( substr( $r, 0, 3 ) === "334" ) { $ok = true; }
336 if ( substr( $r, 3, 1 ) === " " ) { break; }
337 }
338 if ( $ok === false ) {
339 fclose( $socket );
340 cms_debug( $debug_file, "Can't find the answer to the authorization request." );
341 return "Can't find the answer to the authorization request.";
342 }
343
344 // Send login
345 cms_debug( $debug_file, "ME: base64_encode( smtp_login )" );
346 fputs( $socket, base64_encode( $data["smtp_login"] ) . "\r\n" );
347
348 // Receive data
349 $ok = false;
350 while ( $r = fgets( $socket, 1000 ) ) {
351 cms_debug( $debug_file, "SERVER: {$r}" );
352 if ( substr( $r, 0, 3 ) === "334" ) { $ok = true; }
353 if ( substr( $r, 3, 1 ) === " " ) { break; }
354 }
355 if ( $ok === false ) {
356 fclose( $socket );
357 cms_debug( $debug_file, "The authorization login was not accepted by the server." );
358 return "The authorization login was not accepted by the server.";
359 }
360
361 // Send password
362 cms_debug( $debug_file, "ME: base64_encode( smtp_password )" );
363 fputs( $socket, base64_encode( $data["smtp_password"] ) . "\r\n" );
364
365 // Receive data
366 $ok = false;
367 while ( $r = fgets( $socket, 1000 ) ) {
368 cms_debug( $debug_file, "SERVER: {$r}" );
369 if ( substr( $r, 0, 3 ) === "235" ) { $ok = true; }
370 if ( substr( $r, 3, 1 ) === " " ) { break; }
371 }
372 if ( $ok === false ) {
373 fclose( $socket );
374 cms_debug( $debug_file, "The password was not accepted by the server as correct." );
375 return "The password was not accepted by the server as correct.";
376 }
377
378 // Send FROM
379 cms_debug( $debug_file, "ME: MAIL FROM: <{$data['from_email']}>" );
380 fputs( $socket, "MAIL FROM: <{$data['from_email']}>\r\n" );
381
382 // Receive data
383 $ok = false;
384 while ( $r = fgets( $socket, 1000 ) ) {
385 cms_debug( $debug_file, "SERVER: {$r}" );
386 if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
387 if ( substr( $r, 3, 1 ) === " " ) { break; }
388 }
389 if ( $ok === false ) {
390 fclose( $socket );
391 cms_debug( $debug_file, "Can't send command MAIL FROM" );
392 return "Can't send command MAIL FROM";
393 }
394
395 // Send recipient
396 cms_debug( $debug_file, "ME: RCPT TO: <{$data['to_email']}>" );
397 fputs( $socket, "RCPT TO: <{$data['to_email']}>\r\n" );
398
399 // Receive data
400 $ok = false;
401 while ( $r = fgets( $socket, 1000 ) ) {
402 cms_debug( $debug_file, "SERVER: {$r}" );
403 if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
404 if ( substr( $r, 3, 1 ) === " " ) { break; }
405 }
406 if ( $ok === false ) {
407 fclose( $socket );
408 cms_debug( $debug_file, "Can't send RCPT TO command" );
409 return "Can't send RCPT TO command";
410 }
411
412 // BCC
413 if ( ! empty( $data["bcc"] ) ) {
414 cms_debug( $debug_file, "ME (bcc): RCPT TO: <{$data['bcc']}>" );
415 fputs( $socket, "RCPT TO: {$data['bcc']}\r\n" );
416
417 // Receive data
418 $ok = false;
419 while ( $r = fgets( $socket, 1000 ) ) {
420 cms_debug( $debug_file, "SERVER: {$r}" );
421 if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
422 if ( substr( $r, 3, 1 ) === " " ) { break; }
423 }
424 if ( $ok === false ) {
425 fclose( $socket );
426 cms_debug( $debug_file, "Can't send RCPT TO (bcc) command" );
427 return "Can't send RCPT TO (bcc) command";
428 }
429 }
430
431 // Email body command
432 cms_debug( $debug_file, "ME: DATA" );
433 fputs( $socket, "DATA\r\n" );
434
435 // Receive data
436 $ok = false;
437 while ( $r = fgets( $socket, 1000 ) ) {
438 cms_debug( $debug_file, "SERVER: {$r}" );
439 if ( substr( $r, 0, 3 ) === "354" ) { $ok = true; }
440 if ( substr( $r, 3, 1 ) === " " ) { break; }
441 }
442 if ( $ok === false ) {
443 fclose( $socket );
444 cms_debug( $debug_file, "Can't send DATA command" );
445 return "Can't send DATA command";
446 }
447
448 // Send email body
449 cms_debug( $debug_file, "ME SEND DATA" );
450 fputs( $socket, "{$SEND}\r\n.\r\n" );
451
452 // Receive data
453 $ok = false;
454 while ( $r = fgets( $socket, 1000 ) ) {
455 cms_debug( $debug_file, "SERVER: {$r}" );
456 if ( substr( $r, 0, 3 ) === "250" ) { $ok = true; }
457 if ( substr( $r, 3, 1 ) === " " ) { break; }
458 }
459 if ( $ok === false ) {
460 fclose( $socket );
461 cms_debug( $debug_file, "I can not send the body of the letter." );
462 return "I can not send the body of the letter.";
463 }
464
465 // Quit command
466 cms_debug( $debug_file, "ME: QUIT\n" );
467 fputs( $socket, "QUIT\r\n" );
468 fclose( $socket );
469 return "";
470 }
471
472 #endregion Функции отправки письма
473
474
475 function cms_debug( $debug_file, $string ) {
476 global $cms;
477 if ( empty( $cms["config"]["debug"] ) ) {
478 return;
479 }
480 // Следим за размером файла
481 if ( is_file( $debug_file ) && filesize( $debug_file ) > 16384 ) {
482 rename( $debug_file, $debug_file . ".old" );
483 }
484 // Сбрасываем инфу
485 if ( substr( $string, -1 ) !== "\n" ) { $string .= "\n"; }
486 file_put_contents( $debug_file, $string, FILE_APPEND );
487 }
488
489
490 // Функция для отправки файла браузеру малыми порциями,
491 // чтобы не было ошибок с закончившейся памятью
492 function cms_readfile( $file, $headers = true ) {
493 if ( file_exists( $file ) ) {
494 /*
495 if (ob_get_level()) {
496 ob_end_clean();
497 }
498 */
499 if ( $headers ) {
500 header( "Content-Description: File Transfer" );
501 $mime = mime_content_type( $file );
502 header( "Content-Type: {$mime}" );
503 $basename = basename( $file );
504 header( "Content-Disposition: attachment; filename=\"{$basename}\"" );
505 header( "Content-Transfer-Encoding: binary" );
506 header( "Expires: 0" );
507 header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
508 header( "Pragma: public" );
509 $filesize = filesize( $file );
510 header( "Content-Length: {$filesize}" );
511 ob_clean();
512 flush();
513 }
514 if ( $handle = fopen( $file, "rb" ) ) {
515 while ( ! feof( $handle ) ) {
516 print fread( $handle, 1024 );
517 }
518 return fclose( $handle );
519 } else {
520 return false;
521 }
522 } else {
523 return false;
524 }
525 }
526
527
528 // Принимает строку, которую нужно перевести
529 // и модуль ("page.mod.php") если нужно дернуть перевод из другого
530 function __( $string, $module = "" ) {
531 global $cms;
532
533 // Определяем вызвавший файл
534 $backtrace = debug_backtrace();
535 $basename = pathinfo( $backtrace[0]["file"], PATHINFO_BASENAME );
536 $basedir = basename( pathinfo( $backtrace[0]["file"], PATHINFO_DIRNAME ) );
537 if ( $module === "" ) {
538 $module = $basename;
539 // Автовыбор модуля для шаблона админки
540 if ( $basedir === "admin.cms" && $basename === "html.php" ) {
541 $module = "admin.mod.php";
542 }
543 }
544
545 // Загрузка файла перевода если еще не загружен
546 if ( ! isset( $cms["lang"][$module][ $cms["config"]["locale"] ] ) ) {
547 $file = $cms["cms_dir"] . "/lang/" . $cms["config"]["locale"] . "/" . $module;
548 if ( is_file( $file ) ) {
549 include_once( $file );
550 } else {
551 $cms["lang"][$module][ $cms["config"]["locale"] ] = array();
552 }
553 // load translit
554 if ( ! isset( $cms["tr"] ) ) $cms["tr"] = array();
555 $translit = $cms["cms_dir"] . "/lang/" . $cms["config"]["locale"] . "/translit.php";
556 if ( is_file( $translit ) ) {
557 include_once( $translit );
558 }
559 }
560
561 // Translate
562 if ( isset( $cms["lang"][$module][ $cms["config"]["locale"] ][$string] ) ) {
563 return $cms["lang"][$module][ $cms["config"]["locale"] ][$string];
564 } else {
565 // Чтобы узнать какие переводы отсутствуют, нужно включить отладку в config.php
566 // $cms["config"]["debug"] = true;
567 // Результаты буду в файле .cms/debug.log.php
568 if ( ! empty( $cms["config"]["debug"] ) && empty( $cms["debug"]["translate"][$string] ) ) {
569 $line = $backtrace[0]["line"];
570 $t = "translate to {$cms["config"]["locale"]}";
571 $f = "{$basename}:{$line}";
572 $cms["debug"][$t][$f] = $string;
573 }
574 return $string;
575 }
576 }
577
578
579 function cms_translit( $string, $trim_dash = true ) {
580 global $cms;
581 $tr1 = strtr( $string, $cms["tr"] );
582 $tr2 = strtr( $tr1, array( " " => "-" ) );
583 $tr3 = preg_replace( "/[^-A-Za-z0-9_]+/u", "", $tr2 );
584 if ( $trim_dash ) {
585 $tr3 = trim( $tr3, "-_" );
586 }
587 return $tr3;
588 }
589
590
591 function cms_translit_file( $string ) {
592 global $cms;
593 $tr1 = strtr( $string, $cms["tr"] );
594 $tr2 = strtr( $tr1, array( " " => "_" ) );
595 $tr3 = preg_replace( "/[^-A-Za-z0-9_]+/u", "", $tr2 );
596 return $tr3;
597 }
598
599
600 // Вспомогательная функция для последующей cms_asort()
601 function cms_uasort( $a, $b ) {
602 if ( ! isset( $a["sort"] ) || ! isset( $b["sort"] ) ) {
603 return 0;
604 }
605 if ( $a["sort"] <= $b["sort"] ) {
606 return -1;
607 } else {
608 return 1;
609 }
610 }
611 // Сортирует массив из элементов, которые тоже являются массивами
612 // и содержат ключ sort
613 function cms_asort( &$array ) {
614 if ( ! is_array( $array ) ) return false;
615 return uasort( $array, "cms_uasort" );
616 }
617
618
619 // Рекурсивное удаление папок
620 function recurse_rm( $src ) /* bool */ {
621 if ( ! is_dir( $src ) ) {
622 return false;
623 }
624 $dir = opendir( $src );
625 // readdir может вернуть аналог false, поэтому строгая проверка
626 while( false !== ( $file = readdir( $dir ) ) ) {
627 if ( ( $file != "." ) && ( $file != ".." ) ) {
628 if ( is_dir( "{$src}/{$file}" ) ) {
629 recurse_rm( "{$src}/{$file}" );
630 } else {
631 if ( ! unlink( "{$src}/{$file}" ) ) {
632 return false;
633 }
634 }
635 }
636 }
637 closedir( $dir );
638 return rmdir( $src );
639 }
640
641
642 function is_email( $str ) {
643 return preg_match( "/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,9})(\]?)$/", $str );
644 }
645
646
647 // Returns a file size limit in bytes based on the PHP upload_max_filesize
648 // and post_max_size
649 function file_upload_max_size() {
650 $max_size = -1;
651
652 if ( $max_size < 0 ) {
653 // Start with post_max_size.
654 $post_max_size = parse_size( ini_get( "post_max_size" ) );
655 if ( $post_max_size > 0 ) {
656 $max_size = $post_max_size;
657 }
658
659 // If upload_max_size is less, then reduce. Except if upload_max_size is
660 // zero, which indicates no limit.
661 $upload_max = parse_size( ini_get( "upload_max_filesize" ) );
662 if ( $upload_max > 0 && $upload_max < $max_size ) {
663 $max_size = $upload_max;
664 }
665 }
666 return $max_size;
667 }
668
669
670 function parse_size( $size ) {
671 $unit = preg_replace( "/[^bkmgtpezy]/i", "", $size ); // Remove the non-unit characters from the size.
672 $size = preg_replace( "/[^0-9\.]/", "", $size ); // Remove the non-numeric characters from the size.
673 if ( $unit ) {
674 // Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
675 return round( $size * pow( 1024, stripos( "bkmgtpezy", $unit[0] ) ) );
676 } else {
677 return round( $size );
678 }
679 }
680
681
682 // Возвращает true только если это пустая папка
683 function is_dir_and_empty( $dir ) {
684 if ( ! is_dir( $dir ) ) {
685 return false;
686 }
687 $handle = opendir( $dir );
688 while ( false !== ( $entry = readdir( $handle ) ) ) {
689 if ( $entry != "." && $entry != ".." ) {
690 closedir( $handle );
691 return false;
692 }
693 }
694 closedir( $handle );
695 return true;
696 }
697
698
699 // Генерация uid для всяких нужд
700 function cms_admin_pass_gen( $count = 8 ) {
701 $chars = "0123456789AaBbCcDdEeFfGgHhiJjKkLMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
702 $strlen = strlen( $chars ) - 1;
703 $password = "";
704 while ( $count-- ) {
705 $password .= $chars[ rand( 0, $strlen ) ];
706 }
707 return $password;
708 }
709
710
711 // Генерация uid для всяких нужд
712 function cms_uid( $count = 8 ) {
713 $chars = "0123456789AaBbCcDdEeFfGgHhiJjKkLMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
714 $strlen = strlen( $chars ) - 1;
715 $password = "";
716 while ( $count-- ) {
717 $password .= $chars[ rand( 0, $strlen ) ];
718 }
719 return $password;
720 }