<html>
-<head>
-<title>keitairc: Êѹ¹ÍúÎò</title>
-<link type="text/css" rel="stylesheet" href="default.css">
-<meta content="text/html; charset=euc-jp" http-equiv="Content-Type">
-</head>
-<body>
-
-<h1>keitairc: Êѹ¹ÍúÎò</h1>
-
-<p>
- <a href="index.html">¥È¥Ã¥×¥Ú¡¼¥¸</a> |
- <a href="index.html#license">¥é¥¤¥»¥ó¥¹</a> |
- <a href="index.html#environment">Æ°ºî´Ä¶</a> |
- <a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a> |
- <a href="index.html#usage">»È¤¤Êý</a> |
- <a href="index.html#development">³«È¯</a> |
- <a href="index.html#security">¥»¥¥å¥ê¥Æ¥£</a> |
- <a href="faq.html">FAQ</a> |
- Êѹ¹ÍúÎò
-</p>
-
-<dl>
-
-<dt>1.30
-<dd>³°ÉôURL¤Ø¤Î¥ê¥ó¥¯¤Ë¡¢Google Wireless Transcoder ¤ò²ð¤·¤¿¥ê¥ó¥¯¤òÄɲÃ<br>
-³°ÉôURL¤Ø¤Î¥ê¥ó¥¯¤Ë¡¢au·ÈÂӤΡÖPC¥µ¥¤¥È¥Ó¥å¡¼¥¢¡¼¡×¤ò²ð¤·¤¿¥ê¥ó¥¯¤òÄɲÃ
-(thanks to ¤¤¤·¤«¤ï¤à¤Ä¤ß»á)
-
-<dt>1.29
-<dd>topic°ìÍ÷ÄɲÃ
-
-<dt>1.28
-<dd>AirH" Phone¤Ê¤ÉCookieÂбþüËö¤Î¤¿¤á¤Ë¡¢CookieÂбþ¤·¤Þ¤·¤¿¡£
-°ìÅ٥桼¥¶Ì¾¡¢¥Ñ¥¹¥ï¡¼¥Éǧ¾Ú¤ò¹Ô¤Ê¤¨¤Ð¡¢Cookie¤Ëµ²±¤µ¤ì¤ë¤Î¤Ç¡¢
-¼¡¤«¤é¤Ï¥æ¡¼¥¶Ì¾¡¢¥Ñ¥¹¥ï¡¼¥É¤òÆþÎϤ¹¤ëɬÍפ¬¤¢¤ê¤Þ¤»¤ó¡£
-~/.keitairc¤Ë<tt>use_cookie = yes</tt>¤ÎÄɲä¬É¬ÍפǤ¹¡£
-(thanks to
-<a href="http://naimune.com/keitairc/">http://naimune.com/keitairc/</a>:
-¤Ò¤Á¤µ¤È¤¸¤å¤ó»á)
-
-<dt>1.27
-<dd>̤ÆɥХåե¡¤Î°·¤¤¤¬¤ª¤«¤·¤«¤Ã¤¿
-
-<dt>1.26
-<dd>¤Þ¤È¤áÆɤߤ«¤é¡¢ÆüËܸì¤äÂçʸ»ú±Ñʸ»ú¤ÎÆþ¤Ã¤¿¥Á¥ã¥Í¥ë̾¤Ë°ÜÆ°¤·¤Æȯ¸À¤¹¤ë¤È¡¢
-¾¿Í¤â´¬¤¹þ¤ó¤Ç¤ª¤«¤·¤¯¤·¤Æ¤·¤Þ¤Ã¤¿¤Î¤ò½¤Àµ<br>
-̤ÆɹԿôɽ¼¨¤¬¤ª¤«¤·¤«¤Ã¤¿¤Î¤ò½¤Àµ
-
-<dt>1.25
-<dd>Á´¥Á¥ã¥Í¥ë¤Î̤ÆɤޤȤáÆɤßÄɲÃ
-
-<dt>1.23
-<dd>¥Á¥ã¥Í¥ë̾¤ÎÆâÉô½èÍý¤Ï¾®Ê¸»ú¤ËÀµµ¬²½¤·¤Æ°·¤¦ (thanks to Akira Yamada)
-
-<dt>1.22
-<dd>ezweb üËö¤Î subscriber ID ¤òÍøÍѤ·¤¿Ç§¾Ú¤ËÂбþ (thanks to Takuo KITAME)
-
-<dt>1.21
-<dd>CTCP ACTION ¤ËÂбþ (thanks to Akira Tagoh)<br>
- Ϣ³¤·¤¿ HTML ¥¨¥¹¥±¡¼¥×¤¬¤Ç¤¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤ò½¤Àµ
-
-<dt>1.20
-<dd>madoka ¤Ë¤Ä¤Ê¤¤¤Ç»È¤¦¤È¡¢Ã¯¤«¤¬ JOIN ¤¹¤ë¤È
- channel ¤¬Áý¤¨¤¿¤è¤¦¤Ë¸«¤¨¤ë¸½¾Ý¤ò²óÈò<br>
- (thanks to ¾¾°æ¤µ¤ó <matsui at iij-mc.co.jp>)
-
-<dt>1.19
-<dd>¥Á¥ã¥Í¥ë¥ê¥¹¥È¤Îȯ¸À¿ôɽ¼¨¤¬¤ª¤«¤·¤¤¤³¤È¤¬¤¢¤Ã¤¿<br>
- foo@bar ·Á¼°¤ò mailto ¥ê¥ó¥¯¤Ë¤·¤Ê¤¤¤è¤¦¤Ë¤·¤¿<br>
- https:// ·Á¼°¤â¥ê¥ó¥¯¤Ë<br>
- 狼¤¬ channel ¤«¤éÈ´¤±¤¿¤È¤¤Î¥á¥Ã¥»¡¼¥¸¤ò½ñ¼°Êѹ¹<br>
- 狼¤¬ channel ¤Ë join ¤·¤Æ¤¤¿¤È¤¤Ë¥á¥Ã¥»¡¼¥¸¤òÄɲÃ
-
-<dt>1.18
-<dd>jis ¤Î¥Á¥ã¥Í¥ë̾¤ò uri escape ¤·¤Æ°ú¿ô¤ËÅϤ¹¤È WAP ¥²¡¼¥È¥¦¥§¥¤¤¬
- ¾¡¼ê¤Ë unescape ¤·¤Æ¤·¤Þ¤¤¡¢xhtml üËö¤Ç¥Á¥ã¥Í¥ë̾¤Î¼õ¤±ÅϤ·¤¬¤ª¤«
- ¤·¤¯¤Ê¤ë¤Î¤Ç¡¢¤¤¤Á¤¤¤Á uri_unescape() ¤·¤¿¤â¤Î¤ò uri_escape() ¤¹¤ë
- ¤è¤¦¤ËÊѹ¹(ISHIKAWA)
-
-<dt>1.17
-<dd>ȯ¸À¸å¤Î¥Ç¥£¥Õ¥©¥ë¥È¤ÎµóÆ°¤ò¥ª¥ê¥¸¥Ê¥ë¤ÎÁ´È¯¸Àɽ¼¨¤ËÌ᤹¡£
- ̤ÆɤΤߤÎɽ¼¨¤Ë¤·¤¿¤¤»þ¤Ï .keitairc ¤Ë show_newmsgonly ¤òÀßÄê
- ¤·¤Æ¤¯¤À¤µ¤¤(ISHIKAWA)
-
-<dt>1.16
-<dd>ÁêÂХѥ¹¤Ç¤Î¥ê¥ó¥¯¤¬xhtmlüËö¤Ç¤¦¤Þ¤¯µ¡Ç½¤·¤Ê¤¤¤Î
- ÀäÂХѥ¹¤ËÊѹ¹ (ISHIKAWA)
-
-<dt>1.15
-<dd>xhtmlüËö¤Ç¤Î¥¥ã¥Ã¥·¥åÍÞÀ© (ISHIKAWA)
-
-<dt>1.14
-<dd> </head>¤¬È´¤±¤Æ¤¤¤¿¤È¤³¤¬¤¢¤Ã¤¿¤Î¤ÇÁÞÆþ
- (ISHIKAWA)
-
-<dt>1.13
-<dd>ºÙ¤«¤¤½¤Àµ
-
-<dt>1.12
-<dd>¾¤Î¥æ¡¼¥¶¤¬ channel ¤ò part ¤·¤¿¤È¤¤Ë keitairc ¤Î¥Á¥ã¥Í¥ë¥ê¥¹¥È¤«¤é
+ <head>
+ <title>keitairc: Êѹ¹ÍúÎò</title>
+ <link type="text/css" rel="stylesheet" href="default.css">
+ <meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
+ </head>
+ <body>
+
+ <h1>keitairc: Êѹ¹ÍúÎò</h1>
+
+ <p>
+ <a href="index.html">¥È¥Ã¥×¥Ú¡¼¥¸</a> |
+ <a href="index.html#license">¥é¥¤¥»¥ó¥¹</a> |
+ <a href="index.html#environment">Æ°ºî´Ä¶</a> |
+ <a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a> |
+ <a href="index.html#usage">»È¤¤Êý</a> |
+ <a href="index.html#development">³«È¯</a> |
+ <a href="index.html#security">¥»¥¥å¥ê¥Æ¥£</a> |
+ <a href="faq.html">FAQ</a> |
+ Êѹ¹ÍúÎò
+ </p>
+
+ <dl>
+
+ <dt>1.31</dt>
+ <dd>
+ ¿·¤·¤¤POE¤Îµ¯Æ°¥á¥½¥Ã¥É¤ËÂбþ<br>
+ irc¥µ¡¼¥Ð¤«¤éÀÚÃǤµ¤ì¤¿ºÝ¤ËºÆÀܳ¤¹¤ë¤è¤¦¤Ë¤·¤¿<br>
+ <tt>Jcode</tt>¥Ñ¥Ã¥±¡¼¥¸¤ÎÍøÍѤò¤ä¤á¡¢<tt>Unicode::Japanese</tt>¤ËÀÚ¤êÂؤ¨<br>
+ daemon²½¤·¤Æµ¯Æ°¤µ¤»¤ë¥ª¥×¥·¥ç¥ó¤òÄɲá£<tt>Proc::Daemon</tt>¤òÍøÍÑ<br>
+ ¥Ç¥Õ¥©¥ë¥È¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Ê¤¤»þ¥ï¡¼¥Ë¥ó¥°¤ò½Ð¤µ¤Ê¤¤¤è¤¦¤Ë¤·¤¿<br>
+ ¥¹¥é¥Ã¥·¥å¤Ç½ª¤ï¤Ã¤Æ¤¤¤ëURL¤ËÀµ¤·¤¯¥ê¥ó¥¯¤¹¤ë¤è¤¦¤Ë¤·¤¿<br>
+ °ìÈ̥֥饦¥¶¸þ¤±URL¤Ë¡Ö¥Ý¥±¥Ã¥È¤Ï¤Æ¤Ê¡×¤ò²ð¤·¤Æ¥¢¥¯¥»¥¹¤¹¤ë¥ê¥ó¥¯¤òÉÕ¤±¤ë¤è¤¦¤Ë¤·¤¿ (Google Wireless Transcoder¤ò²ð¤·¤Æ¥¢¥¯¥»¥¹¤¹¤ë¥ê¥ó¥¯¤ÏÇÑ»ß)
+ </dd>
+
+ <dt>1.30</dt>
+ <dd>
+ ³°ÉôURL¤Ø¤Î¥ê¥ó¥¯¤Ë¡¢Google Wireless Transcoder ¤ò²ð¤·¤¿¥ê¥ó¥¯¤òÄɲÃ<br>
+ ³°ÉôURL¤Ø¤Î¥ê¥ó¥¯¤Ë¡¢au·ÈÂӤΡÖPC¥µ¥¤¥È¥Ó¥å¡¼¥¢¡¼¡×¤ò²ð¤·¤¿¥ê¥ó¥¯¤òÄɲÃ
+ (thanks to ¤¤¤·¤«¤ï¤à¤Ä¤ß»á)
+ </dd>
+
+ <dt>1.29</dt>
+ <dd>
+ topic°ìÍ÷ÄɲÃ
+ </dd>
+
+ <dt>1.28</dt>
+ <dd>
+ AIR-EDGE Phone¤Ê¤ÉCookieÂбþüËö¤Î¤¿¤á¤Ë¡¢CookieÂбþ¤·¤Þ¤·¤¿¡£
+ °ìÅ٥桼¥¶Ì¾¡¢¥Ñ¥¹¥ï¡¼¥Éǧ¾Ú¤ò¹Ô¤Ê¤¨¤Ð¡¢Cookie¤Ëµ²±¤µ¤ì¤ë¤Î¤Ç¡¢
+ ¼¡¤«¤é¤Ï¥æ¡¼¥¶Ì¾¡¢¥Ñ¥¹¥ï¡¼¥É¤òÆþÎϤ¹¤ëɬÍפ¬¤¢¤ê¤Þ¤»¤ó¡£
+ ~/.keitairc¤Ë<tt>use_cookie = yes</tt>¤ÎÄɲä¬É¬ÍפǤ¹¡£
+ (thanks to
+ <a href="http://naimune.com/keitairc/">http://naimune.com/keitairc/</a>:
+ ¤Ò¤Á¤µ¤È¤¸¤å¤ó»á)
+ </dd>
+
+ <dt>1.27</dt>
+ <dd>
+ ̤ÆɥХåե¡¤Î°·¤¤¤¬¤ª¤«¤·¤«¤Ã¤¿
+ </dd>
+
+ <dt>1.26</dt>
+ <dd>
+ ¤Þ¤È¤áÆɤߤ«¤é¡¢ÆüËܸì¤äÂçʸ»ú±Ñʸ»ú¤ÎÆþ¤Ã¤¿¥Á¥ã¥Í¥ë̾¤Ë°ÜÆ°¤·¤Æȯ¸À¤¹¤ë¤È¡¢
+ ¾¿Í¤â´¬¤¹þ¤ó¤Ç¤ª¤«¤·¤¯¤·¤Æ¤·¤Þ¤Ã¤¿¤Î¤ò½¤Àµ<br>
+ ̤ÆɹԿôɽ¼¨¤¬¤ª¤«¤·¤«¤Ã¤¿¤Î¤ò½¤Àµ
+ </dd>
+
+ <dt>1.25</dt>
+ <dd>
+ Á´¥Á¥ã¥Í¥ë¤Î̤ÆɤޤȤáÆɤßÄɲÃ
+ </dd>
+
+ <dt>1.23</dt>
+ <dd>
+ ¥Á¥ã¥Í¥ë̾¤ÎÆâÉô½èÍý¤Ï¾®Ê¸»ú¤ËÀµµ¬²½¤·¤Æ°·¤¦ (thanks to Akira Yamada)
+ </dd>
+
+ <dt>1.22</dt>
+ <dd>
+ EZweb üËö¤Î subscriber ID ¤òÍøÍѤ·¤¿Ç§¾Ú¤ËÂбþ (thanks to Takuo KITAME)
+ </dd>
+
+ <dt>1.21</dt>
+ <dd>
+ CTCP ACTION ¤ËÂбþ (thanks to Akira Tagoh)<br>
+ Ϣ³¤·¤¿ HTML ¥¨¥¹¥±¡¼¥×¤¬¤Ç¤¤Æ¤¤¤Ê¤«¤Ã¤¿¤Î¤ò½¤Àµ
+ </dd>
+
+ <dt>1.20</dt>
+ <dd>
+ madoka ¤Ë¤Ä¤Ê¤¤¤Ç»È¤¦¤È¡¢Ã¯¤«¤¬ JOIN ¤¹¤ë¤È
+ channel ¤¬Áý¤¨¤¿¤è¤¦¤Ë¸«¤¨¤ë¸½¾Ý¤ò²óÈò<br>
+ (thanks to ¾¾°æ¤µ¤ó <matsui at iij-mc.co.jp>)
+ </dd>
+
+ <dt>1.19</dt>
+ <dd>
+ ¥Á¥ã¥Í¥ë¥ê¥¹¥È¤Îȯ¸À¿ôɽ¼¨¤¬¤ª¤«¤·¤¤¤³¤È¤¬¤¢¤Ã¤¿<br>
+ foo@bar ·Á¼°¤ò mailto ¥ê¥ó¥¯¤Ë¤·¤Ê¤¤¤è¤¦¤Ë¤·¤¿<br>
+ https:// ·Á¼°¤â¥ê¥ó¥¯¤Ë<br>
+ 狼¤¬ channel ¤«¤éÈ´¤±¤¿¤È¤¤Î¥á¥Ã¥»¡¼¥¸¤ò½ñ¼°Êѹ¹<br>
+ 狼¤¬ channel ¤Ë join ¤·¤Æ¤¤¿¤È¤¤Ë¥á¥Ã¥»¡¼¥¸¤òÄɲÃ
+ </dd>
+
+ <dt>1.18</dt>
+ <dd>
+ jis ¤Î¥Á¥ã¥Í¥ë̾¤ò uri escape ¤·¤Æ°ú¿ô¤ËÅϤ¹¤È WAP ¥²¡¼¥È¥¦¥§¥¤¤¬
+ ¾¡¼ê¤Ë unescape ¤·¤Æ¤·¤Þ¤¤¡¢xhtml üËö¤Ç¥Á¥ã¥Í¥ë̾¤Î¼õ¤±ÅϤ·¤¬¤ª¤«
+ ¤·¤¯¤Ê¤ë¤Î¤Ç¡¢¤¤¤Á¤¤¤Á uri_unescape() ¤·¤¿¤â¤Î¤ò uri_escape() ¤¹¤ë
+ ¤è¤¦¤ËÊѹ¹(ISHIKAWA)
+ </dd>
+
+ <dt>1.17</dt>
+ <dd>
+ ȯ¸À¸å¤Î¥Ç¥£¥Õ¥©¥ë¥È¤ÎµóÆ°¤ò¥ª¥ê¥¸¥Ê¥ë¤ÎÁ´È¯¸Àɽ¼¨¤ËÌ᤹¡£
+ ̤ÆɤΤߤÎɽ¼¨¤Ë¤·¤¿¤¤»þ¤Ï .keitairc ¤Ë show_newmsgonly ¤òÀßÄê
+ ¤·¤Æ¤¯¤À¤µ¤¤(ISHIKAWA)
+ </dd>
+
+ <dt>1.16</dt>
+ <dd>
+ ÁêÂХѥ¹¤Ç¤Î¥ê¥ó¥¯¤¬xhtmlüËö¤Ç¤¦¤Þ¤¯µ¡Ç½¤·¤Ê¤¤¤Î
+ ÀäÂХѥ¹¤ËÊѹ¹ (ISHIKAWA)
+ </dd>
+
+ <dt>1.15</dt>
+ <dd>
+ xhtmlüËö¤Ç¤Î¥¥ã¥Ã¥·¥åÍÞÀ© (ISHIKAWA)
+ </dd>
+
+ <dt>1.14</dt>
+ <dd>
+ </head>¤¬È´¤±¤Æ¤¤¤¿¤È¤³¤¬¤¢¤Ã¤¿¤Î¤ÇÁÞÆþ
+ (ISHIKAWA)
+ </dd>
+
+ <dt>1.13</dt>
+ <dd>
+ ºÙ¤«¤¤½¤Àµ
+ </dd>
+
+ <dt>1.12</dt>
+ <dd>
+ ¾¤Î¥æ¡¼¥¶¤¬ channel ¤ò part ¤·¤¿¤È¤¤Ë keitairc ¤Î¥Á¥ã¥Í¥ë¥ê¥¹¥È¤«¤é
¤½¤Î¥Á¥ã¥Í¥ë¤¬¾Ã¤¨¤Æ¤·¤Þ¤¦·ï¤ò½¤Àµ¡£¤É¤Î¥æ¡¼¥¶¤¬È´¤±¤¿¤«¤âɽ¼¨¡£
(thanks to Ichiro FUKUHARA <ichiro at ichiro.org>)
+ </dd>
-<dt>1.11
-<dd>̤ÆɹԿô¤ò¼¨¤¹¥ê¥ó¥¯¤ò¿·Àß(̤ÆɤΤߤòÆɤळ¤È¤¬¤Ç¤¤ë¡£
+ <dt>1.11</dt>
+ <dd>
+ ̤ÆɹԿô¤ò¼¨¤¹¥ê¥ó¥¯¤ò¿·Àß(̤ÆɤΤߤòÆɤळ¤È¤¬¤Ç¤¤ë¡£
(̤ÆɤΤߤΥڡ¼¥¸¤«¤é¥¢¥¯¥»¥¹¥¡¼ [5] ¤Ç¤¹¤Ù¤Æ¤òɽ¼¨)
(thanks to Ichiro FUKUHARA <ichiro at ichiro.org>)
+ </dd>
-<dt>1.9
-<dd>̤ÆɹԿô¤òɽ¼¨¡£¤Þ¤Àȯ¸À¤Î¤Ê¤¤¥Á¥ã¥Í¥ë¤ËÂФ·¤Æ¤âȯ¸À²Äǽ¤Ë
+ <dt>1.9</dt>
+ <dd>
+ ̤ÆɹԿô¤òɽ¼¨¡£¤Þ¤Àȯ¸À¤Î¤Ê¤¤¥Á¥ã¥Í¥ë¤ËÂФ·¤Æ¤âȯ¸À²Äǽ¤Ë
(thanks to Ichiro FUKUHARA <ichiro at ichiro.org>)
+ </dd>
-<dt>1.8
-<dd><a href="http://tagoh.jp/d/?date=20040107#p02">10¸Ä¤á°Ê¹ß¤Î¥Á¥ã¥Í¥ë¤Ø¤Î¥ê¥ó¥¯¤¬¤ª¤«¤·¤«¤Ã¤¿</a><br>
+ <dt>1.8</dt>
+ <dd>
+ <a href="http://tagoh.jp/d/?date=20040107#p02">10¸Ä¤á°Ê¹ß¤Î¥Á¥ã¥Í¥ë¤Ø¤Î¥ê¥ó¥¯¤¬¤ª¤«¤·¤«¤Ã¤¿</a><br>
(thanks to Akira Tagoh)
+ </dd>
-<dt>1.7
-<dd></head>¤ò½ÐÎϤ¹¤ë¤Î¤ò˺¤ì¤Æ¤¤¤Þ¤·¤¿
+ <dt>1.7</dt>
+ <dd>
+ </head>¤ò½ÐÎϤ¹¤ë¤Î¤ò˺¤ì¤Æ¤¤¤Þ¤·¤¿
(thanks to ishikawa[@]netvillage.co.jp)
-
-<dt>1.6
-<dd>¥Á¥ã¥Í¥ë¤ò¸«¤Æ¤¤¤ë¾õÂ֤Υڡ¼¥¸¥¿¥¤¥È¥ë¤¬¤ª¤«¤·¤«¤Ã¤¿<br>
- ¥½¡¼¥¹Ê¸»úÎó¤ò jis ¤Ë·è¤á¤¦¤Á¤·¤Æʸ»ú²½¤±¸º¾¯<br>
- ProxyPass ÍÑ¤Ë web_root ¥ª¥×¥·¥ç¥óÄɲÃ<br>
- i-mode ³¨Ê¸»ú¤Ï»È¤ï¤Ê¤¤¤³¤È¤Ë¤·¤¿
-
-<dt>1.5
-<dd>keitairc ¤«¤é¤Îȯ¸ÀÆâÍƤ¬¼«Ê¬¤«¤é¤Ï
- (keitairc ¤«¤é¤Ï) ʸ»ú²½¤±¤·¤Æ¤ß¤¨¤ë¤³¤È¤¬¤¢¤Ã¤¿¤Î¤ò½¤Àµ
-
-<dt>1.4
-<dd>join ¤·¤Æ¤¤¤¿¥Á¥ã¥Í¥ë¤ò part ¤·¤¿¤È¤¤Ë
- ¥×¥í¥°¥é¥à¤¬Ää»ß¤·¤Æ¤·¤Þ¤Ã¤Æ¤¤¤¿¤Î¤ò½¤Àµ<br>
- ȯ¸ÀÆâÍƤ¬¿·¤·¤¤¥Á¥ã¥Í¥ë¤«¤é¥ê¥¹¥È¥¢¥Ã¥×¤¹¤ë¤è¤¦½¤Àµ
-
-<dt>1.3
-<dd>Ⱦ³Ñ¥¹¥Ú¡¼¥¹¤¬+¤ËÊÑ´¹¤µ¤ì¤Æ¤¤¤¿¤Î¤ò½¤Àµ
-<dt>1.1
-<dd>¸ø³«
-</dl>
-
-
-<p>
-<a href="http://sourceforge.jp/">
-<img src="http://sourceforge.jp/sflogo.php?group_id=1057"
- width="96" height="31" border="0" align=right
- alt="SourceForge.jp"></a>
-</p>
-
-</BODY>
-</HTML>
+ </dd>
+
+ <dt>1.6</dt>
+ <dd>
+ ¥Á¥ã¥Í¥ë¤ò¸«¤Æ¤¤¤ë¾õÂ֤Υڡ¼¥¸¥¿¥¤¥È¥ë¤¬¤ª¤«¤·¤«¤Ã¤¿<br>
+ ¥½¡¼¥¹Ê¸»úÎó¤ò jis ¤Ë·è¤á¤¦¤Á¤·¤Æʸ»ú²½¤±¸º¾¯<br>
+ ProxyPass ÍÑ¤Ë web_root ¥ª¥×¥·¥ç¥óÄɲÃ<br>
+ i¥â¡¼¥É³¨Ê¸»ú¤Ï»È¤ï¤Ê¤¤¤³¤È¤Ë¤·¤¿
+ </dd>
+
+ <dt>1.5</dt>
+ <dd>
+ keitairc ¤«¤é¤Îȯ¸ÀÆâÍƤ¬¼«Ê¬¤«¤é¤Ï
+ (keitairc ¤«¤é¤Ï) ʸ»ú²½¤±¤·¤Æ¤ß¤¨¤ë¤³¤È¤¬¤¢¤Ã¤¿¤Î¤ò½¤Àµ
+ </dd>
+
+ <dt>1.4</dt>
+ <dd>
+ join ¤·¤Æ¤¤¤¿¥Á¥ã¥Í¥ë¤ò part ¤·¤¿¤È¤¤Ë
+ ¥×¥í¥°¥é¥à¤¬Ää»ß¤·¤Æ¤·¤Þ¤Ã¤Æ¤¤¤¿¤Î¤ò½¤Àµ<br>
+ ȯ¸ÀÆâÍƤ¬¿·¤·¤¤¥Á¥ã¥Í¥ë¤«¤é¥ê¥¹¥È¥¢¥Ã¥×¤¹¤ë¤è¤¦½¤Àµ
+ </dd>
+
+ <dt>1.3</dt>
+ <dd>
+ Ⱦ³Ñ¥¹¥Ú¡¼¥¹¤¬+¤ËÊÑ´¹¤µ¤ì¤Æ¤¤¤¿¤Î¤ò½¤Àµ
+ </dd>
+
+ <dt>1.1</dt>
+ <dd>
+ ¸ø³«
+ </dd>
+ </dl>
+
+ <p>
+ <a href="http://sourceforge.jp/">
+ <img src="http://sourceforge.jp/sflogo.php?group_id=1057"
+ width="96" height="31" border="0" align="right"
+ alt="SourceForge.jp"></a>
+ </p>
+
+ </body>
+</html>
<html>
-<head>
-<title>keitairc</title>
-<link type="text/css" rel="stylesheet" href="default.css">
-<meta content="text/html; charset=euc-jp" http-equiv="Content-Type">
-</head>
-<body>
-
-<img src="phones.jpg" width=183 height=319 align=left alt=""
- style="margin-right: 5em;">
-
-<h1>keitairc</h1>
-
-<p class="flushleft">
-morimoto@mrmt.net<br>
-$Id: index.html,v 1.37 2006-08-26 05:18:10 morimoto Exp $
-</p>
-
-<hr>
-
-<p>
-i-mode, EZweb, vodafone live!, AIR-EDGE Phone ¤Ê¤É¤Î¥Ö¥é¥¦¥¶¥Õ¥©¥ó¤«¤éircÁàºî¤¬¤Ç¤¤Þ¤¹¡£
-¤â¤Á¤í¤ó¡¢¥Ñ¥½¥³¥ó¤«¤é»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤âÊ̤˹½¤¤¤Þ¤»¤ó¡£
-plum ¤Ê¤É¤Î pirc (irc ¥×¥í¥¥·) ¤ËÀܳ¤·¤Æ»È¤ï¤ì¤ë¤³¤È¤òÁÛÄꤷ¤Æ¤¤¤Þ¤¹¡£
-</p>
-
-<ul>
-<li>¥¢¥¯¥»¥¹¥¡¼¤Ç·Ú²÷¤ËÁàºî<br>
-<li>ȯ¸ÀÃæ¤ÎÅÅÏÃÈֹ桢URL ¤Ë¤Ï¾¡¼ê¤Ë¥ê¥ó¥¯¡£<br>
-ÅÅÏÃÈÖ¹æ¤Ï²¡¤»¤ÐÅÅÏäǤ¤Þ¤¹¡£<br>
-URL¥ê¥ó¥¯¤Ï¡¢Google Wireless Transcoder ¤ò²ð¤·¤¿±ÜÍ÷¥ê¥ó¥¯¡¢
-PC¥µ¥¤¥È¥Ó¥å¡¼¥¢¡¼¤ò²ð¤·¤¿±ÜÍ÷¥ê¥ó¥¯(au¤ÎÂбþüËö¤Î¤ß)¤âÂбþ¡£
-<li>plum ¤Î multicast.plm ¤ò»È¤Ã¤Æ¤¤¤Æ¤âÂç¾æÉס£
-<li>¥Ñ¥¹¥ï¡¼¥Éǧ¾ÚÂбþ¡£EZwebüËö¤Ç¤ÏEZÈÖ¹æǧ¾ÚÂбþ¡£
-AIR-EDGE Phone¤Ê¤É¤Ç¤ÏCookieǧ¾Ú¤Ë¤âÂбþ¡£
-</ul>
-
-
-<p>
- <a href="#license">¥é¥¤¥»¥ó¥¹</a> |
- <a href="#environment">Æ°ºî´Ä¶</a> |
- <a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a> |
- <a href="#usage">»È¤¤Êý</a> |
- <a href="#development">³«È¯</a> |
- <a href="#security">¥»¥¥å¥ê¥Æ¥£</a> |
- <a href="faq.html">FAQ</a> |
- <a href="changes.html">Êѹ¹ÍúÎò</a>
-</p>
-
-<p>
-<a href="http://sourceforge.jp/">
-<img src="http://sourceforge.jp/sflogo.php?group_id=1057"
- width="96" height="31" border="0" align=right
- alt="SourceForge.jp"></a>
-</p>
-
-<br clear=all>
-
-<h2><a name="license">¥é¥¤¥»¥ó¥¹</a></h2>
-
-<p>
-Copyright (c) 2003 Jun Morimoto <morimoto@mrmt.net><br>
-This program is covered by the GNU General Public License 2.
-</p>
-
-<h2><a name="version">ºÇ¿·¥Ð¡¼¥¸¥ç¥ó</a></h2>
-<p>
-keitairc 1.30¤Ç¤¹¡£<br>
-¤è¤±¤ì¤Ð <a href="http://diary.mrmt.net/item/321">1.31beta</a> ¤â¤ª¤¿¤á¤·¤¯¤À¤µ¤¤¡£<br>
-¤Á¤Ê¤ß¤Ë¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤Ï¡¢Ã±¤Ë keitairc ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Î CVS rcsid ¤ò¼è¤Ã¤Æ¤¤¤ë¤À¤±¤Ç¤¹¡£
-</p>
-
-<h2><a name="environment">Æ°ºî´Ä¶</a></h2>
-
-<p>
-Perl 5.6 °Ê¹ß¤È¡¢°Ê²¼¤Ë¼¨¤¹ Perl ¥é¥¤¥Ö¥é¥ê¤¬Æ°ºî¤¹¤ë¥Û¥¹¥È¡£<br>
-¤¹¤Ç¤Ë plum ¤Ê¤É¤Î pirc ¤ò»È¤Ã¤Æ¤¤¤ë¥æ¡¼¥¶¤ÎÍøÍѤò¿ä¾©¤·¤Þ¤¹¡£
-</p>
-
-<h2><a name="screenshot">¥¹¥¯¥ê¡¼¥ó¥·¥ç¥Ã¥È</a></h2>
-
-<table>
-<tr>
-<td>¥Á¥ã¥Í¥ë°ìÍ÷
-<td>¥Á¥ã¥Í¥ëȯ¸ÀÆâÍÆ
-<td>recent (ºÇ¶á¤Îȯ¸À¤Î¤Þ¤È¤á)
-<tr>
-<td><img src="1.gif" alt="" width="220" height="240">
-<td><img src="2.gif" alt="" width="220" height="240">
-<td><img src="3.gif" alt="" width="220" height="240">
-</td>
-</table>
-
-<h2><a name="usage">»È¤¤Êý</a></h2>
-
-<p>
-keitairc ¤òµ¯Æ°¤·¤Æ·ÈÂÓ¤«¤é¥¢¥¯¥»¥¹¤¹¤ë¤È¡¢
-web_username ¤È web_password ¤Ç»ØÄꤷ¤¿¥æ¡¼¥¶Ì¾¤È¥Ñ¥¹¥ï¡¼¥É¤Çǧ¾Ú¤ò¹Ô¤Ê¤Ã¤¿¤Î¤Á¡¢
-¤¤¤Þ»²²Ã¤·¤Æ¤¤¤ëÁ´¤Æ¤Î¥Á¥ã¥Í¥ë°ìÍ÷¤¬½Ð¤Þ¤¹¡£
-ȯ¸ÀÆâÍƤ¬¿·¤·¤¤¥Á¥ã¥Í¥ë¤«¤é½ç¤ËʤӤޤ¹¡£
-¥Á¥ã¥Í¥ë°ìÍ÷¤ÏÅÅÏõ¡¤Î 0 ¤ò²¡¤¹¤È¹¹¿·¤Ç¤¤Þ¤¹¡£<br>
-AIR-EDGE Phone¤Ê¤ÉCookieÂбþµ¡¼ï¤Ç¤Ï¡¢
-use_cookie = yes »ØÄê¤ò¤¹¤ì¤Ð¡¢Ç§¾ÚÆâÍƤò¥¯¥Ã¥¡¼¤ËµÏ¿¤¹¤ë¤³¤È¤Ç¡¢
-°Ê¹ß¤Î¥æ¡¼¥¶Ì¾¡¦¥Ñ¥¹¥ï¡¼¥Éǧ¾Ú¤ò¾Êά¤Ç¤¤Þ¤¹¡£¥¯¥Ã¥¡¼¤ÎÀ¸Â¸»þ´Ö¤Ï3Æü´Ö¤Ç¤¹¡£
-</p>
-
-<p>
-¥Á¥ã¥Í¥ë¤òÁªÂò¤¹¤ë¤È¤½¤Î¥Á¥ã¥Í¥ë¤Îȯ¸ÀÆâÍƤòÆɤá¤Þ¤¹¡£
-Á°²ó keitairc ¤Ç¸«¤¿¤È¤¤è¤ê¤â¿·¤·¤¤È¯¸À¤¬¤¿¤Þ¤Ã¤Æ¤¤¤ë¥Á¥ã¥Í¥ë¡¢
-¤Ä¤Þ¤ê̤ÆÉÆâÍƤΤ¢¤ë¥Á¥ã¥Í¥ë¤Ë¤Ï̾Á°¤Î¸å¤í¤Ë̤ÆɹԿô¥ê¥ó¥¯¤¬¤Ä¤¤Þ¤¹¡£
-̤ÆɹԿô¥ê¥ó¥¯¤òÁªÂò¤¹¤ë¤È¡¢Ì¤ÆÉÉôʬ¤À¤±¤òÆɤळ¤È¤¬¤Ç¤¤Þ¤¹¡£
-̤ÆÉÉôʬ¤À¤±¤òÆɤó¤Ç¤¤¤Æ¡¢´ûÆÉÉôʬ¤â¸«¤¿¤¤¾ì¹ç¤Ï¡¢<samp>...more[5]</samp>
-¤òÁªÂò¤¹¤ë¤È´ûÆÉÉôʬ¤â¸«¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
-
-<p>
-¤Þ¤¿¡¢Ì¤ÆÉÆâÍƤΤ¢¤ë¥Á¥ã¥Í¥ë¤¬¤Ò¤È¤Ä¤Ç¤â¤¢¤ë¾ì¹ç¤Ï¡¢
-¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Ë recent ¥ê¥ó¥¯¤¬¤Ä¤¤Þ¤¹¡£
-recent ¥ê¥ó¥¯¤Ï¡¢Ã¼Ëö¤Ë¤è¤Ã¤Æ¤Ï * ¥¡¼¤ò²¡¤¹¤À¤±¤Ç¤â¹Ô¤¯¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
-recent ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢Á´¥Á¥ã¥Í¥ë¤Î̤Æɤò¤Þ¤È¤áÆɤߤǤ¤Þ¤¹¡£<br>
-¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Î topics ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢Á´¥Á¥ã¥Í¥ë¤Î¥È¥Ô¥Ã¥¯¤ò°ìÍ÷¤Ç¤¤Þ¤¹¡£
-topics ¥ê¥ó¥¯¤Ï¡¢Ã¼Ëö¤Ë¤è¤Ã¤Æ¤Ï * ¥¡¼¤ò²¡¤¹¤À¤±¤Ç¤â¹Ô¤¯¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
-
-<p>
-¥Á¥ã¥Í¥ë¤Îȯ¸ÀÆâÍƤòÆɤó¤Ç¤¤¤Æ¡¢
-ȯ¸À¤·¤¿¤¤¾ì¹ç¤Ï¥Ú¡¼¥¸¤Î¤Æ¤Ã¤Ú¤ó¤Ë¤¢¤ë¥Æ¥¥¹¥È¥¨¥ê¥¢¤ËµÆþ¤·¡¢
-OK ¥Ü¥¿¥ó¤ò²¡¤·¤Þ¤¹¡£
-OK ¥Ü¥¿¥ó¤Î¤«¤ï¤ê¤ËüËö¤Î 1 ¤Ç¤â¤«¤Þ¤¤¤Þ¤»¤ó¡£
-</p>
-
-<p>
-²¿¤â½ñ¤«¤Ê¤¤¤Ç OK ¤Þ¤¿¤Ï 1 ¤ò²¡¤¹¤È²èÌ̹¹¿·¤Ë¤Ê¤ê¤Þ¤¹¡£
-</p>
-
-<p>
-üËö¤Î 7 ¤ò²¡¤¹¤È¥Ú¡¼¥¸ÀèƬ¤Ø¡¢
-üËö¤Î 8 ¤ò²¡¤¹¤È¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Ø¡¢
-üËö¤Î 9 ¤ò²¡¤¹¤È¥Ú¡¼¥¸ËöÈø¤ËÈô¤Ó¤Þ¤¹¡£
-</p>
-
-<p>
-¤µ¤é¤Ë¾Ü¤·¤¤µ¡Ç½¤Î»È¤¤Êý¤Ï
-<a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a>
-¤â¤´Í÷¤¯¤À¤µ¤¤¡£
-</p>
-
-<h2><a name="development">³«È¯</a></h2>
-
-<p>
-<a href="http://sourceforge.jp/projects/keitairc/">http://sourceforge.jp/projects/keitairc/</a>
-¤Ë cvs ¥ê¥Ý¥¸¥È¥ê, BTS ¤Ê¤É¤¬¤¢¤ê¤Þ¤¹¡£
-</p>
-
-<h2><a name="security">¥»¥¥å¥ê¥Æ¥£</a></h2>
-<ul>
-<li><tt>use_cookie = yes</tt> ¤ÇüËö¤ËÊݸ¤µ¤ì¤ë¥¯¥Ã¥¡¼¤ÎÆâÍƤÏ
-°Å¹æ²½¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢¥¯¥Ã¥¡¼ÆâÍƤ¬Ï³±Ì¤¹¤ë¤È¥æ¡¼¥¶Ì¾¥Ñ¥¹¥ï¡¼¥É¤âϳ±Ì¤·¤Þ¤¹¡£
-<li>¥æ¡¼¥¶Ì¾¤È¥Ñ¥¹¥ï¡¼¥É¤Ï keitairc ¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ëʿʸ¤Çµ½Ò¤µ¤ì¤Þ¤¹¡£
-<li>¤½¤â¤½¤â¤³¤³¤ÇÁ÷¼õ¿®¤µ¤ì¤ë¥æ¡¼¥¶Ì¾¤ä¥Ñ¥¹¥ï¡¼¥É¤Ï¡¢http basic ǧ¾Ú¤Ê¤Î¤Ç¡¢
-ÄÌ¿®Ï©¤òʿʸ¤Çή¤ì¤Þ¤¹¡£
-<li>auüËö¤Ê¤É¤Ïhttp referrer¤âÁ÷¿®¤·¤Þ¤¹¤Î¤Ç¡¢keitairc¤¬É½¼¨¤¹¤ë³°Éô¥ê¥ó¥¯¤ò
-¤¦¤«¤Ä¤Ë¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢¥¢¥¯¥»¥¹Âоݥµ¥¤¥È¤Ë¤Ï¤¢¤Ê¤¿¤Îkeitairc¤ÎURL¤¬¤ï¤«¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£
-</ul>
-
-</BODY>
-</HTML>
+ <head>
+ <title>keitairc</title>
+ <link type="text/css" rel="stylesheet" href="default.css">
+ <meta content="text/html; charset=euc-jp" http-equiv="Content-Type">
+ </head>
+ <body>
+
+ <img src="phones.jpg" width="183" height="319" align="left" alt=""
+ style="margin-right: 5em;">
+
+ <h1>keitairc</h1>
+
+ <p class="flushleft">
+ morimoto@mrmt.net<br>
+ $Id: index.html,v 1.38 2007-09-27 22:20:01 morimoto Exp $
+ </p>
+
+ <hr>
+
+ <p>
+ ¤ª¤â¤Ë·ÈÂÓüËö¤«¤é¤Î»È¤¦¤¿¤á¤Î¡¢web¥Ù¡¼¥¹¤Îirc¥¯¥é¥¤¥¢¥ó¥È¤Ç¤¹¡£<br>
+ i¥â¡¼¥É, EZweb, Softbank, AIR-EDGE Phone ¤Ê¤É¤Î¥Ö¥é¥¦¥¶¥Õ¥©¥ó¤«¤éircÁàºî¤¬¤Ç¤¤Þ¤¹¡£
+ ¤â¤Á¤í¤ó¡¢¥Ñ¥½¥³¥ó¤«¤é»È¤Ã¤Æ¤¤¤¿¤À¤¤¤Æ¤âÊ̤˹½¤¤¤Þ¤»¤ó¡£
+ plum ¤Ê¤É¤Î pirc (irc ¥×¥í¥¥·) ¤ËÀܳ¤·¤Æ»È¤ï¤ì¤ë¤³¤È¤òÁÛÄꤷ¤Æ¤¤¤Þ¤¹¡£
+ </p>
+
+ <ul>
+ <li>¥¢¥¯¥»¥¹¥¡¼¤Ç·Ú²÷¤ËÁàºî<br>
+ <li>ȯ¸ÀÃæ¤ÎÅÅÏÃÈֹ桢URL ¤Ë¤Ï¾¡¼ê¤Ë¥ê¥ó¥¯¡£<br>
+ ÅÅÏÃÈÖ¹æ¤Ï²¡¤»¤ÐÅÅÏäǤ¤Þ¤¹¡£<br>
+ URL¥ê¥ó¥¯¤Ï¡¢¥Ý¥±¥Ã¥È¤Ï¤Æ¤Ê¤ò²ð¤·¤¿±ÜÍ÷¥ê¥ó¥¯¡¢
+ PC¥µ¥¤¥È¥Ó¥å¡¼¥¢¡¼¤ò²ð¤·¤¿±ÜÍ÷¥ê¥ó¥¯(au¤ÎÂбþüËö¤Î¤ß)¤âÂбþ¡£
+ <li>plum ¤Î multicast.plm ¤ò»È¤Ã¤Æ¤¤¤Æ¤âÂç¾æÉס£
+ <li>irc¥µ¡¼¥ÐºÆÀܳÂбþ¡£
+ <li>¥Ñ¥¹¥ï¡¼¥Éǧ¾ÚÂбþ¡£EZwebüËö¤Ç¤ÏEZÈÖ¹æǧ¾ÚÂбþ¡£
+ AIR-EDGE Phone¤Ê¤É¤Ç¤ÏCookieǧ¾Ú¤Ë¤âÂбþ¡£
+ </ul>
+
+ <p>
+ <a href="#license">¥é¥¤¥»¥ó¥¹</a> |
+ <a href="#environment">Æ°ºî´Ä¶</a> |
+ <a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a> |
+ <a href="#usage">»È¤¤Êý</a> |
+ <a href="#development">³«È¯</a> |
+ <a href="#security">¥»¥¥å¥ê¥Æ¥£</a> |
+ <a href="faq.html">FAQ</a> |
+ <a href="changes.html">Êѹ¹ÍúÎò</a>
+ </p>
+
+ <p>
+ <a href="http://sourceforge.jp/">
+ <img src="http://sourceforge.jp/sflogo.php?group_id=1057"
+ width="96" height="31" border="0" align="right"
+ alt="SourceForge.jp"></a>
+ </p>
+
+ <br clear="all">
+
+ <h2><a name="license">¥é¥¤¥»¥ó¥¹</a></h2>
+
+ <p>
+ Copyright (c) 2003-2007 Jun Morimoto <morimoto@mrmt.net><br>
+ This program is covered by the GNU General Public License 2.
+ </p>
+
+ <h2><a name="version">ºÇ¿·¥Ð¡¼¥¸¥ç¥ó</a></h2>
+ <p>
+ keitairc 1.31
+ (2007/9/28 ¥ê¥ê¡¼¥¹)
+ ¤Ç¤¹¡£<br>
+ ¤Á¤Ê¤ß¤Ë¥Ð¡¼¥¸¥ç¥óÈÖ¹æ¤Ï¡¢Ã±¤Ë keitairc ¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Î CVS rcsid ¤ò¼è¤Ã¤Æ¤¤¤ë¤À¤±¤Ç¤¹¡£
+ </p>
+
+ <h2><a name="environment">Æ°ºî´Ä¶</a></h2>
+
+ <p>
+ ¤ª¤½¤é¤¯ Perl 5.8 °Ê¹ß¤È¡¢°Ê²¼¤Ë¼¨¤¹ Perl ¥é¥¤¥Ö¥é¥ê¤¬Æ°ºî¤¹¤ë¥Û¥¹¥È¡£<br>
+ ¤¹¤Ç¤Ë plum ¤Ê¤É¤Î pirc ¤ò»È¤Ã¤Æ¤¤¤ë¥æ¡¼¥¶¤ÎÍøÍѤò¿ä¾©¤·¤Þ¤¹¡£
+ </p>
+
+ <h2><a name="screenshot">¥¹¥¯¥ê¡¼¥ó¥·¥ç¥Ã¥È</a></h2>
+
+ <table>
+ <tr>
+ <td>¥Á¥ã¥Í¥ë°ìÍ÷</td>
+ <td>¥Á¥ã¥Í¥ëȯ¸ÀÆâÍÆ</td>
+ <td>recent (ºÇ¶á¤Îȯ¸À¤Î¤Þ¤È¤á)</td>
+ </tr>
+ <tr>
+ <td><img src="1.gif" alt="" width="220" height="240"></td>
+ <td><img src="2.gif" alt="" width="220" height="240"></td>
+ <td><img src="3.gif" alt="" width="220" height="240"></td>
+ </tr>
+ </table>
+
+ <h2><a name="usage">»È¤¤Êý</a></h2>
+
+ <p>
+ keitairc ¤òµ¯Æ°¤·¤Æ·ÈÂÓ¤«¤é¥¢¥¯¥»¥¹¤¹¤ë¤È¡¢
+ web_username ¤È web_password ¤Ç»ØÄꤷ¤¿¥æ¡¼¥¶Ì¾¤È¥Ñ¥¹¥ï¡¼¥É¤Çǧ¾Ú¤ò¹Ô¤Ê¤Ã¤¿¤Î¤Á¡¢
+ ¤¤¤Þ»²²Ã¤·¤Æ¤¤¤ëÁ´¤Æ¤Î¥Á¥ã¥Í¥ë°ìÍ÷¤¬½Ð¤Þ¤¹¡£
+ ȯ¸ÀÆâÍƤ¬¿·¤·¤¤¥Á¥ã¥Í¥ë¤«¤é½ç¤ËʤӤޤ¹¡£
+ ¥Á¥ã¥Í¥ë°ìÍ÷¤ÏÅÅÏõ¡¤Î 0 ¤ò²¡¤¹¤È¹¹¿·¤Ç¤¤Þ¤¹¡£<br>
+ AIR-EDGE Phone¤Ê¤ÉCookieÂбþµ¡¼ï¤Ç¤Ï¡¢
+ use_cookie = yes »ØÄê¤ò¤¹¤ì¤Ð¡¢Ç§¾ÚÆâÍƤò¥¯¥Ã¥¡¼¤ËµÏ¿¤¹¤ë¤³¤È¤Ç¡¢
+ °Ê¹ß¤Î¥æ¡¼¥¶Ì¾¡¦¥Ñ¥¹¥ï¡¼¥Éǧ¾Ú¤ò¾Êά¤Ç¤¤Þ¤¹¡£¥¯¥Ã¥¡¼¤ÎÀ¸Â¸»þ´Ö¤Ï3Æü´Ö¤Ç¤¹¡£
+ </p>
+
+ <p>
+ ¥Á¥ã¥Í¥ë¤òÁªÂò¤¹¤ë¤È¤½¤Î¥Á¥ã¥Í¥ë¤Îȯ¸ÀÆâÍƤòÆɤá¤Þ¤¹¡£
+ Á°²ó keitairc ¤Ç¸«¤¿¤È¤¤è¤ê¤â¿·¤·¤¤È¯¸À¤¬¤¿¤Þ¤Ã¤Æ¤¤¤ë¥Á¥ã¥Í¥ë¡¢
+ ¤Ä¤Þ¤ê̤ÆÉÆâÍƤΤ¢¤ë¥Á¥ã¥Í¥ë¤Ë¤Ï̾Á°¤Î¸å¤í¤Ë̤ÆɹԿô¥ê¥ó¥¯¤¬¤Ä¤¤Þ¤¹¡£
+ ̤ÆɹԿô¥ê¥ó¥¯¤òÁªÂò¤¹¤ë¤È¡¢Ì¤ÆÉÉôʬ¤À¤±¤òÆɤळ¤È¤¬¤Ç¤¤Þ¤¹¡£
+ ̤ÆÉÉôʬ¤À¤±¤òÆɤó¤Ç¤¤¤Æ¡¢´ûÆÉÉôʬ¤â¸«¤¿¤¤¾ì¹ç¤Ï¡¢<samp>...more[5]</samp>
+ ¤òÁªÂò¤¹¤ë¤È´ûÆÉÉôʬ¤â¸«¤ë¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
+ </p>
+
+ <p>
+ ¤Þ¤¿¡¢Ì¤ÆÉÆâÍƤΤ¢¤ë¥Á¥ã¥Í¥ë¤¬¤Ò¤È¤Ä¤Ç¤â¤¢¤ë¾ì¹ç¤Ï¡¢
+ ¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Ë recent ¥ê¥ó¥¯¤¬¤Ä¤¤Þ¤¹¡£
+ recent ¥ê¥ó¥¯¤Ï¡¢Ã¼Ëö¤Ë¤è¤Ã¤Æ¤Ï * ¥¡¼¤ò²¡¤¹¤À¤±¤Ç¤â¹Ô¤¯¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
+ recent ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢Á´¥Á¥ã¥Í¥ë¤Î̤Æɤò¤Þ¤È¤áÆɤߤǤ¤Þ¤¹¡£<br>
+ ¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Î topics ¤ò¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢Á´¥Á¥ã¥Í¥ë¤Î¥È¥Ô¥Ã¥¯¤ò°ìÍ÷¤Ç¤¤Þ¤¹¡£
+ topics ¥ê¥ó¥¯¤Ï¡¢Ã¼Ëö¤Ë¤è¤Ã¤Æ¤Ï * ¥¡¼¤ò²¡¤¹¤À¤±¤Ç¤â¹Ô¤¯¤³¤È¤¬¤Ç¤¤Þ¤¹¡£
+ </p>
+
+ <p>
+ ¥Á¥ã¥Í¥ë¤Îȯ¸ÀÆâÍƤòÆɤó¤Ç¤¤¤Æ¡¢
+ ȯ¸À¤·¤¿¤¤¾ì¹ç¤Ï¥Ú¡¼¥¸¤Î¤Æ¤Ã¤Ú¤ó¤Ë¤¢¤ë¥Æ¥¥¹¥È¥¨¥ê¥¢¤ËµÆþ¤·¡¢
+ OK ¥Ü¥¿¥ó¤ò²¡¤·¤Þ¤¹¡£
+ OK ¥Ü¥¿¥ó¤Î¤«¤ï¤ê¤ËüËö¤Î 1 ¤Ç¤â¤«¤Þ¤¤¤Þ¤»¤ó¡£
+ </p>
+
+ <p>
+ ²¿¤â½ñ¤«¤Ê¤¤¤Ç OK ¤Þ¤¿¤Ï 1 ¤ò²¡¤¹¤È²èÌ̹¹¿·¤Ç¤¹¡£
+ </p>
+
+ <p>
+ üËö¤Î 7 ¤ò²¡¤¹¤È¥Ú¡¼¥¸ÀèƬ¤Ø¡¢
+ üËö¤Î 8 ¤ò²¡¤¹¤È¥Á¥ã¥Í¥ë¤Î¥ê¥¹¥È¤Ø¡¢
+ üËö¤Î 9 ¤ò²¡¤¹¤È¥Ú¡¼¥¸ËöÈø¤ËÈô¤Ó¤Þ¤¹¡£
+ </p>
+
+ <p>
+ ¤µ¤é¤Ë¾Ü¤·¤¤µ¡Ç½¤Î»È¤¤Êý¤Ï
+ <a href="install.html">¥¤¥ó¥¹¥È¡¼¥ë</a>
+ ¤â¤´Í÷¤¯¤À¤µ¤¤¡£
+ </p>
+
+ <h2><a name="development">³«È¯</a></h2>
+
+ <p>
+ <a href="http://sourceforge.jp/projects/keitairc/">http://sourceforge.jp/projects/keitairc/</a>
+ ¤Ë cvs ¥ê¥Ý¥¸¥È¥ê, BTS ¤Ê¤É¤¬¤¢¤ê¤Þ¤¹¡£
+ </p>
+
+ <h2><a name="security">¥»¥¥å¥ê¥Æ¥£</a></h2>
+ <ul>
+ <li><tt>use_cookie = yes</tt> ¤ÇüËö¤ËÊݸ¤µ¤ì¤ë¥¯¥Ã¥¡¼¤ÎÆâÍƤÏ
+ °Å¹æ²½¤µ¤ì¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢¥¯¥Ã¥¡¼ÆâÍƤ¬Ï³±Ì¤¹¤ë¤È¥æ¡¼¥¶Ì¾¥Ñ¥¹¥ï¡¼¥É¤âϳ±Ì¤·¤Þ¤¹¡£
+ <li>¥æ¡¼¥¶Ì¾¤È¥Ñ¥¹¥ï¡¼¥É¤Ï keitairc ¤ÎÀßÄê¥Õ¥¡¥¤¥ë¤Ëʿʸ¤Çµ½Ò¤µ¤ì¤Þ¤¹¡£
+ <li>¤½¤â¤½¤â¤³¤³¤ÇÁ÷¼õ¿®¤µ¤ì¤ë¥æ¡¼¥¶Ì¾¤ä¥Ñ¥¹¥ï¡¼¥É¤Ï¡¢http basic ǧ¾Ú¤Ê¤Î¤Ç¡¢
+ ÄÌ¿®Ï©¤òʿʸ¤Çή¤ì¤Þ¤¹¡£
+ <li>auüËö, ºÇ¶á¤ÎSoftbanküËö¤Ê¤É¤Ïhttp referrer¤âÁ÷¿®¤·¤Þ¤¹¤Î¤Ç¡¢
+ keitairc¤¬É½¼¨¤¹¤ë³°Éô¥ê¥ó¥¯¤ò¤¦¤«¤Ä¤Ë¥¯¥ê¥Ã¥¯¤¹¤ë¤È¡¢
+ ¥¢¥¯¥»¥¹Âоݥµ¥¤¥È¤Ë¤Ï¤¢¤Ê¤¿¤Îkeitairc¤ÎURL¤¬¤ï¤«¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£
+ </ul>
+
+ </body>
+</html>
#!/usr/bin/perl
# keitairc
-# $Id: keitairc,v 1.30 2006-08-03 07:19:47 morimoto Exp $
+# $Id: keitairc,v 1.31 2007-09-27 22:20:01 morimoto Exp $
#
-# Copyright (c) Jun Morimoto <morimoto@mrmt.net>
+# Copyright (c) 2003-2007 Jun Morimoto <morimoto@mrmt.net>
# This program is covered by the GNU General Public License 2
#
-# Depends: libjcode-pm-perl, libpoe-component-irc-perl,
-# liburi-perl, libwww-perl, libappconfig-perl
+# Depends: libunicode-japanese-perl, libpoe-component-irc-perl,
+# liburi-perl, libwww-perl, libappconfig-perl, libproc-daemon-perl
-my $rcsid = q$Id: keitairc,v 1.30 2006-08-03 07:19:47 morimoto Exp $;
+my $rcsid = q$Id: keitairc,v 1.31 2007-09-27 22:20:01 morimoto Exp $;
my ($version) = $rcsid =~ m#,v ([0-9.]+)#;
use strict;
-use Jcode;
+use Unicode::Japanese;
use POE;
use POE::Component::Server::TCP;
use POE::Filter::HTTPD;
use POE::Component::IRC;
use URI::Escape;
use HTTP::Response;
+use Proc::Daemon;
use AppConfig qw(:argcount);
use constant true => 1;
use constant false => 0;
-use constant cookie_ttl => 86400*3; # 3 days
+use constant cookie_ttl => 86400 * 3; # 3 days
+
+our $config = AppConfig->new(
+ {
+ CASE => 1,
+ GLOBAL => {
+ ARGCOUNT => ARGCOUNT_ONE,
+ }
+ },
+ qw(irc_nick irc_username irc_desc
+ irc_server irc_port irc_password
+ au_subscriber_id au_pcsv use_cookie
+ web_port web_title web_lines web_root
+ web_username web_password show_newmsgonly
+ ping_delay reconnect_delay
+ daemonize pid_dir)
+);
+
+$config->ping_delay(30);
+$config->reconnect_delay(10);
+
+if(defined $ARGV[0] && -e $ARGV[0]){
+ try_config($ARGV[0]);
+ shift(@ARGV);
+}else{
+ try_config('/etc/keitairc');
+ try_config($ENV{HOME} . '/.keitairc');
+}
-my $config = AppConfig->new(
- {
- CASE => 1,
- GLOBAL => {
- ARGCOUNT => ARGCOUNT_ONE,
- }
- },
- qw(irc_nick irc_username irc_desc
- irc_server irc_port irc_password
- au_subscriber_id au_pcsv use_cookie
- web_port web_title web_lines web_root
- web_username web_password show_newmsgonly)
- );
-
-$config->file('/etc/keitairc');
-$config->file($ENV{'HOME'} . '/.keitairc');
$config->args;
-my $docroot = '/';
+if(defined $config->daemonize){
+ Proc::Daemon::Init;
+ if (defined $config->pid_dir) {
+ if (open(PID, '> ' . $config->pid_dir . '/keitairc.pid')) {
+ print PID $$, "\n";
+ close(PID);
+ }
+ }
+}
+
+our $docroot = '/';
if(defined $config->web_root){
- $docroot = $config->web_root;
+ $docroot = $config->web_root;
}
# join \e$B$7$F$$$k%A%c%M%k$NL>>N$r5-O?$9$k%O%C%7%e\e(B
-my %channel_name;
+# \e$BJ8;zNs$O\e(Bjis\e$B$GJ]B8$5$l$F$$$k$N$GCm0U\e(B
+our %channel_name;
# join \e$B$7$F$$$k%A%c%M%k$NL>>N$r5-O?$9$k%O%C%7%e\e(B
-my %topic;
+# \e$BJ8;zNs$O\e(Bjis\e$B$GJ]B8$5$l$F$$$k$N$GCm0U\e(B
+our %channel_topic;
# \e$B%A%c%M%k$N2qOCFbMF$r5-O?$9$k%O%C%7%e\e(B
-my (%channel_buffer, %channel_recent);
+# \e$BJ8;zNs$O\e(Beuc\e$B$GJ]B8$5$l$F$$$k$N$GCm0U\e(B
+our (%channel_buffer, %channel_recent);
# \e$B3F%A%c%M%k$N:G=*%"%/%;%9;~9o!":G?7H/8@;~9o\e(B
-my %mtime;
+our %channel_mtime;
# unread lines
-my %unread_lines;
+# \e$BJ8;zNs$O\e(Beuc\e$B$GJ]B8$5$l$F$$$k$N$GCm0U\e(B
+our %unread_lines;
# chk
-my ($message_added);
+our $message_added;
+our $connected = false,
# irc component
-POE::Component::IRC->new('keitairc');
-POE::Session->new(
- _start => \&on_irc_start,
- irc_join => \&on_irc_join,
- irc_part => \&on_irc_part,
- irc_public => \&on_irc_public,
- irc_notice => \&on_irc_notice,
- irc_topic => \&on_irc_topic,
- irc_332 => \&on_irc_topicraw,
- irc_ctcp_action => \&on_irc_ctcp_action,
- );
+our $irc = POE::Component::IRC->spawn(
+ Alias => 'keitairc_irc',
+ Nick => $config->irc_nick,
+ Username => $config->irc_username,
+ Ircname => $config->irc_desc,
+ Server => $config->irc_server,
+ Port => $config->irc_port,
+ Password => $config->irc_password);
+POE::Session->create(
+ heap => {
+ seen_traffic => false,
+ disconnect_msg => true,
+ },
+ inline_states => {
+ _start => \&on_irc_start,
+ irc_001 => \&on_irc_001,
+ irc_join => \&on_irc_join,
+ irc_part => \&on_irc_part,
+ irc_public => \&on_irc_public,
+ irc_notice => \&on_irc_notice,
+ irc_topic => \&on_irc_topic,
+ irc_332 => \&on_irc_topicraw,
+ irc_ctcp_action => \&on_irc_ctcp_action,
+ autoping => \&do_autoping,
+ connect => \&do_connect,
+ irc_disconnected => \&on_irc_reconnect,
+ irc_error => \&on_irc_reconnect,
+ irc_socketerr => \&on_irc_reconnect
+ });
# web server component
POE::Component::Server::TCP->new(
- Alias => 'keitairc',
- Port => $config->web_port,
- ClientFilter => 'POE::Filter::HTTPD',
- ClientInput => \&on_web_request
- );
+ Alias => 'keitairc',
+ Port => $config->web_port,
+ ClientFilter => 'POE::Filter::HTTPD',
+ ClientInput => \&on_web_request);
$poe_kernel->run();
exit 0;
################################################################
+sub try_config{
+ my $file = shift;
+ if(-e $file){
+ $config->file($file);
+ }
+}
+
+################################################################
sub on_irc_start{
- my $kernel = $_[KERNEL];
- $kernel->post('keitairc' => 'register' => 'all');
- $kernel->post('keitairc' => 'connect' => {
- Nick => $config->irc_nick,
- Username => $config->irc_username,
- Ircname => $config->irc_desc,
- Server => $config->irc_server,
- Port => $config->irc_port,
- Password => $config->irc_password
- });
+ $irc->yield(register => 'all');
+ $irc->yield(connect => {});
+}
+
+################################################################
+sub on_irc_001{
+ my ($kernel,$heap, $sender) = @_[KERNEL, HEAP, SENDER];
+ for my $channel (sort keys %channel_name){
+ &add_message($channel, undef, 'Connected to irc server!');
+ }
+ $heap->{disconnect_msg} = true;
+ %channel_name = ();
+ $kernel->delay(autoping => $config->ping_delay);
}
################################################################
sub on_irc_join{
- my ($kernel, $who, $channel) = @_[KERNEL, ARG0, ARG1];
- $who =~ s/!.*//;
+ my ($kernel, $heap, $who, $channel) = @_[KERNEL, HEAP, ARG0, ARG1];
+ $who =~ s/!.*//;
- # chop off after the gap (bug workaround of madoka)
- $channel =~ s/ .*//;
- my $canon_channel = &canon_name($channel);
+ # chop off after the gap (bug workaround of madoka)
+ $channel =~ s/ .*//;
+ my $canon_channel = canon_name($channel);
- $channel_name{$canon_channel} = $channel;
- unless ($who eq $config->irc_nick) {
- &add_message($channel, undef, "$who joined");
- }
+ $channel_name{$canon_channel} = $channel;
+ unless ($who eq $config->irc_nick) {
+ add_message($channel, undef, "$who joined");
+ }
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
+ $connected = true;
}
################################################################
sub on_irc_part{
- my ($kernel, $who, $channel) = @_[KERNEL, ARG0, ARG1];
- $who =~ s/!.*//;
-
- # chop off after the gap (bug workaround of POE::Filter::IRC)
- $channel =~ s/ .*//;
- my $canon_channel = &canon_name($channel);
-
- if ($who eq $config->irc_nick) {
- delete $channel_name{$canon_channel};
- } else {
- &add_message($channel, undef, "$who leaves");
- }
+ my ($kernel, $heap, $who, $channel) = @_[KERNEL, HEAP, ARG0, ARG1];
+ $who =~ s/!.*//;
+
+ # chop off after the gap (bug workaround of POE::Filter::IRC)
+ $channel =~ s/ .*//;
+ my $canon_channel = canon_name($channel);
+
+ if ($who eq $config->irc_nick) {
+ delete $channel_name{$canon_channel};
+ } else {
+ add_message($channel, undef, "$who leaves");
+ }
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
}
################################################################
sub on_irc_public{
- my ($kernel, $who, $channel, $msg) = @_[KERNEL, ARG0 .. ARG2];
- $who =~ s/!.*//;
- $channel = $channel->[0];
- $msg = Jcode->new($msg, 'jis')->euc;
- &add_message($channel, $who, $msg);
+ my ($kernel, $heap, $who, $channel, $msg) = @_[KERNEL, HEAP, ARG0 .. ARG2];
+ $who =~ s/!.*//;
+ $channel = $channel->[0];
+ $msg = Unicode::Japanese->new($msg, 'jis')->euc;
+ add_message($channel, $who, $msg);
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
}
################################################################
sub on_irc_notice{
- my ($kernel, $who, $channel, $msg) = @_[KERNEL, ARG0 .. ARG2];
- $who =~ s/!.*//;
- $channel = $channel->[0];
- $msg = Jcode->new($msg, 'jis')->euc;
- &add_message($channel, $who, $msg);
+ my ($kernel, $heap, $who, $channel, $msg) = @_[KERNEL, HEAP, ARG0 .. ARG2];
+ $who =~ s/!.*//;
+ $channel = $channel->[0];
+ $msg = Unicode::Japanese->new($msg, 'jis')->euc;
+ add_message($channel, $who, $msg);
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
}
################################################################
sub on_irc_topic{
- my ($kernel, $who, $channel, $topic) = @_[KERNEL, ARG0 .. ARG2];
- $who =~ s/!.*//;
- $topic = Jcode->new($topic, 'jis')->euc;
- &add_message($channel, undef, "$who set topic: $topic");
- $topic{&canon_name($channel)} = $topic;
+ my ($kernel, $heap, $who, $channel, $topic) = @_[KERNEL, HEAP, ARG0 .. ARG2];
+ $who =~ s/!.*//;
+ $topic = Unicode::Japanese->new($topic, 'jis')->euc;
+ add_message($channel, undef, "$who set topic: $topic");
+ $channel_topic{canon_name($channel)} = $topic;
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
}
################################################################
sub on_irc_topicraw{
- my ($kernel, $raw) = @_[KERNEL, ARG1];
- my ($channel, $topic) = split(/ :/, $raw, 2);
- $topic{&canon_name($channel)} = $topic;
+ my ($kernel, $heap, $raw) = @_[KERNEL, HEAP, ARG1];
+ my ($channel, $topic) = split(/ :/, $raw, 2);
+ $channel_topic{canon_name($channel)} = $topic;
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
}
################################################################
sub on_irc_ctcp_action{
- my ($kernel, $who, $channel, $msg) = @_[KERNEL, ARG0 .. ARG2];
- $who =~ s/!.*//;
- $channel = $channel->[0];
- $msg = sprintf('* %s %s', $who, Jcode->new($msg, 'jis')->euc);
- &add_message($channel, '', $msg);
+ my ($kernel, $heap, $who, $channel, $msg) = @_[KERNEL, HEAP, ARG0 .. ARG2];
+ $who =~ s/!.*//;
+ $channel = $channel->[0];
+ $msg = sprintf('* %s %s', $who, Unicode::Japanese->new($msg, 'jis')->euc);
+ add_message($channel, '', $msg);
+ $heap->{seen_traffic} = true;
+ $heap->{disconnect_msg} = true;
+}
+
+################################################################
+sub do_connect{
+ my ($kernel, $heap) = @_[KERNEL, HEAP];
+ $kernel->post(keitairc_irc => connect => {});
+}
+
+################################################################
+sub do_autoping{
+ my ($kernel, $heap) = @_[KERNEL, HEAP];
+ $kernel->post(keitairc_irc => time) unless $heap->{seen_traffic};
+ $heap->{seen_traffic} = false;
+ $kernel->delay(autoping => $config->ping_delay);
+}
+
+################################################################
+sub on_irc_reconnect{
+ my ($kernel, $heap) = @_[KERNEL, HEAP];
+ if ($heap->{disconnect_msg}) {
+ for my $channel (sort keys %channel_name){
+ add_message($channel, undef, 'Disconnected from irc server, trying to reconnect...');
+ }
+ }
+ $heap->{disconnect_msg} = false;
+ $connected = false;
+ $kernel->delay(connect => $config->reconnect_delay);
}
################################################################
# $msg \e$B$O\e(B EUC \e$B$K$J$C$F$$$k$O$:\e(B
# $channel \e$B$O\e(B jis \e$B$G$-$F$k$>\e(B
sub add_message{
- my($channel, $who, $msg) = @_;
-
- my $message;
- if(length $who){
- $message = sprintf('%s %s> %s', &now, $who, $msg);
- }else{
- $message = sprintf('%s %s', &now, $msg);
- }
-
- my $canon_channel = &canon_name($channel);
- my @tmp = split("\n", $channel_buffer{$canon_channel});
- push @tmp, $message;
-
- my @tmp2 = split("\n", $channel_recent{$canon_channel});
- push @tmp2, $message;
-
- if(@tmp > $config->web_lines){
- $channel_buffer{$canon_channel} =
- join("\n", splice(@tmp, -$config->web_lines));
- }else{
- $channel_buffer{$canon_channel} = join("\n", @tmp);
- }
-
- if(@tmp2 > $config->web_lines){
- $channel_recent{$canon_channel} =
- join("\n", @tmp2[1 .. $config->web_lines]);
- }else{
- $channel_recent{$canon_channel} = join("\n", @tmp2);
- }
-
- $mtime{$canon_channel} = time;
-
- # unread lines
- $unread_lines{$canon_channel} = scalar(@tmp2);
-
- if($unread_lines{$canon_channel} > $config->web_lines){
- $unread_lines{$canon_channel} = $config->web_lines;
- }
+ my($channel, $who, $msg) = @_;
+
+ my $message;
+ if(length $who){
+ $message = sprintf('%s %s> %s', now(), $who, $msg);
+ }else{
+ $message = sprintf('%s %s', now(), $msg);
+ }
+
+ my $canon_channel = canon_name($channel);
+ my @tmp = split("\n", $channel_buffer{$canon_channel});
+ push @tmp, $message;
+
+ my @tmp2 = split("\n", $channel_recent{$canon_channel});
+ push @tmp2, $message;
+
+ if(@tmp > $config->web_lines){
+ $channel_buffer{$canon_channel} =
+ join("\n", splice(@tmp, -$config->web_lines));
+ }else{
+ $channel_buffer{$canon_channel} = join("\n", @tmp);
+ }
+
+ if(@tmp2 > $config->web_lines){
+ $channel_recent{$canon_channel} =
+ join("\n", @tmp2[1 .. $config->web_lines]);
+ }else{
+ $channel_recent{$canon_channel} = join("\n", @tmp2);
+ }
+
+ $channel_mtime{$canon_channel} = time;
+
+ # unread lines
+ $unread_lines{$canon_channel} = scalar(@tmp2);
+
+ if($unread_lines{$canon_channel} > $config->web_lines){
+ $unread_lines{$canon_channel} = $config->web_lines;
+ }
}
################################################################
sub now{
- my ($sec,$min,$hour) = localtime(time);
- sprintf('%02d:%02d', $hour, $min);
+ my ($sec, $min, $hour) = localtime(time);
+ sprintf('%02d:%02d', $hour, $min);
}
################################################################
sub escape{
- local($_) = shift;
- s/&/&/g;
- s/>/>/g;
- s/</</g;
- $_;
+ local($_) = shift;
+ s/&/&/g;
+ s/>/>/g;
+ s/</</g;
+ $_;
}
################################################################
sub label{
- my $accesskey = shift;
+ my $accesskey = shift;
- if($accesskey < 10){
- sprintf('%d ', $accesskey);
- }else{
- ' ';
- }
+ if($accesskey < 10){
+ sprintf('%d ', $accesskey);
+ }else{
+ ' ';
+ }
}
################################################################
sub index_page{
- my $buf;
- my $accesskey = 1;
- my $channel;
-
- for my $canon_channel (sort {
- $mtime{$b} <=> $mtime{$a};
- }(keys(%channel_name))){
- $channel = $channel_name{$canon_channel};
+ my $buf;
+ my $accesskey = 1;
+ my $channel;
+
+ for my $canon_channel (sort {
+ $channel_mtime{$b} <=> $channel_mtime{$a};
+ }(keys(%channel_name))){
+ $channel = $channel_name{$canon_channel};
+
+ $buf .= label($accesskey);
+
+ if($accesskey < 10){
+ $buf .= sprintf('<a accesskey="%1d" href="%s%s">%s</a>',
+ $accesskey,
+ $docroot,
+ uri_escape($channel),
+ compact_channel_name($channel));
+ }else{
+ $buf .= sprintf('<a href="%s%s">%s</a>',
+ $docroot,
+ uri_escape($channel),
+ compact_channel_name($channel));
+ }
- $buf .= &label($accesskey);
+ $accesskey++;
- if($accesskey < 10){
- $buf .= sprintf('<a accesskey="%1d" href="%s%s">%s</a>',
- $accesskey,
- $docroot,
- uri_escape($channel),
- &compact_channel_name($channel));
- }else{
- $buf .= sprintf('<a href="%s%s">%s</a>',
- $docroot,
- uri_escape($channel),
- &compact_channel_name($channel));
+ # \e$BL$FI9T?t\e(B
+ if($unread_lines{$canon_channel}){
+ $buf .= sprintf(' <a href="%s%s,recent">%s</a>',
+ $docroot,
+ uri_escape($channel),
+ $unread_lines{$canon_channel});
+ }
+ $buf .= '<br>';
}
- $accesskey++;
+ $buf .= qq(0 <a href="$docroot" accesskey="0">refresh list</a><br>);
- # \e$BL$FI9T?t\e(B
- if($unread_lines{$canon_channel}){
- $buf .= sprintf(' <a href="%s%s,recent">%s</a>',
- $docroot,
- uri_escape($channel),
- $unread_lines{$canon_channel});
+ if(grep($unread_lines{$_}, keys %unread_lines)){
+ $buf .= qq(* <a href="$docroot,recent" accesskey="*">recent</a><br>);
}
- $buf .= '<br>';
- }
- $buf .= qq(0 <a href="$docroot" accesskey="0">refresh list</a><br>);
-
- if(grep($unread_lines{$_}, keys %unread_lines)){
- $buf .= qq(* <a href="$docroot,recent" accesskey="*">recent</a><br>);
- }
-
- if(keys %topic){
- $buf .= qq(# <a href="$docroot,topics" accesskey="#">topics</a><br>);
- }
+ if(keys %channel_topic){
+ $buf .= qq(# <a href="$docroot,topics" accesskey="#">topics</a><br>);
+ }
- $buf .= qq( - keitairc $version);
- $buf;
+ $buf .= qq( - keitairc $version);
+ $buf;
}
################################################################
# \e$B%A%c%M%kL>>N$rC;$+$/$9$k\e(B
sub compact_channel_name{
- local($_) = shift;
+ local($_) = shift;
- # #name:*.jp \e$B$r\e(B %name \e$B$K\e(B
- if(s/:\*\.jp$//){
- s/^#/%/;
- }
+ # #name:*.jp \e$B$r\e(B %name \e$B$K\e(B
+ if(s/:\*\.jp$//){
+ s/^#/%/;
+ }
- # \e$BKvHx$NC1FH$N\e(B @ \e$B$O<h$k\e(B (for multicast.plm)
- s/\@$//;
+ # \e$BKvHx$NC1FH$N\e(B @ \e$B$O<h$k\e(B (plum\e$B%W%i%0%$%s$N\e(Bmulticast.plm\e$BBP:v\e(B)
+ s/\@$//;
- $_;
+ Unicode::Japanese->new($_, 'jis')->euc;
}
################################################################
sub canon_name{
- local($_) = shift;
-
- tr/A-Z[\\]^/a-z{|}~/;
-
- $_;
+ local($_) = shift;
+ tr/A-Z[\\]^/a-z{|}~/;
+ $_;
}
################################################################
if(defined $config->au_pcsv && $ENV{HTTP_USER_AGENT} =~ /^KDDI-/){
push @buf, sprintf('<a href="device:pcsiteviewer?url=%s">[PCSV]</a>', $url);
}
- push @buf, sprintf('<a href="http://www.google.com/gwt/n?u=%s&hl=ja&mrestrict=xhtml|chtml&lr=&inlang=ja&client=ms-kddi-jp">[GWT]</a>', uri_escape($url));
+ push @buf, sprintf('<a href="http://mgw.hatena.ne.jp/?url=%s&noimage=0&split=1">[ph]</a>', uri_escape($url));
join(' ', @buf);
}
################################################################
sub render{
- local($_);
- my @buf;
+ local($_);
+ my @buf;
- my @src = (reverse(split("\n", shift)))[0 .. $config->web_lines];
+ my @src = (reverse(split("\n", shift)))[0 .. $config->web_lines];
- for (@src){
- next unless defined;
- next unless length;
+ for (@src){
+ next unless defined;
+ next unless length;
- $_ = &escape($_);
+ $_ = escape($_);
- unless(s|\b(https?://[!-;=-\177]+)\b|link_url($1)|eg){
- unless(s|\b(www\.[!-\177]+)\b|link_url($1)|eg){
- # phone to
- unless(s|\b(0\d{1,3})([-(]?)(\d{2,4})([-)]?)(\d{4})\b|<a href="tel:$1$3$5">$1$2$3$4$5</a>|g){
- s|\b(\w[\w.+=-]+\@[\w.-]+[\w]\.[\w]{2,4})\b|<a href="mailto:$1">$1</a>|g;
+ unless(s|\b(https?://[/!-;=-\177]+)|link_url($1)|eg){
+ unless(s|\b(www\.[/!-\177]+)|link_url($1)|eg){
+ # phone to
+ unless(s|\b(0\d{1,3})([-(]?)(\d{2,4})([-)]?)(\d{4})\b|<a href="tel:$1$3$5">$1$2$3$4$5</a>|g){
+ s|\b(\w[\w.+=-]+\@[\w.-]+[\w]\.[\w]{2,4})\b|<a href="mailto:$1">$1</a>|g;
+ }
+ }
}
- }
- }
- s/\s+$//;
- s/\s+/ /g;
- push @buf, $_;
- }
+ s/\s+$//;
+ s/\s+/ /g;
+ push @buf, $_;
+ }
- '<pre>' . join("\n", @buf) . '</pre>';
+ '<pre>' . join("\n", @buf) . '</pre>';
}
################################################################
sub on_web_request{
- my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0];
-
- # Filter::HTTPD sometimes generates HTTP::Response objects.
- # They indicate (and contain the response for) errors that occur
- # while parsing the client's HTTP request. It's easiest to send
- # the responses as they are and finish up.
- if($request->isa('HTTP::Response')){
- $heap->{client}->put($request);
- $kernel->yield('shutdown');
- return;
- }
-
- # cookie
- my $cookie_authorized;
- if($config->use_cookie){
- my %cookie;
- for(split(/; */, $request->header('Cookie'))){
- my ($name, $value) = split(/=/);
- $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/eg;
- $cookie{$name} = $value;
- }
-
- if($cookie{username} eq $config->web_username &&
- $cookie{passwd} eq $config->web_password){
- $cookie_authorized = true;
- }
- }
-
- # authorization
- unless($cookie_authorized){
- unless(defined($config->au_subscriber_id) &&
- $request->header('x-up-subno') eq $config->au_subscriber_id){
- if(defined($config->web_username)){
- unless($request->headers->authorization_basic eq
- $config->web_username . ':' . $config->web_password){
- my $response = HTTP::Response->new(401);
- $response->push_header(WWW_Authenticate =>
- qq(Basic Realm="keitairc"));
- $heap->{client}->put($response);
- $kernel->yield('shutdown');
- return;
- }
+ my ($kernel, $heap, $request) = @_[KERNEL, HEAP, ARG0];
+
+ # Filter::HTTPD sometimes generates HTTP::Response objects.
+ # They indicate (and contain the response for) errors that occur
+ # while parsing the client's HTTP request. It's easiest to send
+ # the responses as they are and finish up.
+ if($request->isa('HTTP::Response')){
+ $heap->{client}->put($request);
+ $kernel->yield('shutdown');
+ return;
+ }
+
+ # cookie
+ my $cookie_authorized;
+ if($config->use_cookie){
+ my %cookie;
+ for(split(/; */, $request->header('Cookie'))){
+ my ($name, $value) = split(/=/);
+ $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/eg;
+ $cookie{$name} = $value;
+ }
+
+ if($cookie{username} eq $config->web_username &&
+ $cookie{passwd} eq $config->web_password){
+ $cookie_authorized = true;
+ }
}
- }
- }
-
- my $uri = $request->uri;
- my $content = '<html><head>';
- $content .= '<meta http-equiv="Cache-Control" content="max-age=0" />';
-
- # POST \e$B$5$l$F$-$?$b$N$OH/8@\e(B
- if($request->method =~ /POST/i){
- my $message = $request->content;
- $message =~ s/^m=//;
- $message =~ s/\+/ /g;
- $message = uri_unescape($message);
-
- if(length($message)){
- $uri =~ s|^/||;
- my $channel = uri_unescape($uri);
- $poe_kernel->post('keitairc',
- 'privmsg',
- Jcode->new($channel)->jis,
- Jcode->new($message)->jis);
- &add_message($channel, $config->irc_nick,
- Jcode->new($message)->euc);
- $message_added = true;
+
+ # authorization
+ unless($cookie_authorized){
+ unless(defined($config->au_subscriber_id) &&
+ $request->header('x-up-subno') eq $config->au_subscriber_id){
+ if(defined($config->web_username)){
+ unless($request->headers->authorization_basic eq
+ $config->web_username . ':' . $config->web_password){
+ my $response = HTTP::Response->new(401);
+ $response->push_header(WWW_Authenticate =>
+ qq(Basic Realm="keitairc"));
+ $heap->{client}->put($response);
+ $kernel->yield('shutdown');
+ return;
+ }
+ }
+ }
}
- }
-
- # store and remove attached options from uri
- my %option;
- {
- my @opts = split(',', $uri);
- shift @opts;
- grep($option{$_} = $_, @opts);
- $uri =~ s/,.*//;
- }
-
- if($uri eq '/'){
- $content .= '<title>' . $config->web_title . '</title>';
- $content .= '</head>';
- $content .= '<body>';
-
- if($option{recent}){
- # recent messages on every channel
- for my $canon_channel (sort keys %channel_name){
- my $channel = $channel_name{$canon_channel};
- if(length($channel) &&
- length($channel_recent{$canon_channel})){
- $content .= '<b>' . Jcode->new($channel_name{$canon_channel})->euc . '</b>';
- $content .= sprintf(' <a href="%s%s">more..</a><br>',
- $docroot, uri_escape($channel));
- $content .= &render($channel_recent{$canon_channel});
- $unread_lines{$canon_channel} = 0;
- $channel_recent{$canon_channel} = '';
- $content .= '<hr>';
- }
+
+ my $uri = $request->uri;
+ my $content = '<html><head>';
+ $content .= '<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />';
+ $content .= '<meta http-equiv="Cache-Control" content="max-age=0" />';
+
+ # POST \e$B$5$l$F$-$?$b$N$OH/8@\e(B
+ if($request->method =~ /POST/i){
+ my $message = $request->content;
+ $message =~ s/^m=//;
+ $message =~ s/\+/ /g;
+ $message = uri_unescape($message);
+
+ if(length($message)){
+ $uri =~ s|^/||;
+ my $channel = uri_unescape($uri);
+ $irc->yield(privmsg => $channel => Unicode::Japanese->new($message, 'sjis')->jis);
+ add_message($channel, $config->irc_nick,
+ Unicode::Japanese->new($message, 'jis')->euc);
+ $message_added = true;
+ }
}
- $content .= qq(<a accesskey="8" href="$docroot">ch list[8]</a>);
- }elsif($option{topics}){
- # topic on every channel
- for my $canon_channel (sort keys %channel_name){
- my $channel = $channel_name{$canon_channel};
- if(length $channel){
- $content .= sprintf(' <a href="%s%s">%s</a><br>',
- $docroot, uri_escape($channel),
- Jcode->new($channel_name{$canon_channel})->euc);
- $content .= &escape(Jcode->new($topic{$canon_channel})->euc);
- $content .= '<br>';
- }
+
+ # store and remove attached options from uri
+ my %option;
+ {
+ my @opts = split(',', $uri);
+ shift @opts;
+ grep($option{$_} = $_, @opts);
+ $uri =~ s/,.*//;
}
- $content .= qq(<br><a accesskey="8" href="$docroot">ch list[8]</a>);
- }else{
- # channel list
- $content .= &index_page;
- }
- }else{
- # channel conversation
- $uri =~ s|^/||;
-
- # RFC 2811:
- # Apart from the the requirement that the first character
- # being either '&', '#', '+' or '!' (hereafter called "channel
- # prefix"). The only restriction on a channel name is that it
- # SHALL NOT contain any spaces (' '), a control G (^G or ASCII
- # 7), a comma (',' which is used as a list item separator by
- # the protocol). Also, a colon (':') is used as a delimiter
- # for the channel mask. The exact syntax of a channel name is
- # defined in "IRC Server Protocol" [IRC-SERVER].
- #
- # so we use white space as separator character of channel name
- # and command argument.
-
- my $channel = uri_unescape($uri);
-
- $content .= '<title>' . $config->web_title . ": $channel</title>";
- $content .= '</head>';
- $content .= '<body>';
-
- $content .= '<a name="1"></a>';
- $content .= '<a accesskey="7" href="#1"></a>';
-
- $content .= sprintf('<form action="%s%s" method="post">',
- $docroot, uri_escape($channel));
- $content .= '<input type="text" name="m" size="10">';
- $content .= '<input type="submit" accesskey="1" value="OK[1]">';
- $content .= qq(<a accesskey="8" href="$docroot">ch list[8]</a><br>);
- $content .= '</form>';
-
- my $canon_channel = &canon_name($channel);
- if(defined($channel_name{$canon_channel})){
- if(defined($channel_buffer{$canon_channel}) &&
- length($channel_buffer{$canon_channel})){
- $content .= '<a accesskey="9" href="#2"></a>';
- if($option{recent} ||
- (defined($config->show_newmsgonly) && $message_added)){
- $content .= &render($channel_recent{$canon_channel});
- $content .= sprintf('<a accesskey="5" href="%s%s">more[5]</a>',
- $docroot, uri_escape($channel));
- } else {
- $content .= &render($channel_buffer{$canon_channel});
+
+ if($uri eq '/'){
+ $content .= '<title>' . $config->web_title . '</title>';
+ $content .= '</head>';
+ $content .= '<body>';
+
+ if($option{recent}){
+ # recent messages on every channel
+ for my $canon_channel (sort keys %channel_name){
+ my $channel = $channel_name{$canon_channel};
+ if(length($channel) &&
+ length($channel_recent{$canon_channel})){
+ $content .= '<b>' . Unicode::Japanese->new($channel_name{$canon_channel}, 'jis')->euc . '</b>';
+ $content .= sprintf(' <a href="%s%s">more..</a><br>',
+ $docroot, uri_escape($channel));
+ $content .= render($channel_recent{$canon_channel});
+ $unread_lines{$canon_channel} = 0;
+ $channel_recent{$canon_channel} = '';
+ $content .= '<hr>';
+ }
+ }
+ $content .= qq(<a accesskey="8" href="$docroot">ch list[8]</a>);
+ }elsif($option{topics}){
+ # topic on every channel
+ for my $canon_channel (sort keys %channel_name){
+ my $channel = $channel_name{$canon_channel};
+ if(length $channel){
+ $content .= sprintf(' <a href="%s%s">%s</a><br>',
+ $docroot, uri_escape($channel),
+ Unicode::Japanese->new($channel_name{$canon_channel}, 'jis')->euc);
+ $content .= escape(Unicode::Japanese->new($channel_topic{$canon_channel}, 'jis')->euc);
+ $content .= '<br>';
+ }
+ }
+ $content .= qq(<br><a accesskey="8" href="$docroot">ch list[8]</a>);
+ }else{
+ # channel list
+ $content .= index_page();
}
- $content .= '<a accesskey="9" href="#2"></a>';
- $content .= '<a name="2"></a>';
- }else{
- $content .= 'no message here yet';
- }
}else{
- $content .= 'no such channel';
+ # channel conversation
+ $uri =~ s|^/||;
+
+ # RFC 2811:
+ # Apart from the the requirement that the first character
+ # being either '&', '#', '+' or '!' (hereafter called "channel
+ # prefix"). The only restriction on a channel name is that it
+ # SHALL NOT contain any spaces (' '), a control G (^G or ASCII
+ # 7), a comma (',' which is used as a list item separator by
+ # the protocol). Also, a colon (':') is used as a delimiter
+ # for the channel mask. The exact syntax of a channel name is
+ # defined in "IRC Server Protocol" [IRC-SERVER].
+ #
+ # so we use white space as separator character of channel name
+ # and command argument.
+
+ my $channel = uri_unescape($uri);
+
+ $content .= sprintf('<title>%s: %s</title>', $config->web_title, compact_channel_name($channel));
+ $content .= '</head>';
+ $content .= '<body>';
+
+ $content .= '<a name="1"></a>';
+ $content .= '<a accesskey="7" href="#1"></a>';
+
+ $content .= sprintf('<form action="%s%s" method="post">',
+ $docroot, uri_escape($channel));
+ $content .= '<input type="text" name="m" size="10">';
+ $content .= '<input type="submit" accesskey="1" value="OK[1]">';
+ $content .= qq(<a accesskey="8" href="$docroot">ch list[8]</a><br>);
+ $content .= '</form>';
+
+ my $canon_channel = canon_name($channel);
+ if(defined($channel_name{$canon_channel})){
+ if(defined($channel_buffer{$canon_channel}) &&
+ length($channel_buffer{$canon_channel})){
+ $content .= '<a accesskey="9" href="#2"></a>';
+ if($option{recent} ||
+ (defined($config->show_newmsgonly) && $message_added)){
+ $content .= render($channel_recent{$canon_channel});
+ $content .= sprintf('<a accesskey="5" href="%s%s">more[5]</a>',
+ $docroot, uri_escape($channel));
+ } else {
+ $content .= render($channel_buffer{$canon_channel});
+ }
+ $content .= '<a accesskey="9" href="#2"></a>';
+ $content .= '<a name="2"></a>';
+ }else{
+ $content .= 'no message here yet';
+ }
+ }else{
+ $content .= 'no such channel';
+ }
+
+ # clear check flags
+ $message_added = false;
+
+ # clear unread counter
+ $unread_lines{$canon_channel} = 0;
+
+ # clear recent messages buffer
+ $channel_recent{$canon_channel} = '';
}
- # clear check flags
- $message_added = false;
-
- # clear unread counter
- $unread_lines{$canon_channel} = 0;
-
- # clear recent messages buffer
- $channel_recent{$canon_channel} = '';
- }
-
- $content .= '</body></html>';
-
- my $response = HTTP::Response->new(200);
-
- if($config->use_cookie){
- my ($sec, $min, $hour, $mday, $mon, $year, $wday) =
- localtime(time + cookie_ttl);
- my $expiration =
- sprintf('%.3s, %.2d-%.3s-%.4s %.2d:%.2d:%.2d',
- qw(Sun Mon Tue Wed Thu Fri Sat)[$wday],
- $mday,
- qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$mon],
- $year + 1900,
- $hour,
- $min,
- $sec);
- $response->push_header('Set-Cookie',
- sprintf("username=%s; expires=%s; \n",
- $config->web_username, $expiration));
- $response->push_header('Set-Cookie',
- sprintf("passwd=%s; expires=%s; \n",
- $config->web_password, $expiration));
- }
-
- $response->push_header('Content-type', 'text/html; charset=Shift_JIS');
- $response->content(Jcode->new($content)->sjis);
- $heap->{client}->put($response);
- $kernel->yield('shutdown');
+ $content .= '</body></html>';
+
+ my $response = HTTP::Response->new(200);
+
+ if($config->use_cookie){
+ my ($sec, $min, $hour, $mday, $mon, $year, $wday) =
+ localtime(time + cookie_ttl);
+ my $expiration =
+ sprintf('%.3s, %.2d-%.3s-%.4s %.2d:%.2d:%.2d',
+ qw(Sun Mon Tue Wed Thu Fri Sat)[$wday],
+ $mday,
+ qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)[$mon],
+ $year + 1900,
+ $hour,
+ $min,
+ $sec);
+ $response->push_header('Set-Cookie',
+ sprintf("username=%s; expires=%s; \n",
+ $config->web_username, $expiration));
+ $response->push_header('Set-Cookie',
+ sprintf("passwd=%s; expires=%s; \n",
+ $config->web_password, $expiration));
+ }
+
+ $response->push_header('Content-type', 'text/html; charset=Shift_JIS');
+ $response->content(Unicode::Japanese->new($content, 'euc')->sjis);
+ $heap->{client}->put($response);
+ $kernel->yield('shutdown');
}
__END__