内部フィードを表示する

Daisukeh 2009/01/19 09:59 投稿
Daisukeh 2009/01/22 11:10 解説
Daisukeh 2009/02/05 08:49 更新
Daisukeh 2009/08/05 14:30 移設

記事一覧

DokuWikiにはSimplePieと呼ばれる RSS / ATOM フィードの解析エンジンが標準装備されている。フィード内の HTML コードの表示はできないが、解析処理は安全にできるようで、以前はPEARZendFrameworkや独自方式で処理していたが、DokuWikiでできるから面倒でやめちゃった。8-O それはともかく、DokuWikiもサイト更新情報やplugin:blog等で書いた情報をplugin:feedで出力することができる。ただし{{rss>...}}の記述で、SimplePieを使ってフィードを表示するときに、指定する URL をどうするかが問題になる。たとえばレンタルサーバーなどで、DokuWikiが稼動するマシンが必ずインターネットの向こう側にいるのなら、直接そのドメインを指定することができるから、フィードのリンクにジャンプすることは問題ない。だけど、ローカルサーバーの場合はhttp://localhost/...てな具合の URL 指定になるのだろうか?

 実際のところ、このサイトは自宅のマシンで動いていて、ローカルIPとグローバルIPの両方を持っている。自宅にいるときに、http://daisukeh.ddo.jp/は通用しない(ルーターがエコーバックするのを禁止して、接続エラーになる)ので、ローカルIPで接続することになるのである。だからドメインに何を指定すべきなのか、考えなければならない。たとえばドメインにlocalhostを指定すれば、フィードは自分のマシンから取得できるから正しく表示されるが、リンク先がlocalhostになっているため、当然127.0.0.1(クライアントマシン)に接続しにいってしまい、結果「リンク先が見当たらない」エラーが表示されることになるというカラクリ…。外からも中からも正しく接続したい、ということでplugin:phpincを利用して作ったのが、下のプログラムなのだ。これ自体はPukiWikiで使っていたものを流用している。SimplePieとは比べ物にならないくらい(そして信じられないくらい!)簡単な構文解析でフィードを整形し、一応キャッシュ処理なんかも入れて、最後にhttp://localhostあるいはhttp://127.0.0.1の部分を、DokuWikiの内部変数$conf['baseurl']で置換している。この変数には実際のドメイン(あるいはローカルIP)が格納されるので、ページのレンダリング時には、正しいリンク先に置換されるという訳だ。もちろん、外部のフィードでもかまわない(たとえばこのサイトの左側では、ココログのフィードを表示している)が、構文解析が完全じゃないから、どんなフィードでも飲み込めると言う訳じゃないけど。

 このサイトはウェブサーバーにAbyss Web Serverというのを使っている。Apacheも試したことあるけれど、ASP.NETに対応していて、コンフィギュレーションが簡単(日本語設定ファイルも有)なので、ずーっとこれ。しかしDokuWikiとはちょっとだけ相性が悪いらしく、doku.phpへのアクセス時にドメインが指定されないことがあった。(http://doku.php?...とかになっちゃうのだ。)なので/conflocal.protected.phpというファイルを作って、中に

/conf/local.protected.php

<?php
  $conf['baseurl'] = 'http://' . $_SERVER['SERVER_NAME'];
?>
というコードを入れておいた。標準の設定ファイルであるlocal.phpの最後に@include(DOKU_CONF.'local.protected.php');という記述があるのがミソである。ファイルがあれば優先的に設定情報を書き換えられるからだ。上述したhttp://localhostの置換に$conf['baseurl']を使うのも、ここで$_SERVER['SERVER_NAME'];が必ず指定されているからドメインが保証されている、ということなのだ。

 このプログラムを使うときには、

DokuWikiでの使用例

====== サイト ======
<phpinc=rssfeeddump.php>
<php>
  $remote = $_SERVER['REMOTE_ADDR'];
  if(($remote == "127.0.0.1") || ($remote == "localhost")) $server = "localhost";
  else if(eregi("^192\.168\.0\.[0-9]+$", $remote))         $server = "192.168.0.240";
  else                                                     $server = "daisukeh.ddo.jp";
  print "<a class=\"feed\" href=\"http://$server/feed.php\">思考の遷移図(サイト更新)</a>";
  rss_feed_dump('http://localhost/feed.php');
</php>
 
====== ブログ ======
{{blogfeed>blog|思考の遷移図(ブログ更新)}}
<php> rss_feed_dump('http://localhost/lib/plugins/feed/feed.php?plugin=blog&fn=getBlog&ns=blog&title=Blog'); </php>
 
====== ココログ ======
<html> <a class="feed" href="http://daisukeh.cocolog-nifty.com/blog/index.rdf">思考の遷移図(@nifty)</a> </html>
<php> rss_feed_dump('http://daisukeh.cocolog-nifty.com/blog/index.rdf'); </php>
みたいな調子で書く。左側の3つのフィードはこれで表示しているので参考にして欲しい。

 http://localhost/feed.phpやplugin:blogのフィードの表示にはlocalhostを使用してかまわないが、フィードへのリンクはやはりPHPでドメインを加工してやらなければならない。ほとんどの場合、サーバーマシンはネットの向こう側だろうけど、自宅サーバーを構えた場合は「敷居の跨ぎ方にコツがある」のだ。

下に示すのがplugin:phpinc/phpincludes/に入れるプログラムである。

ダウンロードrssfeeddump-090304.zip2.20

rssfeeddump.php 2.10

<?php
 
  // ニュースフィード表示   2.20 09/03/04 Daisukeh
 
  function rss_feed_dump($feedurl, $num = 10, $desc = false)
  {
    // 解析用パラメータ初期化 (09/02/05修正)
    if($feedurl == '') return;
    $feedhtml  = eregi_replace('[a-z]+\.[a-z]+$', '', $_SERVER['APPL_PHYSICAL_PATH'])
               . eregi_replace('/', '\\', eregi_replace('/[^/]*$', '', $_SERVER['SCRIPT_NAME']))
               . '\data\\'
               . md5($feedurl)
               . '.html';
    $channel   = false;
    $encoding  = 'utf-8';
    $feedtitle = '';
    $feedlink  = '';
    $content   = null;
    $item      = false;
    $itemtitle = array();
    $itemlink  = array();
    $itemdesc  = array();
    $itemdate  = array();
    $items     = 0;
 
    // ニュースフィード解析・整形
    $regs = array();
    $file = false;
    if(!file_exists($feedhtml)) $file = true;
    else
    {
      // 10分毎に更新 (09/02/05修正)
      $filedt = eregi_replace('[0-9]$', '', date('ymdHi', filemtime($feedhtml)));
      $nowdt  = eregi_replace('[0-9]$', '', date('ymdHi'));
      $file = ($filedt < $nowdt);
    }
    if($file) $file = fopen($feedurl, 'r');
    if($file)
    {
      // ニュースフィード解析(RSS/ATOM) (09/02/05改造)
      while(!feof($file))
      {
        $line = trim(mb_convert_encoding(fgets($file), 'utf-8', 'auto'));
 
        // ヘッダ解析 (09/02/05改造)
        if    (mberegi('<channel',   $line)
        ||     mberegi('<feed',      $line)) $channel = true;
        elseif(mberegi('</channel>', $line)
        ||     mberegi('</feed>',    $line)) $channel = false;
        if($channel)
        {
          if(mberegi('<title>', $line)) $feedtitle = mberegi_replace('<[^>]*>', '', $line);
          if(mberegi('<link>',  $line)) $feedlink  = mberegi_replace('<[^>]*>', '', $line);
        }
        if(mberegi('<\?xml.+encoding="([^"]+)"\?>', $data, $regs)) $encoding = $regs[1];
 
        // エントリ解析 (09/02/05改造)
        if    (mberegi('<item',    $line)
        ||     mberegi('<entry',   $line)) $item = true;
        elseif(mberegi('</item>',  $line)
        ||     mberegi('</entry>', $line))
        {
          $content = null;
          $item    = false;
          $items ++;
          if($items >= $num) break;
        }
        if($item)
        {
          // (09/03/04改造)
          $channel = false;
          $rawdata = html_entity_decode($line, ENT_QUOTES, $encoding);
          $strip   = trim(strip_tags($rawdata));
          if(mberegi('<title>',        $line)) $itemtitle[$items] = mberegi_replace('^[0-9]+: *', '', $strip);
          if(mberegi('<description>',  $line))
          {
            $itemhtml[$items] = $rawdata;
            $itemdesc[$items] = $strip;
          }
          if(mberegi('<content',   $line)) $content  = '';
          if(isset($content))              $content .= $rawdata."\n";
          if(mberegi('</content>', $line))
          {
            $itemhtml[$items] = $content;
            $itemdesc[$items] = trim(strip_tags($content));
            $content = null;
          }
          if(($itemlink[$items] == '')
          && mberegi('<id>', $line) 
          && mberegi('^[htps]+://[^<>]+$', $strip)) $line = mb_eregi_replace('<id>', '<link>', $line);
          if(mberegi('<link>', $line))                       $itemlink[$items] = $strip;
          if(mberegi('<link.+href="([^"]+)"', $line, $regs)) $itemlink[$items] = $regs[1];
          if(mberegi('<dc:date>', $line)
          || mberegi('<updated>', $line)) $itemdate[$items] = mberegi_replace('T.*$',         '', $strip);
          if(mberegi('<pubDate>', $line)) $itemdate[$items] = mberegi_replace(' +[0-9]+:.+$', '', $strip);
          if(($itemdate[$items] != '')
          && ($itemtime[$items] == ''))
          {
            $match = array();
            mberegi('([0-9]+:[0-9]+):[0-9]+', $line, $match);
            $itemtime[$items] = $match[1];
          }
        }
      }
      fclose($file);
 
      // ニュースフィード整形 (09/02/04修正,09/03/04改造)
      $html = '';
      $date = '';
      for($i = 0; $i < $items; $i ++)
      {
        if($date <> $itemdate[$i])
        {
          if($date <> '') $html .= "</ul>\n";
          $date = $itemdate[$i];
          $html .= '<strong>'.$date."</strong><ul>\n";
        }
        if($html == '') $html = '<ul>';
        if(($tm = $itemtime[$i]) != '') $tm = ' ('.$tm.')';
        $html .= '<li><a href="'.$itemlink[$i].'" title="'.$itemdesc[$i].'" style="text-decoration:underline;">'.$itemtitle[$i].'</a>'.$tm;
        if($desc) $html .= '<br/><div style="color:gray;">'.$itemhtml[$i].'</div>';
        $html .= "</li>\n";
      }
      if($html != '') $html = "<div>\n".$html."</ul>\n</div>\n";
      file_put_contents($feedhtml, $html);
    }
 
    // ニュースフィード表示 (09/02/02修正)
    global $conf;
    $server = $conf['baseurl'];
    $local  = 'http://localhost';
    if($server == $local)
      if(eregi('^([htps]+://[^/]+)/', $feedurl, $regs)) $server = $regs[1];
    $html = file_get_contents($feedhtml);
    if($server != $local) $html = mb_eregi_replace($local, $server, $html);
    print($html);
  }
 
?>

Daisukeh 2009/01/30 08:46 更新 2.01

 同じフィードスクリプト名称の場合(たとえばindex.rdfなど)に、キャッシュするファイル名が競合して正しく表示できないことが判明したので、ファイル名を整形する部分を修正した。

rssfeeddump.php ファイル名整形箇所

$feedhtml  = eregi_replace('[a-z]+\.[a-z]+$', '', $_SERVER['APPL_PHYSICAL_PATH'])
           . '\data\\'
           . eregi_replace('[/\.]', '_',
             eregi_replace('^.*//', '',
             eregi_replace('\.[^/]+$', '', $feedurl)))
           . '.html';

Daisukeh 2009/02/02 10:14 更新 2.02

 DokuWikiの配置に関する問題と、ドメインの文字列置換部分に不具合があった。具体的には、DokuWikiをウェブルートに展開していない場合(たとえば、/dokuwiki/など)、キャッシュするニュースフィードのファイル保存に失敗していた。もう一点は、localhostのフィード解析時に、クライアントの識別だけでなくフィードのドメインも考慮しなければいけなかった。

rssfeeddump.php 最下部

  global $conf;
  $server = $conf['baseurl'];
  $local  = 'http://localhost';
  if($server == $local)
    if(eregi('^([htps]+://[^/]+)/', $feedurl, $regs)) $server = $regs[1];

Daisukeh 2009/02/04 12:01 更新 2.04

 MANTISを使いたくて、少しいじっていたら不具合(バグじゃないよ)を見つけたので、少し修正してみた。strip_tagsでいいところをmb_eregi_replaceでズラズラ書いていた部分をきれいにしたのと、<ul>タグが生成されない可能性がある場合、それを生成する処理を追加した。MANTISはバグ追跡が主な機能であって、プロジェクト管理はしていないからなのか、フィードにタイムスタンプが付加されていない。何でだろう?と言うことで、チケットIDが桁が多くてちょっと邪魔なので、正規表現でカットすることにした。

rssfeeddump.php ニュースフィード解析 部分

  $strip = mb_eregi_replace('&[a-z]+;', '', strip_tags(mb_eregi_replace('&lt;', '<', mb_eregi_replace('&gt;', '>', $line))));

Daisukeh 2009/02/04 18:24 更新 2.05

 いじくりまわしていたら、同じスクリプトで異なるフィードを出力する場合、キャッシュするファイル名( HTML ファイル)が競合してしまうため、思い切ってファイル名整形をやめた。その代わりに、md5でリクエスト URL をそのままエンコードして、それをファイル名にすることにした。

rssfeeddump.php 解析用パラメータ初期化 部分

    . '\data\\'
//  . eregi_replace('[/\.]', '_',
//    eregi_replace('^.*//', '',
//    eregi_replace('\.[^/]+$', '', $feedurl)))
    . md5($feedurl)
    . '.html';

最初からこうしておけばよかったと、今になって思う。

Daisukeh 2009/02/05 08:43 更新 2.06

 フィード整形ファイルの更新間隔を10分にした。1時間では場合によっては長すぎるためである。それともうひとつ、整形後のファイルを何故かfopenで書き出していたので、file_put_contentsに変更した。おかげで、少しすっきりしたと思う。

rssfeeddump.php ニュースフィード解析・整形 部分

  // 10分毎に更新 (09/02/05修正)
  $filedt = eregi_replace('[0-9]$', '', date('ymdHi', filemtime($feedhtml)));
  $nowdt  = eregi_replace('[0-9]$', '', date('ymdHi'));
  $file = ($filedt < $nowdt);

Daisukeh 2009/02/05 14:09 更新 2.10

 昨日はMANTISに対応させたのだが、Trac Lightningを飛び越して、Redmineを使ってみることにした。Railsで作られたプロジェクトとバグトラックの両対応のウェブアプリケーションである。まだ使い始めたばかりだが、簡単に言えば、Trac LightningRuby版(ただし、Subversion機能はない)というところかな。

 それはいいとして、Redmineも他の開発支援ツールと同様に、チケットでバグや仕様を管理するのだが、そのフィードをここで紹介しているrssfeeddump.phpで表示してみたところ、うまく表示できないことが判明した。これは単純に RSS 形式にのみ対応していたためで、 ATOM 形式のフィードを認識できないことが原因であった。当初はDokuWikiの{{rss>...}}で表示できればいいやと思っていたのだが、何故かWEBrickの3000番がリンク先アドレスから欠落してしまう。バグなのか?とにかく、このスクリプトでも対応を試みるということで、 RSSATOM の両対応版を作ってみた。多分まだ完璧じゃないけど。

 作っている最中に見つけたんだけど、PHPは本当に便利だなぁと思う関数があったのだ。

  $strip = trim(strip_tags(html_entity_decode($line, ENT_QUOTES, $encoding)));
当然あるよね、という関数なんだけど、html_entity_decode&#xx;見たいな特殊文字を元に戻してくれる関数だ。ニュースフィードの説明文などに HTML コードを含んでいる場合は大抵エンコードされている(というか、エンコードしないと XML 文書として成立しないが…)。前の版まではmberegi_replaceで対応していただけに、他にも便利な関数が眠っていて、知らないだけなんじゃないかと思っちゃうな。(たとえば、urlencodeみたいなヤツ)

Daisukeh 2009/03/04 10:48 更新 2.20

 {{rss>...}}はとても便利なのだが、やっぱりポート番号が消えてしまう(?)のがいただけない。何故なのだろうか?このサイトではRedmineを使っているため、必然的に(というかデフォルトで)Railsのポートが3000番になっている。{{rss>...}}で表示できるのはいいのだが、リンクが切れるのは好ましくない。したがって、このプログラムに HTML で記述した概要の表示モード追加した。使い方はソースコードを参照してください。あわせて、plugin:phpincの、指定したPHPプログラムをインクルードする部分をincludeからinclude_onceに変更した。チョッとのことだけど、これがあるとないとでは、ページ記述の利便性が大きく変わる。

掲示板

, 2012/10/16 04:35
You put the lime in the coconut and drink the atrcile up.
, 2013/02/02 11:44
Hello! effgade interesting effgade site! I'm really like it! Very, very effgade good!
, 2013/02/02 11:44
Very nice site!
, 2013/02/02 11:44
Hello! abgdebe interesting abgdebe site! I'm really like it! Very, very abgdebe good!
, 2013/02/02 11:45
Very nice site!
, 2017/04/10 00:42
cheap authentic jerseys սsa (Buford) nfl shop jerseys
, 2017/04/10 00:42
cheap authentic jerseys usɑ (Buford) nfl shop jerseys
, 2017/05/14 08:11
cheap china jerseys nfl cheap nike frolm china
, 2017/05/14 08:11
cheap china jerseys nfl cheap nike fгom china
, 2017/05/25 13:06
on field jerse cheap jersey fabric
, 2017/05/25 13:06
on field jersey cheap jersey fabric
, 2018/01/17 04:06
When I initially commented I clicked the "Notify me when new comments are added"
checkbox and now each time a comment is added I get four e-mails with the same
comment. Is there any way you can remove people from that service?
Appreciate it!cheap NFL jerseys
, 2018/01/17 04:06
When I initially commented I clicked the "Notify me when new comments are added"
checkbox and now each time a comment is added I get four e-mails with
the same comment. Is there any way you can remove people from that service?
Appreciate it!cheap NFL jerseys
, 2018/03/02 03:28
Peculiar article, exactly what I wanted to find.wholesale jerseys
, 2018/03/02 03:28
Peculiar article, exactly what I wanted to find.wholesale jerseys
, 2018/03/31 06:50
It is not my first time to go to see this web site, i am browsing
this site dailly and take fastidious information from here daily.cheap
NFL jerseys
, 2018/03/31 06:50
It is not my first time to go to see this web site, i am browsing this site
dailly and take fastidious information from here daily.cheap NFL jerseys
, 2018/04/06 13:16
What i do not realize is in truth how you are no longer actually much more neatly-favored than you may be now.
You are so intelligent. You already know thus considerably relating to this subject, made me in my view imagine it from a lot of various angles.
Its like women and men are not fascinated
until it's one thing to do with Girl gaga! Your personal stuffs nice.
Always maintain it up!wholesale MLB jerseys
, 2018/04/06 13:16
What i do not realize is in truth how you are no longer actually much more neatly-favored
than you may be now. You are so intelligent. You already know
thus considerably relating to this subject, made me in my view imagine
it from a lot of various angles. Its like women and men are not fascinated until it's one thing to do with Girl gaga!

Your personal stuffs nice. Always maintain it up!wholesale MLB jerseys
, 2018/04/09 19:42
It's amazing for me to have a web page, which is valuable for my experience.

thanks adminwholesale jerseys (Addie)
, 2018/04/09 19:42
It's amazing for me to have a web page, which is
valuable for my experience. thanks adminwholesale jerseys (Addie)
, 2018/04/14 09:42
I need to to thank you for this fantastic read!! I definitely enjoyed every little bit of it.
I have you bookmarked to look at new stuff you post…wholesale jerseys
, 2018/04/14 09:42
I need to to thank you for this fantastic read!! I definitely enjoyed every little bit of it.
I have you bookmarked to look at new stuff you post…wholesale jerseys
, 2018/04/23 12:13
Its like you read my mind! You seem to know a lot about this, like you wrote the book
in it or something. I think that you can do with
a few pics to drive the message home a little bit, but other than that, this is magnificent blog.

A great read. I will definitely be back.cheap NHL jerseys
, 2018/04/23 12:13
Its like you read my mind! You seem to know a lot about this, like you wrote the book in it or something.
I think that you can do with a few pics to drive the message
home a little bit, but other than that, this is magnificent blog.
A great read. I will definitely be back.cheap NHL jerseys
, 2018/05/03 02:25
You're so awesome! I do not think I've truly read anything like that before.
So wonderful to discover somebody with a few genuine thoughts on this topic.
Really.. thanks for starting this up. This web site is something that is needed on the web,
someone with a little originality!cheap NBA jerseys
, 2018/05/03 02:25
You're so awesome! I do not think I've truly read anything
like that before. So wonderful to discover somebody with a few genuine thoughts
on this topic. Really.. thanks for starting this up.
This web site is something that is needed on the web, someone
with a little originality!cheap NBA jerseys
, 2018/05/18 02:17
When someone writes an post he/she maintains the
plan of a user in his/her mind that how a user can know it.
Therefore that's why this post is outstdanding. Thanks!146832
, 2018/05/18 02:17
When someone writes an post he/she maintains the plan of a
user in his/her mind that how a user can know it.
Therefore that's why this post is outstdanding.
Thanks!146832
, 2018/05/20 16:14
This website certainly has all the information and facts I needed
concerning this subject and didn't know who to ask.
cheap ncaa jerseys
, 2018/05/20 16:14
This website certainly has all the information and facts I needed concerning this subject and didn't know
who to ask. cheap ncaa jerseys
, 2018/05/21 13:13
I have been surfing online greater than 3 hours lately, yet I never discovered any interesting article like yours.
It is beautiful price sufficient for me.
In my opinion, if all web owners and bloggers made good content material as you
probably did, the web shall be much more helpful than ever before.p10120
, 2018/05/21 13:13
I have been surfing online greater than 3 hours lately, yet I never discovered any interesting article like yours.
It is beautiful price sufficient for me. In my opinion, if
all web owners and bloggers made good content material as you
probably did, the web shall be much more helpful than ever before.p10120
, 2018/05/24 07:49
Great article, totally what I wanted to find.146832
, 2018/05/24 07:49
Great article, totally what I wanted to find.146832
, 2018/05/26 13:51
I really like it when people come together and share views.

Great blog, continue the good work!p120123
, 2018/05/26 13:51
I really like it when people come together and share views.
Great blog, continue the good work!p120123
, 2018/08/03 07:32
I think I can help answer your questions.
bikini swimsuit cheap bikinis wynrba67241
, 2018/08/03 07:32
I think I can help answer your questions.
bikini swimsuit cheap bikinis wynrba67241
, 2018/08/04 03:28
Trading Forex gives traders the option to trade at their own time or pleasure.

Actually, it's open from 3pm EST, on Sundays, and runs 24
hours a day, until 4pm EST on Fridays.
Cheap Swimsuits Cheap Swimsuits ttpjdb51049
, 2018/08/04 03:28
Trading Forex gives traders the option to trade at their own time or pleasure.
Actually, it's open from 3pm EST, on Sundays, and runs
24 hours a day, until 4pm EST on Fridays.
Cheap Swimsuits Cheap Swimsuits ttpjdb51049
, 2018/08/09 06:22
She is 4 quadrillion light years old and would like to give earth a space age
makeover. She can't keep her feet on the ground,
which results in her floating; she wears glittery
and trendy fashions.
hair extension hair extension vxeodi71061wigs 10834
, 2018/08/09 06:22
She is 4 quadrillion light years old and would like to give
earth a space age makeover. She can't keep her feet on the ground,
which results in her floating; she wears glittery and trendy
fashions.
hair extension hair extension vxeodi71061wigs 10834
, 2018/08/14 23:57
In 1773, he was appointed high sheriff of Bedfordshire and
supervision of the county jail became of one his responsibilities.
He was shocked by the conditions he found there and visited others in England, where the situation was no better.

Cheap Jerseys from china wholesale jerseys uhusbo5798
, 2018/08/14 23:57
In 1773, he was appointed high sheriff of Bedfordshire
and supervision of the county jail became of one his responsibilities.
He was shocked by the conditions he found there
and visited others in England, where the situation was no better.

Cheap Jerseys from china wholesale jerseys uhusbo5798
, 2018/08/29 05:59
I didn't like boys then, but I figured that if I waited, I would eventually.
(I'm still waiting. I don't think I'll ever stop waiting.) Until then, I just remained quiet about the issue.


dildos 33604
, 2018/08/29 05:59
I didn't like boys then, but I figured that if I waited, I
would eventually. (I'm still waiting. I don't think I'll ever stop waiting.) Until then, I just
remained quiet about the issue.
dildos 33604
Enter your comment
 
 
programming/dokuwiki/内部フィードを表示する.txt · 最終更新: 2009/08/05 14:45 by daisukeh
 

Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS
Driven by DokuWiki Powered by Google do yourself a favour and use a real browser - get firefox ! GIMP is the GNU Image Manipulation Program. Adobe Flex smarty : Template Engine