Backport(バックポート) #2273
完了サイドバナーのRSSリーダーで読み込めない時がある
100%
説明
現象¶
(http://sns.openpne.jp/communityTopic/6318 より転記)
サイドバナーへRSSリーダーを登録しているのですが、
読み込み先によって、
画面の表示が「サーバーが混雑しています~」のような表示になってしまいます。
再現環境¶
サーバー:
- CentOS Linux 5.5
- MySQL version 5.0.91
- php 5.2.13
OpenPNEのバージョン:
- OpenPNE3.4.6.2
再現手順¶
こちらのRSSを登録する(8月28日23時ごろ)
http://video.baidu.jp/api/search?word=%E3%83%90%E3%82%A4%...
最初はずっと表示されていましたので、時間がたつと内容が変わりますので、表示されるようになるかもしれません。
サーバーのエラーログ:
PHP Fatal error: Uncaught exception 'sfException' with message 'Impossible to parse date "" with format "yyyy-MM-dd HH:mm:ss".' in /www/lib/vendor/symfony/lib/i18n/sfDateFormat.class.php:186\n Stack trace:\n #0 /www/lib/vendor/symfony/lib/i18n/sfDateFormat.class.php(219): sfDateFormat->getDate('', NULL)\n #1 /www/lib/vendor/symfony/lib/helper/DateHelper.php(60): sfDateFormat->format('', 'MM???dd???', NULL, 'utf-8')\n #2 /www/lib/helper/opUtilHelper.php(333): format_date('', 'MM???dd???', 'ja_JP', NULL)\n #3 /www/apps/pc_frontend/modules/default/templates/_rssBox.php(7): op_format_date('', 'XShortDateJa')\n #4 /www/cache/apache/pc_frontend/prod/config/config_core_compile.yml.php(3810): require('...')\n #5 /www/lib/vendor/symfony/lib/view/sfPartialView.class.php(110): sfPHPView->renderFile('...')\n #6 /www/lib/vendor/symfony/lib/helper/PartialHelper.php(155): sfPartialView->render()\n #7 /var/www/r in /www/lib/vendor/symfony/lib/i18n/sfDateFormat.class.php on line 186
原因¶
規定外のRSSを受信した場合などに、パースに失敗し例外により処理が中断されるため。
修正内容¶
ガジェット側ですべての例外を catch して、適切な表示になるように修正するべきです。
具体的には、http://redmine.openpne.jp/issues/1684#note-3 にあるように
diff --git a/apps/pc_frontend/modules/default/actions/components.class.php b/apps/pc_frontend/modules/def index 097703c..ad79046 100644 --- a/apps/pc_frontend/modules/default/actions/components.class.php +++ b/apps/pc_frontend/modules/default/actions/components.class.php @@ -95,11 +95,17 @@ class defaultComponents extends sfComponents public function executeRssBox() { - $fetcher = new opRssFetcher('UTF-8'); - $this->result = @$fetcher->fetch($this->gadget->getConfig('url'), true); - if ($this->result) + try + { + $fetcher = new opRssFetcher('UTF-8'); + $this->result = @$fetcher->fetch($this->gadget->getConfig('url'), true); + if ($this->result) + { + $this->result[1] = array_slice($this->result[1], 0, 5); + } + } + catch (Exception $e) { - $this->result[1] = array_slice($this->result[1], 0, 5); } }のような変更で十分かと思われます。
Naoya Tozuka さんが13年以上前に更新
- ステータス を Accepted(着手) から Pending Review(レビュー待ち) に変更
- 進捗率 を 0 から 50 に変更
更新履歴 6350db096217ef41f45582c49bf5e23b673996d1 で適用されました。
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Fumie Toyooka さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Rejected(差し戻し) に変更
- 進捗率 を 70 から 50 に変更
こちらのチケットのテストを開始しましたが、
読み込めない場合のRSSを登録すると「現在、サーバが混み合っているか、メンテナンス中です。」と
表示されます。ご確認よろしくお願いいたします。
以下はdevモードのエラーです。
500 | Internal Server Error | sfException Impossible to parse date "" with format "yyyy-MM-dd HH:mm:ss".
Yuya Watanabe さんが約13年前に更新
note-8で指摘された問題の原因¶
本チケットに記載されたRSSフィードのURLにおいては,下記部分で$entry['date']で空文字列が与えられていることが原因です.
ここで$entry['date']が空文字列であった場合でも適切な文字列をop_format_date()に与えることで解決できると思われます.
apps/pc_frontend/modules/default/templates/_rssBox.php
6 <?php foreach ($result[1] as $entry): ?> 7 <li><span class="date"><?php echo op_format_date($entry['date'], 'XShortDateJa') ?></span> 8 <?php echo link_to($entry['title'], $entry['link']) ?>
その他問題に関して¶
このチケットの例で得られるRSSフィードがおかしいので以下の部分でRSSフィードをフェッチしている部分に注目してみました.
apps/pc_frontend/modules/default/actions/components.class.php
98 try 99 { 100 $fetcher = new opRssFetcher('UTF-8'); 101 $this->result = @$fetcher->fetch($this->gadget->getConfig('url'), true); 102 if ($this->result) 103 { 104 $this->result[1] = array_slice($this->result[1], 0, 5); 105 } 106 }
ここで101行目で$this->gadget->getconfig('url')がそのまま用いられていることが気になったので出力を行ってみました.
すると下記のような文字列が得られました.
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
これをhtmlspecialchars_decode()によってデコードしてみると下記のようになり,最新の結果が得られました.
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
この部分を加味するに,本チケットにおける問題の本質としては「URLに特殊記号が含まれる場合に正しい結果を得られない」というところなのではないかと思いました.
メモ¶
apps/pc_frontend/modules/default/actions/components.class.php:101で得られる$this->gadgetをget_class($this->gadget)した結果.
sfOutputEscaperIteratorDecorator
Yuya Watanabe さんが約13年前に更新
その他問題追記¶
サイドバーガジェット設定画面(pc_backend.php/design/gadget/type/sideBanner)において,ガジェットの設定画面において「設定変更」部分に「URL」の欄が存在します.
この「URL」の欄にも気になる点があったので調べてみました.
確認内容¶
ガジェットの設定画面のRSSリーダーガジェット設定における「設定変更」部分「URL」の文字列がデコードされているかどうか.
確認手順¶
- サイドバーガジェット設定画面でRSSリーダーを2つ追加
- それぞれのRSSリーダーにおいて「URL」に以下の2つのURLを入力して設定を保存
- RSSリーダー1
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー2
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー1
- その後「設定変更」部分に「URL」の欄を確認
- RSSリーダー1
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー2
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー1
- 下記のようにコードを編集して確認.
lib/form/doctrine/GadgetConfigForm.class.php:43行目に値を出力するコードを挿入.40 $config = Doctrine::getTable('GadgetConfig')->retrieveByGadgetIdAndName($gadget->getId(), $key); 41 if ($config) 42 { 43 var_dump($config->getValue()); 44 $this->setDefault($key, $config->getValue()); 45 }
- RSSリーダー1
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー2
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- RSSリーダー1
まとめ¶
以上の結果より,RSSリーダー設定部の「URL」の欄は,入力され保存されているデータそのままを表示していないということが考えられます.よってnote-10で述べたその他問題に関して修正を施したとしても適切な動作の確認を行えない可能性があります.
修正案¶
管理画面ガジェット設定のガジェット編集部においてデコードを行わない実装を行う.
Yuya Watanabe さんが約13年前に更新
下記のような修正を行った際にURL1,URL2でRSSは違う結果が表示されるが管理画面では同じURLに見える現象が生じたことを確認.
diff --git a/apps/pc_frontend/modules/default/actions/components.class.php b/apps/pc_frontend/modules/default/actions/components.class.php index ad79046..06b97c4 100644 --- a/apps/pc_frontend/modules/default/actions/components.class.php +++ b/apps/pc_frontend/modules/default/actions/components.class.php @@ -98,7 +98,7 @@ class defaultComponents extends sfComponents try { $fetcher = new opRssFetcher('UTF-8'); - $this->result = @$fetcher->fetch($this->gadget->getConfig('url'), true); + $this->result = @$fetcher->fetch(sfOutputEscaper::unescape($this->gadget)->getConfig('url'), true); if ($this->result) { $this->result[1] = array_slice($this->result[1], 0, 5);
- URL1
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
- URL2
http://video.baidu.jp/api/search?word=バイク&output=rss&start=0&count=12&sort=dt_recent&adult_filter=1
Yuya Watanabe さんが約13年前に更新
note-11の問題は #2407 にチケットを作成しました.テスト実施者は入力するURLに注意してテストを実施してください.
wa ta さんが約13年前に更新
- ステータス を Rejected(差し戻し) から Pending Review(レビュー待ち) に変更
更新履歴 52b7e1f21f74bab3eb8067edebbf92d3648eb41a で適用されました。
Kousuke Ebihara さんが約13年前に更新
- ステータス を Pending Review(レビュー待ち) から Pending Testing(テスト待ち) に変更
- 進捗率 を 50 から 70 に変更
Yuma Sakata さんが約13年前に更新
- ステータス を Pending Testing(テスト待ち) から Fixed(完了) に変更
- 進捗率 を 70 から 100 に変更
テストOKです。