OSDN Git Service

FIX:変数名の誤記を修正
[nucleus-jp/nucleus-next.git] / nucleus / libs / NOTIFICATION.php
1 <?php\r
2 /*\r
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)\r
4  * Copyright (C) 2002-2012 The Nucleus Group\r
5  *\r
6  * This program is free software; you can redistribute it and/or\r
7  * modify it under the terms of the GNU General Public License\r
8  * as published by the Free Software Foundation; either version 2\r
9  * of the License, or (at your option) any later version.\r
10  * (see nucleus/documentation/index.html#license for more info)\r
11  */\r
12 /**\r
13  * Class used to represent a collection of e-mail addresses, to which a\r
14  * message can be sent (e.g. comment or karma vote notification).\r
15  *\r
16  * @license http://nucleuscms.org/license.txt GNU General Public License\r
17  * @copyright Copyright (C) 2002-2012 The Nucleus Group\r
18  * @version $Id: NOTIFICATION.php 1534 2011-06-22 06:13:23Z sakamocchi $\r
19  */\r
20 class Notification\r
21 {\r
22         static private $charset;\r
23         static private $scheme = 'B';\r
24         \r
25         /**\r
26          * NOTIFICATION::address_validation()\r
27          * Validating the string as address\r
28          * \r
29          * FIXME: this is just migrated from globalfunctions.php\r
30          *  we should confirm this regular expression refering to RFC 5322\r
31          * \r
32          * @link        http://www.ietf.org/rfc/rfc5322.txt\r
33          * @see         3.4. Address Specification\r
34          * \r
35          * @static\r
36          * @param       String  $address        Address\r
37          * @return      Boolean valid or not\r
38          */\r
39         static public function address_validation($address)\r
40         {\r
41                 return (boolean) preg_match('#^(?!\\.)(?:\\.?[-a-zA-Z0-9!\\#$%&\'*+/=?^_`{|}~]+)+@(?!\\.)(?:\\.?(?!-)[-a-zA-Z0-9]+(?<!-)){2,}$#', $address);\r
42         }\r
43         \r
44         /**\r
45          * NOTIFICATION::get_mail_footer()\r
46          * Return mail footer with Nucleus CMS singnature\r
47          * \r
48          * @static\r
49          * @param       void\r
50          * @return      String  Message body with \r
51          */\r
52         static public function get_mail_footer()\r
53         {\r
54                 $message  = "\n";\r
55                 $message .= "\n";\r
56                 $message .= "-----------------------------\n";\r
57                 $message .=  "   Powered by Nucleus CMS\n";\r
58                 $message .=  "(http://www.nucleuscms.org/)\n";\r
59                 return $message;\r
60         }\r
61         \r
62         /**\r
63          * NOTIFICATION::mail\r
64          * Send mails with headers including 7bit-encoded multibyte string\r
65          * \r
66          * @static\r
67          * @param       string  $to             receivers including singlebyte and multibyte strings, based on RFC 5322\r
68          * @param       string  $subject        subject including singlebyte and multibyte strings\r
69          * @param       string  $message        message including singlebyte and multibyte strings\r
70          * @param       string  $from           senders including singlebyte and multibyte strings, based on RFC 5322\r
71          * @param       string(B/Q)     $scheme 7bit-encoder scheme based on RFC 2047\r
72          * @return      boolean accepted delivery or not\r
73          */\r
74         static public function mail($to, $subject, $message, $from, $charset, $scheme='B')\r
75         {\r
76                 self::$charset = $charset;\r
77                 self::$scheme = $scheme;\r
78                 \r
79                 $to = self::mailbox_list_encoder($to);\r
80                 $subject = self::seven_bit_characters_encoder($subject);\r
81                 $from = 'From: ' . self::mailbox_list_encoder($from);\r
82                 \r
83                 /*\r
84                  * All of 7bit character encoding derives from ISO/IEC 646\r
85                  * So we can decide the body's encoding bit count by this regular expression.\r
86                  * \r
87                  */\r
88                 $bitcount = '8bit';\r
89                 if ( preg_match('#\A[\x00-\x7f]*\z#', $message) )\r
90                 {\r
91                         $bitcount = '7bit';\r
92                 }\r
93                 \r
94                 $header  = 'Content-Type: text/html; charset=' . self::$charset . "; format=flowed; delsp=yes\n";\r
95                 $header .= "Content-Transfer-Encoding: {$bitcount}\n";\r
96                 $header .= "X-Mailer: Nucleus CMS NOTIFICATION class\n";\r
97                 \r
98                 return mail($to, $subject, $message, "{$from}\n{$header}");\r
99         }\r
100         \r
101         /**\r
102          * NOTIFICATION::mailbox_list_encoder\r
103          * Encode multi byte strings included in mailbox.\r
104          * The format of mailbox is based on RFC 5322, which obsoletes RFC 2822\r
105          * \r
106          * @link        http://www.ietf.org/rfc/rfc5322.txt\r
107          * @see         3.4. Address Specification\r
108          * \r
109          * @static\r
110          * @param       string  $mailbox_list           mailbox list\r
111          * @return      string  encoded string  \r
112          * \r
113          */\r
114         static private function mailbox_list_encoder ($mailbox_list)\r
115         {\r
116                 $encoded_mailboxes = array();\r
117                 $mailboxes = preg_split('#,#', $mailbox_list);\r
118                 foreach ( $mailboxes as $mailbox )\r
119                 {\r
120                         if ( preg_match("#^([^,]+)?<([^,]+)?@([^,]+)?>$#", $mailbox, $match) )\r
121                         {\r
122                                 $display_name = self::seven_bit_characters_encoder(trim($match[1]));\r
123                                 $local_part = trim($match[2]);\r
124                                 $domain = trim($match[3]);\r
125                                 $encoded_mailboxes[] = "{$display_name} <{$local_part}@{$domain}>";\r
126                         }\r
127                         else if ( preg_match("#([^,]+)?@([^,]+)?#", $mailbox) )\r
128                         {\r
129                                 $encoded_mailboxes[] = $mailbox;\r
130                         }\r
131                         else\r
132                         {\r
133                                 continue;\r
134                         }\r
135                 }\r
136                 if ( $encoded_mailboxes == array() )\r
137                 {\r
138                         return FALSE;\r
139                 }\r
140                 return implode(',', $encoded_mailboxes);\r
141         }\r
142         \r
143         /**\r
144          * NOTIFICATION::seven_bit_characters_encoder\r
145          * Encoder into 7bit ASCII expression for Non-ASCII Text based on RFC 2047.\r
146          * \r
147          * @link http://www.ietf.org/rfc/rfc2047.txt\r
148          * @see 2. Syntax of encoded-words\r
149          * \r
150          * NOTE: RFC 2047 has a ambiguousity for dealing with 'linear-white-space'.\r
151          *  This causes a trouble related to line breaking between single byte and multi-byte strings.\r
152          *  To avoid this, single byte string is encoded as well as multi byte string here.\r
153          * \r
154          * NOTE: RFC 2231 also defines the way to use non-ASCII characters in MIME header.\r
155          * http://www.ietf.org/rfc/rfc2231.txt\r
156          * \r
157          * NOTE: iconv extension give the same functions as this in PHP5\r
158          * iconv_mime_encode():\r
159          * http://www.php.net/manual/en/function.iconv-mime-encode.php\r
160          * \r
161          * @static\r
162          * @param       string  $charset        Character set encoding\r
163          * @param       string  $type   type of 7 bit encoding, should be 'B' or 'Q'\r
164          * @param       string  $string Target string with header field\r
165          * @return      string  encoded string\r
166          * \r
167          */\r
168         static private function seven_bit_characters_encoder($string)\r
169         {\r
170                 $header = chr(13) . chr(10) . chr(32) . '=?' . self::$charset . '?' . self::$scheme . '?';\r
171                 $footer = "?=";\r
172                 $restriction = 78 - strlen($header) - strlen($footer) ;\r
173                 \r
174                 $encoded_words = array();\r
175                 for ( $i = 0; $i < i18n::strlen($string); $i++ )\r
176                 {\r
177                         if ( self::$scheme == 'B' )\r
178                         {\r
179                                 if ( $i == 0 )\r
180                                 {\r
181                                         $letters = '';\r
182                                 }\r
183                                 \r
184                                 $letter = i18n::substr($string, $i, 1);\r
185                                 $expected_length = strlen($letters) + strlen($letter) * 4 / 3;\r
186                                 \r
187                                 if ( $expected_length > $restriction )\r
188                                 {\r
189                                         $encoded_text = self::b_encoder($letters);\r
190                                         $encoded_words[] = "{$header}{$encoded_text}{$footer}";\r
191                                         $letters = '';\r
192                                 }\r
193                                 \r
194                                 $letters .= $letter;\r
195                                 \r
196                                 if ( $i == i18n::strlen($string) - 1 )\r
197                                 {\r
198                                         $encoded_text = self::b_encoder($letters);\r
199                                         $encoded_words[] = "{$header}{$encoded_text}{$footer}";\r
200                                         break;\r
201                                 }\r
202                                 continue;\r
203                         }\r
204                         else\r
205                         {\r
206                                 if ( $i == 0 )\r
207                                 {\r
208                                         $encoded_text = '';\r
209                                 }\r
210                                 \r
211                                 $encoded_letter = self::q_encoder(i18n::substr($string, $i, 1));\r
212                                 $expected_length = strlen($encoded_text) + strlen($encoded_letter);\r
213                                 \r
214                                 if ( $expected_length > $restriction )\r
215                                 {\r
216                                         $encoded_words[] = "{$header}{$encoded_text}{$footer}";\r
217                                         $letters = '';\r
218                                 }\r
219                                 \r
220                                 $encoded_text .= $encoded_letter;\r
221                                 \r
222                                 if ( $i == i18n::strlen($string) - 1 )\r
223                                 {\r
224                                         $encoded_words[] = "{$header}{$encoded_text}{$footer}";\r
225                                         break;\r
226                                 }\r
227                                 continue;\r
228                         }\r
229                 }\r
230                 \r
231                 return implode('', $encoded_words);\r
232         }\r
233         \r
234         /**\r
235          * NOTIFICATION::b_encoder()\r
236          * \r
237          * B encoder according to RFC 2047.\r
238          * The "B" encoding is identical to the "BASE64" encoding defined by RFC 4648.\r
239          * \r
240          * @link http://www.ietf.org/rfc/rfc4648.txt\r
241          * @see 6.8. Base64 Content-Transfer-Encoding\r
242          * \r
243          * NOTE: According to RFC 4648\r
244          * (1)  The final quantum of encoding input is an integral multiple of 24 bits;\r
245          *              here, the final unit of encoded output will be an integral multiple\r
246          *              of 4 characters with no "=" padding.\r
247          * (2)  The final quantum of encoding input is exactly 8 bits; here,\r
248          *              the final unit of encoded output will be two characters followed\r
249          *              by two "=" padding characters.\r
250          * (3)  The final quantum of encoding input is exactly 16 bits; here,\r
251          *              the final unit of encoded output will be three characters followed\r
252          *              by one "=" padding character.\r
253          * \r
254          * @static\r
255          * @param       string  $target targetted string\r
256          * @return      string  encoded string\r
257          */\r
258         static private function b_encoder($target)\r
259         {\r
260                 return base64_encode($target);\r
261         }\r
262         \r
263         /**\r
264          * NOTIFICATION::q_encoder()\r
265          * \r
266          * Q encoder according to RFC 2047.\r
267          * The "Q" encoding is similar to "Quoted-Printable" content-transfer-encoding defined in RFC 2045,\r
268          *  but the "Q" encoding and the "Quoted-Printable" are different a bit.\r
269          * \r
270          * @link http://www.ietf.org/rfc/rfc2047.txt\r
271          * @see 4.2. The "Q" encoding\r
272          * \r
273          * NOTE: According to RFC 2047\r
274          * (1)  Any 8-bit value may be represented by a "=" followed by two hexadecimal digits.\r
275          *              For example, if the character set in use were ISO-8859-1,\r
276          *              the "=" character would thus be encoded as "=3D", and a SPACE by "=20".\r
277          *              (Upper case should be used for hexadecimal digits "A" through "F".)\r
278          * (2)  The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be\r
279          *              represented as "_" (underscore, ASCII 95.).\r
280          *              (This character may not pass through some internetwork mail gateways,\r
281          *              but its use will greatly enhance readability of "Q" encoded data\r
282          *              with mail readers that do not support this encoding.)\r
283          *              Note that the "_" always represents hexadecimal 20,\r
284          *              even if the SPACE character occupies a different code position\r
285          *              in the character set in use.\r
286          * (3)  8-bit values which correspond to printable ASCII characters\r
287          *              other than "=", "?", and "_" (underscore), MAY be represented as those characters.\r
288          *              (But see section 5 for restrictions.)\r
289          *              In particular, SPACE and TAB MUST NOT be represented as themselves within encoded words.\r
290          * \r
291          * @static\r
292          * @param       string  $target targetted string\r
293          * @return      string  encoded string\r
294          */\r
295         static private function q_encoder($target)\r
296         {\r
297                 $string = '';\r
298                 \r
299                 for ( $i = 0; $i < strlen($target); $i++ )\r
300                 {\r
301                         $letter = substr ($target, $i, 1);\r
302                         $order = ord($letter);\r
303                         \r
304                         // Printable ASCII characters without "=", "?", "_"\r
305                         if ((33 <= $order && $order <= 60)\r
306                          || (62 == $order)\r
307                          || (64 <= $order && $order <= 94)\r
308                          || (96 <= $order && $order <= 126))\r
309                         {\r
310                                 $string .= strtoupper(dechex($order));\r
311                         }\r
312                         // Space shuold be encoded as the same strings as "_"\r
313                         else if ($order == 32)\r
314                         {\r
315                                 $string .= '_';\r
316                         }\r
317                         // Other characters\r
318                         else\r
319                         {\r
320                                 $string .= '=' . strtoupper(dechex($order));\r
321                         }\r
322                 }\r
323                 \r
324                 return $string;\r
325         }\r
326         \r
327         /**\r
328          * NOTICE: Deprecated\r
329          * NOTIFICATION::$addresses\r
330          * \r
331          * @deprecated\r
332          */\r
333         private $addresses = array();\r
334         \r
335         /**\r
336          * NOTICE: Deprecated\r
337          * takes one string as argument, containing multiple e-mail addresses\r
338          * separated by semicolons\r
339          * eg: site@demuynck.org;nucleus@demuynck.org;foo@bar.com\r
340          * \r
341          * @deprecated\r
342          */\r
343         function __construct($addresses)\r
344         {\r
345                 $this->addresses = preg_split('#;#' , $addresses);\r
346         }\r
347         \r
348         /**\r
349          * NOTICE: Deprecated\r
350          * NOTIFICATION::validAddresses()\r
351          * \r
352          * returns true if all addresses are valid\r
353          * \r
354          * @deprecated\r
355          * @param       Void\r
356          * @return      Boolean\r
357          */\r
358         function validAddresses()\r
359         {\r
360                 foreach ( $this->addresses as $address )\r
361                 {\r
362                         if ( !self::address_validation(trim($address)) )\r
363                         {\r
364                                 return 0;\r
365                         }\r
366                 }\r
367                 return 1;\r
368         }\r
369         \r
370         /**\r
371          * NOTICE: Deprecated\r
372          * NOTIFICATION::notify()\r
373          * \r
374          * Sends email messages to all the email addresses\r
375          * \r
376          * @deprecated\r
377          * @param       String  $title  \r
378          * @param       String  $message        \r
379          * @param       String  $from   \r
380          * @return      Void\r
381          */\r
382         function notify($title, $message, $from)\r
383         {\r
384                 global $member;\r
385                 $addresses = array();\r
386                 \r
387                 foreach ($this->addresses as $address)\r
388                 {\r
389                         if ( $member->isLoggedIn() && ($member->getEmail() == $address) )\r
390                         {\r
391                                 continue;\r
392                         }\r
393                         $addresses[] = $address;\r
394                 }\r
395                 \r
396                 self::mail(implode(',', $addresses), $title, $message , $from);\r
397                 return;\r
398         }\r
399 }\r