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