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