ここの情報は古いです。ご理解頂いた上でお取り扱いください。

source: OpenPNE/branches/stable-2.10.x/webapp/lib/OpenPNE/KtaiMail.php @ 6930

Last change on this file since 6930 was 6930, checked in by ebihara, 13 years ago

#2030:日記・トピックコメントを添付画像付きでメール投稿する際に、ファイルサイズがIMAGE_MAX_FILESIZEを超過しているか、GIF,JPEG,PNGに正しく変換できない場合にエラーメールを送信して日記・トピックコメントへの投稿をおこなわないようにした

File size: 10.2 KB
Line 
1<?php
2/**
3 * @copyright 2005-2007 OpenPNE Project
4 * @license   http://www.php.net/license/3_01.txt PHP License 3.01
5 */
6
7// PEAR::Mail_mimeDecode
8require_once 'Mail/mimeDecode.php';
9
10/**
11 * OpenPNE_KtaiMail
12 * 携帯メール用のメールデコーダ
13 */
14class OpenPNE_KtaiMail
15{
16    /**
17     * デコード結果
18     * @var stdClass
19     */ 
20    var $mail;
21
22    /** @var string 変換元文字エンコーディング(デフォルト値) */
23    var $from_encoding = 'auto';
24
25    /** @var string 変換先文字エンコーディング */
26    var $to_encoding = 'UTF-8';
27
28    /** @var string 画像検証用のテンポラリディレクトリ */
29    var $img_tmp_dir;
30
31    /** @var string 画像検証用のテンポラリファイルの接頭辞 */
32    var $img_tmp_prefix = 'OpenPNE_KtaiMail_';
33
34    /** @var string 画像の最大ファイルサイズ(byte) */
35    var $img_max_filesize;
36
37    /** @var bool 全角スペースを削除するかどうか */
38    var $trim_doublebyte_space = true;
39
40    /**
41     * constructor
42     *
43     * @access public
44     * @param string $options
45     *      - from_encoding    : 変換元文字エンコーディング
46     *      - to_encoding      : 変換先文字エンコーディング
47     *      - img_tmp_dir      : 画像検証用のテンポラリディレクトリ
48     *      - img_tmp_prefix   : 画像検証用のテンポラリファイルの接頭辞
49     *      - img_max_filesize : 画像の最大ファイルサイズ
50     *      - trim_doublebyte_space : 全角スペースを削除するかどうか
51     */
52    function OpenPNE_KtaiMail($options = array())
53    {
54        foreach ($options as $key => $value) {
55            switch ($key) {
56            case 'from_encoding':
57                $this->from_encoding = $value;
58                break;
59            case 'to_encoding':
60                $this->to_encoding = $value;
61                break;
62            case 'img_tmp_dir':
63                $this->img_tmp_dir = $value;
64                break;
65            case 'img_tmp_prefix':
66                $this->img_tmp_prefix = $value;
67                break;
68            case 'img_max_filesize':
69                $this->img_max_filesize = $value;
70                break;
71            case 'trim_doublebyte_space':
72                $this->trim_doublebyte_space = (bool)$value;
73                break;
74            }
75        }
76    }
77
78    /**
79     * メールをデコード
80     *
81     * @access public
82     * @param string メールの生データ
83     */
84    function decode($raw_mail)
85    {
86        $params['include_bodies'] = true;
87        $params['decode_bodies']  = true;
88        $params['decode_headers'] = true;
89        $params['input'] = $raw_mail;
90
91        $this->mail =& Mail_mimeDecode::decode($params);
92    }
93
94    /**
95     * ヘッダー(From:)から送信元メールアドレスを取得
96     *
97     * @access public
98     * @return string Fromメールアドレス
99     */
100    function get_from()
101    {
102        return $this->_get_mail_address($this->mail->headers['from']);
103    }
104
105    /**
106     * ヘッダー(To:)から宛先メールアドレスを取得
107     *
108     * @access public
109     * @return string Toメールアドレス
110     */
111    function get_to()
112    {
113        return $this->_get_mail_address($this->mail->headers['to']);
114    }
115
116    /**
117     * Subject の内容を抽出(+文字コード変換)
118     *
119     * @access public
120     * @return string Subject
121     */
122    function get_subject()
123    {
124        return isset($this->mail->headers['subject']) ?
125                    $this->convert_text($this->mail->headers['subject']) : '';
126    }
127
128    /**
129     * メール本文からテキストを抽出(+文字コード変換)
130     *
131     * @access public
132     * @return string メール本文のテキスト
133     */
134    function get_text_body()
135    {
136        return $this->_get_text_body($this->mail);
137    }
138
139    /** @access private */
140    function _get_text_body(&$mail)
141    {
142        $body = '';
143
144        if (isset($mail->parts) && is_array($mail->parts)) {
145            // multipart
146            foreach ($mail->parts as $part) {
147                if ($body = $this->_get_text_body($part)) break;
148            }
149        } elseif (strtolower($mail->ctype_primary) === 'text' &&
150                  strtolower($mail->ctype_secondary) === 'plain') {
151            $body = $mail->body;
152            $charset = $mail->ctype_parameters['charset'];
153
154            $body = $this->convert_text($body, $charset);
155        }
156
157        return $body;
158    }
159
160    /**
161     * メールから画像データを抽出
162     *
163     * @access public
164     * @return array 画像データ配列
165     */
166    function get_images()
167    {
168        return $this->_get_images($this->mail);
169    }
170
171    /** @access private */
172    function _get_images(&$mail)
173    {
174        $allowed_type = array('jpeg', 'gif', 'png');
175        $images = array();
176
177        if (isset($mail->parts) && is_array($mail->parts)) {
178            // multipart
179            foreach ($mail->parts as $part) {
180                $item = $this->_get_images($part);
181                if ($item === false) {
182                    return false;
183                }
184
185                $images = array_merge($images, $item);
186            }
187        } elseif (strtolower($mail->ctype_primary) === 'image' &&
188                  in_array(strtolower($mail->ctype_secondary), $allowed_type)) {
189            $image_data = $mail->body;
190            $image_ext = '';
191
192             // 画像かどうかチェック
193            if (!@imagecreatefromstring($image_data)) {
194                // base64_decodeしてリトライ
195                $image_data = base64_decode($image_data);
196                if (!@imagecreatefromstring($image_data)) {
197                    return false;
198                }
199            }
200
201            // 一時ファイルを作成
202            $tmpfname = tempnam($this->img_tmp_dir, $this->img_tmp_prefix);
203
204            $fp = fopen($tmpfname, 'wb');
205            fwrite($fp, $image_data);
206            fclose($fp);
207
208            // 画像サイズのチェック
209            if ($this->img_max_filesize && filesize($tmpfname) > $this->img_max_filesize) {
210                unlink($tmpfname);
211                return false;
212            }
213
214            // 画像のリサイズ
215            list($width, $height, $type, $attr) = @getimagesize($tmpfname);
216            $need_resize = false;
217            $original_width = $width;
218            $original_height = $height;
219            //横のサイズが、指定されたサイズより大きい場合
220            if (IMAGE_MAX_WIDTH && ($width > IMAGE_MAX_WIDTH)) {
221                $need_resize = true;
222                $height = $height * (IMAGE_MAX_WIDTH / $width);
223                $width = IMAGE_MAX_WIDTH;
224            }
225            //縦サイズが、指定されたサイズより大きい場合
226            if (IMAGE_MAX_HEIGHT && ($height > IMAGE_MAX_HEIGHT)) {
227                $need_resize = true;
228                $width = $width * (IMAGE_MAX_HEIGHT / $height);
229                $height = IMAGE_MAX_HEIGHT;
230            }
231            if ($height < 1.) {
232                $height = 1;
233            }
234            if ($width < 1.) {
235                $width = 1;
236            }
237            if ($need_resize) {
238                resize_image($type, $tmpfname, $tmpfname, $original_width, $original_height, $width, $height);
239                $fp = fopen($tmpfname, 'rb');
240                $image_data = fread($fp, filesize($tmpfname));  // 一時ファイルを再度読み込み
241                fclose($fp);
242            }
243
244            // 画像が正しいかどうかチェック
245            switch (strtolower($mail->ctype_secondary)) {
246            case 'jpeg':
247                if (!@imagecreatefromjpeg($tmpfname)) {
248                    $image_data = '';
249                } else {
250                    $image_ext = 'jpg';
251                }
252                break;
253            case 'gif':
254                if (!@imagecreatefromgif($tmpfname)) {
255                    $image_data = '';
256                } else {
257                    $image_ext = 'gif';
258                }
259                break;
260            case 'png':
261                if (!@imagecreatefrompng($tmpfname)) {
262                    $image_data = '';
263                } else {
264                    $image_ext = 'png';
265                }
266                break;
267            }
268            unlink($tmpfname);
269
270            if ($image_data && $image_ext) {
271                $images = array(array('data' => $image_data, 'ext' => $image_ext));
272            }
273        }
274
275        return $images;
276    }
277
278    /**
279     * 文字列からメールアドレスを抽出
280     *
281     * @access private
282     * @param string $str 入力文字列
283     * @return string メールアドレス
284     */
285    function _get_mail_address($str)
286    {
287        if (!$str) {
288            return false;
289        }
290
291        // "(ダブルクォーテーション)を取り除く
292        // "example"@docomo.ne.jp
293        $str = str_replace('"', '', $str);
294
295        // <example@docomo.ne.jp> というメールアドレスになることがある。
296        //   日本語 <example@docomo.ne.jp>
297        // のような場合に複数マッチする可能性があるので、
298        // マッチした最後のものを取ってくるように変更
299        $matches = array();
300        $regx = '/([\.\w!#$%&\'*+\-\/=?^`{|}~]+@[\w!#$%&\'*+\-\/=?^`{|}~]+(\.[\w!#$%&\'*+\-\/=?^`{|}~]+)*)/';
301        if (preg_match_all($regx, $str, $matches)) {
302            return array_pop($matches[1]);
303        }
304
305        return false;
306    }
307
308    /**
309     * 文字エンコーディングの変換、空白文字の削除
310     *
311     * @access public
312     * @param string $str 変換前の文字列
313     * @param string $from_encoding
314     * @param string $to_encoding
315     * @return string 変換後の文字列
316     */
317    function convert_text($str, $from_encoding = '', $to_encoding = '')
318    {
319        if (!$from_encoding) $from_encoding = $this->from_encoding;
320        if (!$to_encoding)   $to_encoding = $this->to_encoding;
321
322        $str = mb_convert_encoding($str, $to_encoding, $from_encoding);
323
324        // 空白文字の削除
325        $str = str_replace("\0", '', $str);
326        if ($this->trim_doublebyte_space) {
327            $str = mb_ereg_replace('([\s ])+$', '', $str);
328        } else {
329            $str = rtrim($str);
330        }
331
332        return $str;
333    }
334}
335
336?>
Note: See TracBrowser for help on using the repository browser.