2 // vim: tabstop=2:shiftwidth=2
5 * NP_Moblog ($Revision: 1.1 $)
6 * by hsur ( http://blog.cles.jp/np_cles )
7 * $Id: NP_Moblog.php,v 1.1 2008-05-04 07:04:50 hsur Exp $
9 * Based on NP_HeelloWorld v0.8
10 * http://nakahara21.com/?itemid=133
14 * Copyright (C) 2003 nakahara21 All rights reserved.
15 * Copyright (C) 2004-2007 cles All rights reserved.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 * In addition, as a special exception, mamio and cles gives
32 * permission to link the code of this program with those files in the PEAR
33 * library that are licensed under the PHP License (or with modified versions
34 * of those files that use the same license as those files), and distribute
35 * linked combinations including the two. You must obey the GNU General Public
36 * License in all respects for all of the code used other than those files in
37 * the PEAR library that are licensed under the PHP License. If you modify
38 * this file, you may extend this exception to your version of the file,
39 * but you are not obligated to do so. If you do not wish to do so, delete
40 * this exception statement from your version.
44 require_once($DIR_LIBS . 'MEDIA.php');
47 require_once(dirname(__FILE__).'/sharedlibs/sharedlibs.php');
48 require_once('Net/POP3.php');
49 require_once('Mail/mimeDecode.php');
50 require_once('Mail/RFC822.php');
54 if( ! version_compare(phpversion() , $required , '>=') ){
55 ACTIONLOG :: add(WARNING, 'NP_MoblogはPHP>=4.3.0であることが必要です。');
58 if (!function_exists('sql_table')) {
59 function sql_table($name) {
60 return 'nucleus_'.$name;
64 class NP_Moblog extends NucleusPlugin {
72 function getAuthor() {
76 // an URL to the plugin website
77 // can also be of the form mailto:foo@bar.com
79 return 'http://blog.cles.jp/np_cles/category/31/subcatid/2';
82 // version of the plugin
83 function getVersion() {
87 function hasAdminArea() {
91 function getEventList() {
92 return array('PrePluginOptionsEdit');
95 function event_PrePluginOptionsEdit(&$data) {
96 switch($data['context']){
99 $m =& MEMBER :: createFromID($data['contextid']);
107 $res = mysql_query('SELECT bnumber, bname FROM '.sql_table('blog'));
108 while( $o = mysql_fetch_object($res) ){
109 if( $m->isTeamMember($o->bnumber) ){
110 $blogs[$o->bnumber] = $o->bname;
114 $idandcatTypeInfo = '';
115 foreach($blogs as $blogid => $blogname){
116 $res = mysql_query('SELECT catid, cname FROM '.sql_table('category').' WHERE cblog='.$blogid);
117 if( @mysql_num_rows($res) > 0) {
118 while( $o = mysql_fetch_object($res) ){
119 if($idandcatTypeInfo)
120 $idandcatTypeInfo .= '|';
121 $o->cname = strtr($o->cname, $trimChar);
122 $blogname = strtr($blogname, $trimChar);
123 $idandcatTypeInfo .= "{$o->cname} ({$blogname})|{$blogid},{$o->catid}";
127 if( ! $idandcatTypeInfo ){
128 $idandcatTypeInfo = "!!投稿可能なblogがありません!!|0,0";
131 // collection & thumb_col
132 $collections = MEDIA::getCollectionList();
133 $mid = intval($m->getID());
134 $collections[$mid] = 'デフォルト(useridディレクトリ)';
136 $collectionTypeInfo = '';
137 foreach( $collections as $collection => $name ){
138 if($collectionTypeInfo) $collectionTypeInfo .= '|';
139 $name = strtr($name, $trimChar);
140 $collection = strtr($collection, $trimChar);
141 $collectionTypeInfo .= "{$name}|{$collection}";
145 foreach($data['options'] as $oid => $option ){
146 switch($data['options'][$oid]['name']){
148 $data['options'][$oid]['typeinfo'] = $idandcatTypeInfo;
152 $data['options'][$oid]['typeinfo'] = $collectionTypeInfo;
164 $this->createMemberOption('enable', 'プラグインを有効にするか?', 'yesno', 'no');
166 $this->createMemberOption('host', 'POP3 ホスト名', 'text', 'localhost');
167 $this->createMemberOption('port', 'POP3 ポート', 'text', '110', 'numerical=true');
168 $this->createMemberOption('user', 'POP3 ユーザー名', 'text', '');
169 $this->createMemberOption('pass', 'POP3 パスワード', 'password', '');
170 $this->createMemberOption('useAPOP', 'APOPを使用するか?', 'yesno', 'no');
172 $this->createMemberOption('idandcat', 'Nucleusカテゴリ(Blog)', 'select', '', '');
174 $this->createMemberOption('collection', '画像を保存するディレクトリ', 'select', '', '');
175 $this->createMemberOption('thumb_col', 'サムネイルをを保存するディレクトリ', 'select', '', '');
177 $this->createMemberOption('imgonly', 'イメージ添付メールのみ追加?', 'yesno', 'no');
178 $this->createMemberOption('DefaultPublish', 'デフォルトで公開するか?', 'yesno', 'no');
180 $this->createMemberOption('optionsKeyword', 'オプション記述開始の区切り文字', 'text', '@');
181 $this->createMemberOption('blogKeyword', 'オプションでblogidを指定する場合のキー', 'text', 'b');
182 $this->createMemberOption('categoryKeyword', 'オプションでカテゴリを指定する場合のキー', 'text', 'c');
183 $this->createMemberOption('publishKeyword', 'オプションでストレートにpublish指定する場合のキー', 'text', 's');
185 $this->createMemberOption('moreDelimiter', '追記にする場合の区切り文字(利用しない場合は空欄)', 'text', '');
187 $this->createMemberOption('accept', '投稿許可アドレス(複数の場合改行で区切ってください)', 'textarea', '');
188 $this->createMemberOption('acceptSubjectPrefix','投稿許可SubjectPrefix(制限無しの場合は空欄)','text','');
190 $this->createMemberOption('nosubject', '件名がないときの題名', 'text', '');
191 $this->createMemberOption('no_strip_tags', 'htmlメールの場合に除去しないタグ', 'textarea', '<title><hr><h1><h2><h3><h4><h5><h6><div><p><pre><sup><ul><ol><br><dl><dt><table><caption><tr><li><dd><th><td><a><area><img><form><input><textarea><button><select><option>');
192 $this->createMemberOption('maxbyte', '最大添付量(B)', 'text', '300000', 'numerical=true');
193 $this->createMemberOption('subtype', '対応MIMEタイプ(正規表現)', 'text', 'gif|jpe?g|png|bmp|octet-stream|x-pmd|x-mld|x-mid|x-smd|x-smaf|x-mpeg|pdf');
194 $this->createMemberOption('viri', '保存しないファイル(正規表現)', 'text', '.+\.exe$|.+\.zip$|.+\.pif$|.+\.scr$');
195 $this->createMemberOption('imgExt', '画像ファイルの拡張子(正規表現)', 'text', '.+\.png$|.+\.jpe?g$|.+\.gif$|.+\.bmp$');
197 $this->createMemberOption('thumb_ok', 'サムネイルを使用する?', 'yesno', 'yes');
198 $this->createMemberOption('W', 'サムネイルの大きさ(Width)', 'text', '120', 'numerical=true');
199 $this->createMemberOption('H', 'サムネイルの大きさ(Hight)', 'text', '120', 'numerical=true');
200 $this->createMemberOption('thumb_ext', 'サムネイルを作る対象画像', 'text', '.+\.jpe?g$|.+\.png$');
201 $this->createMemberOption('smallW', 'アイテム内に表示する画像の最大横幅', 'text', '120', 'numerical=true');
203 $this->createMemberOption('textTpl', 'テキストテンプレート', 'textarea', '<%body%>');
204 $this->createMemberOption('withThumbTpl', 'サムネイル付きテンプレート', 'textarea', '<div class="leftbox"><a href="<%mediaUrl%><%imageUrl%>" target="_blank"><%image(<%thumbUrl%>|<%thumbW%>|<%thumbH%>|)%></a></div><%body%>');
205 $this->createMemberOption('withoutThumbTpl', 'サムネイルなしテンプレート', 'textarea', '<div class="leftbox"><%image(<%imageUrl%>|<%sizeW%>|<%sizeH%>|)%></div><%body%>');
206 $this->createMemberOption('reductionTpl', 'サムネイルなしテンプレート(縮小)', 'textarea', '<div class="leftbox"><a href="<%mediaUrl%><%imageUrl%>" target="_blank"><%image(<%imageUrl%>|<%reductionW%>|<%reductionH%>|)%></a></div><%body%>');
207 $this->createMemberOption('dataTpl', 'データファイルテンプレート', 'textarea', '<div class="leftbox"><a href="<%mediaUrl%><%imageUrl%>" target="_blank"><%fileName%></a></div><%body%>');
209 $this->createOption('execMode', '動作モード', 'select', '1', '振分対応モード|0|互換モード|1');
210 $this->createOption('spamCheck', 'SPAMチェックを有効にする', 'yesno', 'no');
212 $this->createOption('interval', 'メール取得の間隔(秒)', 'text', '600', 'numerical=true');
213 $this->createOption('nextUpdate', '次回更新時刻(変更できません)', 'text', '-', 'access=readonly');
214 $this->createOption('lastUpdate', '最終更新時刻(UnixTimeStamp,)', 'text', '0', 'access=hidden');
215 $this->createOption('debug', 'ログを出力を行うか?', 'yesno', 'no');
218 function unInstall() {}
219 function getMinNucleusVersion() { return 320; }
220 function getMinNucleusPatchLevel() { return 0; }
222 // a description to be shown on the installed plugins listing
223 function getDescription() {
224 return '[$Revision: 1.1 $]<br />メールを拾ってアイテムを追加します。<%Moblog%>の記述のあるスキンを適用するページを開くと実行されます。<br />
225 <%Moblog(link)%>と記入することでメールを取得するためのリンクを表示することができます(要ログイン)<br />
226 個人ごとに設定ができるようになりましたので「あなたの設定」か「メンバー管理」から設定を行ってください。';
229 function supportsFeature($what) {
231 case 'SqlTablePrefix' :
239 function _info($msg) {
240 if ($this->getOption('debug') == 'yes') {
241 ACTIONLOG :: add(INFO, 'Moblog: '.$msg);
245 function _warn($msg) {
246 ACTIONLOG :: add(WARNING, 'Moblog: '.$msg);
249 function _getEnableUserId() {
250 $userOptions = $this->getAllMemberOptions('enable');
252 foreach( $userOptions as $userId => $value ){
253 if( $value == 'yes') $userIds[] = $userId;
258 function _initMediaDirByUserId($userId) {
261 $this->_info(__LINE__ . ": ユーザ($userId)の初期設定");
262 $this->memid = $userId;
264 /*-- 受信メールサーバーの設定--*/
265 $this->host = $this->getMemberOption($userId, 'host');
266 $this->port = $this->getMemberOption($userId, 'port');
267 $this->user = $this->getMemberOption($userId, 'user');
268 $this->pass = $this->getMemberOption($userId, 'pass');
270 // メールでアイテムを追加するblogのID
271 $idandcat = $this->getMemberOption($userId, 'idandcat');
272 list($this->blogid, $this->categoryNameOrId) = explode(",", $idandcat);
274 $this->imgonly = ($this->getMemberOption($userId, 'imgonly') == 'yes') ? 1 : 0;
275 $this->DefaultPublish = ($this->getMemberOption($userId, 'DefaultPublish') == 'yes') ? 1 : 0;
277 /*-- メールのタイトルに各種オプションを含める場合の設定--*/
278 $this->optionsKeyword = $this->getMemberOption($userId, 'optionsKeyword');
279 $this->blogKeyword = $this->getMemberOption($userId, 'blogKeyword');
280 $this->categoryKeyword = $this->getMemberOption($userId, 'categoryKeyword');
281 $this->publishKeyword = $this->getMemberOption($userId, 'publishKeyword');
284 $this->accept = explode("\n", $this->getMemberOption($userId, 'accept'));
285 $this->accept = Array_Map("Trim", $this->accept);
286 $this->accept = Array_Map("strtolower", $this->accept);
287 foreach( $this->accept as $mailAddr ){
288 $this->_info(__LINE__ . "許可アドレス user:$userId, $mailAddr");
292 $this->acceptSubjectPrefix = Trim($this->getMemberOption($userId, 'acceptSubjectPrefix'));
295 $this->moreDelimiter = Trim($this->getMemberOption($userId, 'moreDelimiter'));
298 $this->nosubject = $this->getMemberOption($userId, 'nosubject');
299 $this->no_strip_tags = $this->getMemberOption($userId, 'no_strip_tags');
301 // 最大添付量(バイト・1ファイルにつき)※超えるものは保存しない
302 $this->maxbyte = $this->getMemberOption($userId, 'maxbyte');
303 $this->subtype = $this->getMemberOption($userId, 'subtype');
304 $this->viri = $this->getMemberOption($userId, 'viri');
305 $this->imgExt = $this->getMemberOption($userId, 'imgExt');
308 $this->thumb_ok = ($this->getMemberOption($userId, 'thumb_ok') == 'yes') ? 1 : 0;
309 $this->W = $this->getMemberOption($userId, 'W');
310 $this->H = $this->getMemberOption($userId, 'H');
311 $this->thumb_ext = $this->getMemberOption($userId, 'thumb_ext');
312 $this->smallW = $this->getMemberOption($userId, 'smallW');
315 $collections = MEDIA::getCollectionList();
316 $collection = $this->getMemberOption($userId, 'collection');
317 if( $collection && isset($collections[$collection]) ){
318 $this->collection = $collection;
320 $this->_info(__LINE__ . ": 画像保存ディレクトリが正しくありません。デフォルトを使用します");
321 $this->collection = $this->memid;
324 $this->tmpdir = $DIR_MEDIA.$this->collection.'/';
325 $this->_info(__LINE__ . ": 画像保存ディレクトリ: $this->tmpdir");
327 if (!@is_dir($this->tmpdir)) {
328 $this->_warn(__LINE__ . ": {$DIR_MEDIA}.{$this->collection} ディレクトリが存在しないので、ディレクトリを作成します。");
329 $oldumask = umask(0000);
330 if (!@mkdir($this->tmpdir, 0777))
331 return $this->_warn(__LINE__ . ": 設定エラー: {$DIR_MEDIA}.{$this->collection} ディレクトリの作成に失敗しました。パーミッションを確認してください。");
335 if (!is_writable($this->tmpdir)) {
336 $this->_warn(__LINE__ . ": 設定エラー: {$DIR_MEDIA}.{$this->collection} ディレクトリが存在しないか、書き込み可能になっていません");
340 $thumb_collection = $this->getMemberOption($userId, 'thumb_col');
341 if( $collection && isset($collections[$thumb_collection]) ){
342 $this->thumb_collection = $thumb_collection;
344 $this->_info(__LINE__ . ": サムネイル画像保存ディレクトリが正しくありません。デフォルトを使用します");
345 $this->thumb_collection = $this->memid;
348 $this->thumb_dir = $DIR_MEDIA.$this->thumb_collection.'/';
349 $this->_info(__LINE__ . ": サムネイル画像保存ディレクトリ: $this->thumb_dir");
351 if (!@is_dir($this->thumb_dir)) {
352 $this->_warn(__LINE__ . ": {$DIR_MEDIA}.{$this->thumb_dir} ディレクトリが存在しないので、ディレクトリを作成します。");
353 $oldumask = umask(0000);
354 if (!@mkdir($this->thumb_dir, 0777))
355 return $this->_warn(__LINE__ . ": 設定エラー: {$DIR_MEDIA}.{$this->thumb_dir} ディレクトリの作成に失敗しました。パーミッションを確認してください。");
359 if (!is_writable($this->thumb_dir)) {
360 $this->_warn(__LINE__ . ": 設定エラー: {$DIR_MEDIA}.{$this->thumb_dir} ディレクトリが存在しないか、書き込み可能になっていません");
364 function _convert($str, $input_encoding = false) {
365 if( ! $input_encoding ){
366 $input_encoding = "ISO-2022-JP,ASCII,JIS,UTF-8,EUC-JP,SJIS,ISO-2022-JP";
367 $encoding = mb_detect_encoding($input_encoding);
369 $input_encoding = "ISO-2022-JP";
371 return mb_convert_encoding($str, _CHARSET, $input_encoding);
374 function _addr_search($str) {
375 if( PEAR::isError($addresses = Mail_RFC822::parseAddressList($str)) ){
378 $addr = array_shift($addresses);
380 return $addr->mailbox . "@" .$addr->host;
384 function _thumb_create($src, $W, $H, $thumb_dir = "./") {
386 $size = GetImageSize($src);
392 $im_in = @ImageCreateFromJPEG($src);
395 $im_in = @ImageCreateFromPNG($src);
399 $this->_warn(__LINE__ . ": GDをサポートしていないか、ソースが見つかりません<br>phpinfo()でGDオプションを確認してください");
403 if ($size[0] > $W || $size[1] > $H) {
404 $key_w = $W / $size[0];
405 $key_h = $H / $size[1];
406 ($key_w < $key_h) ? $keys = $key_w : $keys = $key_h;
407 $out_w = $size[0] * $keys;
408 $out_h = $size[1] * $keys;
413 // 出力画像(サムネイル)のイメージを作成し、元画像をコピーします。(GD2.0用)
414 $im_out = ImageCreateTrueColor($out_w, $out_h);
415 $resize = ImageCopyResampled($im_out, $im_in, 0, 0, 0, 0, $out_w, $out_h, $size[0], $size[1]);
417 // サムネイル画像をブラウザに出力、保存
418 $filename = substr($src, strrpos($src, "/") + 1);
419 ImageJPEG($im_out, $thumb_dir.$this->_getThumbFileName($filename)); //jpgサムネイル作成
421 ImageDestroy($im_in);
422 ImageDestroy($im_out);
424 $this->_info(__LINE__ . ": サムネイルを作成しました" . $thumb_dir.$this->_getThumbFileName($filename));
428 function _getThumbFileName($filename){
429 $filename = substr($filename, 0, strrpos($filename, "."));
430 return $filename."-small.jpg";
433 function _getExecuteLink() {
435 return $CONF['ActionURL'].'?action=plugin&name=Moblog&type=execute';
438 function _checkLastupdate() {
440 $lastUpdate = $this->getOption('lastUpdate');
441 $interval = $this->getOption('interval');
443 if ($lastUpdate + $interval < $now) {
444 $this->setOption('lastUpdate', $now);
445 $this->setOption('nextUpdate', date("Y-m-d H:i:s", $lastUpdate + $interval));
446 $this->_info(__LINE__ . ": 更新します。");
449 $this->_info(__LINE__ . ": 更新しません。次回更新は".date("Y-m-d H:i:s", $lastUpdate + $interval)."以降です。");
453 function doSkinVar($skinType, $type = "") {
458 if ( $this->_checkLastupdate() )
463 if ( $member->isLoggedIn() )
464 echo '<a href="'.$this->_getExecuteLink().'">Add Item by Mail</a>';
467 } //end of function doSkinVar($skinType)
469 function doAction($type) {
475 if (!$member->isLoggedIn())
478 header('Location: ' . serverVar('HTTP_REFERER'));
482 return 'アクションが定義されていません: '.$type;
487 $this->execMode = intval($this->getOption('execMode'));
488 if( $this->execMode == 0 ){
490 $this->_info(__LINE__ . ": 振分対応モードで動作します。");
491 } elseif ( $this->execMode == 1 ) {
493 $this->_info(__LINE__ . ": 互換モードで動作します");
496 $enabledUserIds = $this->_getEnableUserId();
497 foreach ($enabledUserIds as $userId) {
498 $this->_info(__LINE__ . ": ユーザ($userId)のメールを取得開始します");
499 $this->_initMediaDirByUserId($userId);
502 $pop3 =& new Net_POP3();
503 $pop3->_timeout = 10;
505 if( ! $pop3->connect($this->host, $this->port) ){
506 $this->_warn(__LINE__ . ": POPサーバーに接続できません");
511 $authMethod = $this->getMemberOption($this->memid, 'useAPOP') == 'yes' ? 'APOP' : 'USER';
512 $this->_info(__LINE__ . ": $authMethod で認証を行います");
513 if(PEAR::isError($ret =& $pop3->login($this->user , $this->pass , $authMethod)) ){
514 $this->_warn(__LINE__ . ": 認証に失敗しました:" . $ret->getMessage() );
520 $num = $pop3->numMsg();
521 $this->_info(__LINE__ . ": $num 件のメールがあります");
528 for ($i = 1; $i <= $num; $i ++) {
529 if(! $msg =& $pop3->getMsg($i) ){
530 $this->_warn(__LINE__ . ": メールの取得に失敗しました。");
533 $result = $this->addItemByMail($userId, $msg);
535 $this->_info(__LINE__ . ": メッセージを削除します");
536 $pop3->deleteMsg($i);
541 $this->_info(__LINE__ . ": ユーザ($userId)のメールを取得終了しました");
545 function addItemByMail($userId, $msg) {
547 $params['include_bodies'] = TRUE;
548 $params['decode_bodies'] = TRUE;
549 $params['decode_headers'] = TRUE;
550 $params['input'] = $msg;
551 if(PEAR::isError( $decodedMsg = Mail_mimeDecode::decode($params)) ){
552 $this->_warn(__LINE__ . ": メールデコードに失敗しました:" . $decodedMsg->getMessage() );
557 if ( $decodedMsg->headers['from'] ) {
558 $from = $this->_addr_search($decodedMsg->headers['from']);
560 if ( (! $from ) && $decodedMsg->headers['reply-to'] ) {
561 $from = $this->_addr_search($decodedMsg->headers['reply-to']);
563 if ( (! $from ) && $decodedMsg->headers['return-path'] ) {
564 $from = $this->_addr_search($decodedMsg->headers['return-path']);
567 $this->_warn(__LINE__ . ": メールに送信者アドレスが見つかりません");
570 $this->_info(__LINE__ . ": From($from)");
573 $from = strtolower(Trim($from));
574 if ( in_array($from, $this->accept) ) {
575 $this->_info(__LINE__ . ": 投稿許可アドレスに含まれているので受付($from)");
576 } elseif( in_array( "*", $this->accept) ){
577 $this->_info(__LINE__ . ": 投稿許可アドレスにワイルドカードが含まれているので受付($from)");
579 if( $this->execMode == 0 ){
580 $this->_info(__LINE__ . ": 投稿許可アドレスに含まれていないので拒否($from)。振り分け対応モードなので他のアカウントで取得が行われる場合があります。");
582 $this->_warn(__LINE__ . ": 投稿許可アドレスに含まれていないので拒否($from)");
586 return $this->execMode;
590 $blog =& new BLOG($this->blogid);
592 $timestamp = strtotime( trim($decodedMsg->headers['date']) );
593 if ($timestamp == -1){
594 $this->_info(__LINE__ . ": Dateヘッダからのtimestamp取得に失敗しました。");
597 $timestamp = $blog->getCorrectTime($timestamp);
600 $subject = $this->_convert($decodedMsg->headers['subject']);
602 // Subject: prefixチェック
603 if ( $this->acceptSubjectPrefix ){
604 $this->_info(__LINE__ . ": 投稿許可SubjectPrefixがあります(prefix: $this->acceptSubjectPrefix)");
605 $pos = mb_strpos($subject, $this->acceptSubjectPrefix);
608 $subject = mb_substr($subject, mb_strlen($this->acceptSubjectPrefix) );
609 $this->_info(__LINE__ . ": 投稿許可SubjectPrefixをみつけました(prefix削除後subject: $subject)");
611 $this->_warn(__LINE__ . ": 投稿許可SubjectPrefixがないので拒否します($subject)");
617 if (preg_match('/'.$this->optionsKeyword.'/i', $subject)) {
618 list ($subject, $option) = spliti($this->optionsKeyword, $subject, 2);
620 $this->_info(__LINE__ . ": Subject($subject), Option($option)");
622 $option = '&'.$option;
623 if (preg_match('/&' . $this->blogKeyword . '=([^&=]+)/i', $option, $word)) {
624 $this->blogid = $word[1];
625 $this->_info(__LINE__ . ': blogidを' . $this->blogid . 'で上書きします');
627 if (preg_match('/&' . $this->categoryKeyword . '=([^&=]+)/i', $option, $word)) {
628 $this->categoryNameOrId = $word[1];
629 $this->_info(__LINE__ . ': Categoryを' . $this->categoryNameOrId . 'で上書きします');
631 if (preg_match('/&' . $this->publishKeyword . '=([^&=]+)/i', $option, $word)) {
632 $this->DefaultPublish = $word[1];
633 $this->_info(__LINE__ . ($this->DefaultPublish ? ': 投稿を公開に上書きします' : ': 投稿を下書きに上書きします'));
638 if( ! $subject = trim(htmlspecialchars($subject)) ){
639 $subject = $this->nosubject;
644 if( strtolower($decodedMsg->ctype_primary) == "text" ){
645 $this->_info(__LINE__ . ": single partメッセージです");
646 $text = $this->_textPart($decodedMsg);
647 } elseif ( strtolower($decodedMsg->ctype_primary) == "multipart" ){
648 $this->_info(__LINE__ . ": multipart partメッセージです");
650 $fileNames = Array();
651 $this->_decodeMultiPart($decodedMsg->parts, $texts, $fileNames);
653 $text = $texts['plain'];
654 if( $texts['html'] ) $text = $texts['html'];
657 if ($this->imgonly && (! $fileNames) ) {
658 $this->_info(__LINE__ . ": 添付ファイルがないので書き込みません");
662 if( $this->_isSpam($text) ){
663 $this->_warn(__LINE__ . ": SPAMのため追加しません");
669 if ( ! $fileNames ) {
675 $body .= TEMPLATE :: fill($this->getMemberOption($this->memid, 'textTpl'), $vars);
678 $lastFile = array_pop($fileNames);
680 foreach( $fileNames as $filename ){
681 $body .= $this->_imageHtml($filename);
684 $body .= $this->_imageHtml($lastFile, $text);
688 $this->_info(__LINE__ . ": アイテム追加します");
692 if( $this->moreDelimiter )
693 list($body, $more) = spliti($this->moreDelimiter, $body, 2);
698 $this->_addDatedItem($this->blogid, $subject, $body, $more, 0, $timestamp, 0, $this->categoryNameOrId);
702 function _decodeMultiPart($parts, &$texts, &$fileNames){
703 foreach($parts as $part){
\r switch ( strtolower( $part->ctype_primary )){
706 $this->_decodeMultiPart($part->parts, $texts, $fileNames);
710 $this->_info(__LINE__ . ": text part をみつけました[{$part->ctype_primary}/{$part->ctype_secondary}]");
711 $texts[$part->ctype_secondary] = $this->_textPart($part);
716 $this->_info(__LINE__ . ": image/data part をみつけました[{$part->ctype_primary}/{$part->ctype_secondary}]");
717 if( $fileName = $this->_imagePart($part) )
718 $fileNames[] = $fileName;
724 function _textPart(&$part){
726 if( $part->ctype_parameters )
727 $encoding = $this->ctype_parameters['charset'];
729 $text = $this->_convert($part->body, $encoding);
730 $text = strip_tags($text, $this->no_strip_tags);
732 $blog =& new BLOG($this->blogid);
733 //blog設定で改行を<br />に置換onの場合
734 if ($blog->getSetting('bconvertbreaks')) {
735 if ( strtolower($part->ctype_secondary) == 'html' ) {
737 $text = str_replace("\r\n", "\r", $text);
738 $text = str_replace("\r", "\n", $text);
739 $text = str_replace("\n", "", $text);
740 $text = str_replace("<br>", "\n", $text);
746 function _imagePart(&$part){
747 if( !$this->prefixDate ){
748 $this->prefixDate = date('YmdHis');
749 $this->fileCount = 0;
751 $this->fileCount += 1;
753 $this->filePrefix = $this->prefixDate . sprintf('%02d', $this->fileCount);
756 if( $part->d_parameters ){
757 $filename = $part->d_parameters['filename'];
758 } elseif( $part->ctype_parameters ){
759 $filename = $part->ctype_parameters['name'];
761 $filename = $part->ctype_secondary;
764 $filename = $this->_convert($filename);
765 $filename = $this->filePrefix . "-" . $filename;
766 $this->_info(__LINE__ . ": FileName($filename)");
769 $size = strlen($part->body);
770 if( eregi($this->subtype, trim($part->ctype_secondary) )){
772 if ($size < $this->maxbyte && !eregi($this->viri, $filename)) {
774 $fp = fopen($this->tmpdir.$filename, "w");
775 fputs($fp, $part->body);
778 $size = @getimagesize($this->tmpdir.$filename);
780 if ($this->thumb_ok && function_exists('ImageCreate')) {
782 if ( preg_match("/$this->thumb_ext/i", $filename) ) {
783 if ($size[0] > $this->W || $size[1] > $this->H) {
784 $this->_thumb_create($this->tmpdir.$filename, $this->W, $this->H, $this->thumb_dir);
790 $this->_warn(__LINE__ . ": 添付ファイルを無視します。(サイズ超過: $size B or 保存しないファイルに該当しています) [$part->ctype_primary/$part->ctype_secondary]");
793 $this->_warn(__LINE__ . ": 添付ファイルを無視します。(subtypeチェック: $part->ctype_secondary が対応MIMEタイプに入っていますか?) [$part->ctype_primary/$part->ctype_secondary]");
797 function _imageHtml($filename, $body = ""){
800 $size = @getimagesize($this->tmpdir.$filename);
801 $thumb_size = @getimagesize($this->thumb_dir.$this->_getThumbFileName($filename));
802 $smallH = round($this->smallW / $size[0] * $size[1], 0);
805 'thumbW' => $thumb_size[0],
806 'thumbH' => $thumb_size[1],
807 'reductionW' => $this->smallW,
808 'reductionH' => $smallH,
812 'thumbUrl' => $this->thumb_collection.'/'.$this->_getThumbFileName($filename),
813 'imageUrl' => $this->collection.'/'.$filename,
814 'mediaUrl' => $CONF['MediaURL'],
815 'fileName' => $filename
819 if( ! preg_match("/$this->imgExt/i", $filename) ){
820 $this->_info(__LINE__ . ": 画像ファイルに該当しないので、データファイルテンプレートを使用します");
821 return TEMPLATE :: fill($this->getMemberOption($this->memid, 'dataTpl'), $vars);
824 if ( $thumb_size[0] ) { //サムネイルがある場合のソース
825 $this->_info(__LINE__ . ": サムネイルがあります");
826 return TEMPLATE :: fill($this->getMemberOption($this->memid, 'withThumbTpl'), $vars);
827 } else { //サムネイルがない場合のソース
828 if ($size[0] > $this->smallW) { //縮小表示
829 $this->_info(__LINE__ . ": サムネイルがありません、縮小表示します");
830 return TEMPLATE :: fill($this->getMemberOption($this->memid, 'reductionTpl'), $vars);
832 $this->_info(__LINE__ . ": サムネイルがありません");
833 return TEMPLATE :: fill($this->getMemberOption($this->memid, 'withoutThumbTpl'), $vars);
838 function _addDatedItem($blogid, $title, $body, $more, $closed, $timestamp, $future, $catNameOrId = "") {
839 // 1. ログイン======================
840 $mem = MEMBER :: createFromID($this->memid);
842 // 2. ブログ追加できるかチェック======================
843 if (!BLOG :: existsID($this->blogid)) {
844 $this->_info(__LINE__ . ": 存在しないblogです");
847 $this->_info(__LINE__ . ": blogidはOK!");
849 if (!$mem->isTeamMember($blogid)) {
850 $this->_warn(__LINE__ . ": メンバーではありません");
853 $this->_info(__LINE__ . ": メンバーチェックもok!");
856 $this->_warn(__LINE__ . ": 空のアイテムは追加できません");
859 $this->_info(__LINE__ . ": アイテムは空じゃないです");
862 $blog =& new BLOG($this->blogid);
863 if( $blog->isValidCategory($catNameOrId) ){
864 // カテゴリIDとして有効なときはそのまま使う
865 $catid = $catNameOrId;
867 // カテゴリID ゲット (誤ったカテゴリID使用時はデフォを使用)
868 $catid = $blog->getCategoryIdFromName($catNameOrId);
871 $this->_info(__LINE__ . ": 追加するcatid: ".$catid);
872 if ($this->DefaultPublish) {
876 $this->_info(__LINE__ . ": ドラフトで追加します");
879 $closed = 0; //コメントを許可
880 $this->_info(__LINE__ . ": \$catid:".$catid.", \$draft:".$draft.", \$closed:".$closed);
883 $itemid = $blog->additem($catid, $title, $body, $more, $blogid, $mem->getID(), $timestamp, $closed, $draft);
885 $this->_info(__LINE__ . ": itemid: $itemid");
889 function _isSpam($str){
891 if( $this->getOption('spamCheck') == 'yes' ){
898 $manager->notify('SpamCheck', array ('spamcheck' => & $spamcheck));
899 if (isset($spamcheck['result']) && $spamcheck['result'] == true)