--- /dev/null
+# -*-perl-*-
+# Keitairc::ClientInfo
+# $Id: ClientInfo.pm,v 1.1 2008-01-10 03:23:31 morimoto Exp $
+# $Source: /home/ishikawa/work/keitairc/tmp/keitairc/lib/Keitairc/ClientInfo.pm,v $
+#
+# Copyright (c) 2008 Jun Morimoto <morimoto@mrmt.net>
+# This program is covered by the GNU General Public License 2
+
+package Keitairc::ClientInfo;
+use strict;
+
+################################################################
+sub new{
+ my $proto = shift;
+ my $arg = shift;
+ my $me = {};
+
+ for my $key (keys %{$arg->{_headers}}){
+ my $ukey = $key;
+ $ukey =~ s/-/_/g;
+ $me->{header}->{$ukey} = $arg->{_headers}->{$key};
+ }
+
+ for my $set (split(/; */, $me->{header}->{Cookie})){
+ my ($name, $value) = split(/=/, $set);
+ $value =~ s/%([0-9A-Fa-f][0-9A-Fa-f])/pack('C', hex($1))/eg;
+ $me->{cookie}->{$name} = $value;
+ }
+
+ bless $me;
+ $me->{serial_key} = $me->serial_key();
+ $me;
+}
+
+################################################################
+sub user_agent{
+ my $me = shift;
+ $me->{header}->{user_agent};
+}
+
+################################################################
+sub is_ezweb{
+ my $me = shift;
+ $me->{header}->{user_agent} =~ /^KDDI-/;
+}
+
+################################################################
+sub is_docomo{
+ my $me = shift;
+ $me->{header}->{user_agent} =~ /^DoCoMo/;
+}
+
+################################################################
+sub is_ipod{
+ my $me = shift;
+ $me->{header}->{user_agent} =~ /(iPod|iPhone)/;
+}
+
+################################################################
+sub is_softbank{
+ my $me = shift;
+ $me->{header}->{user_agent} =~ /^(SoftBank|Vodafone|J-PHONE|MOT-)/;
+}
+
+################################################################
+sub softbank_serial{
+ my $me = shift;
+ if($me->is_softbank()){
+ if($me->{header}->{user_agent} =~ m|/(SN[0-9A-Z]+)|){
+ return $1;
+ }
+ }
+}
+
+################################################################
+sub docomo_foma_icc{
+ my $me = shift;
+ if($me->is_docomo()){
+ # NTT DoCoMo¤ÎFOMAüËöÀ½Â¤ÈÖ¹æ (15·å¤Î¥æ¥Ë¡¼¥¯¤Ê±Ñ¿ô»ú) ¤ª¤è¤Ó
+ # FOMA¥«¡¼¥ÉÀ½Â¤ÈÖ¹æ (20·å¤Î¥æ¥Ë¡¼¥¯¤Ê±Ñ¿ô»ú)
+ # http://www.nttdocomo.co.jp/service/imode/make/content/html/tag/utn.html
+ # DoCoMo/2.0 P703imyu(c100;TB;W30H15)
+ # DoCoMo/2.0 P703imyu(c100;TB;W30H15;ser12345ABCDE12345;icc12345ABCDE12345ABCDE)
+ if($me->{header}->{user_agent} =~ /;(icc[0-9A-Z]{20})/){
+ return $1;
+ }
+ }
+}
+
+################################################################
+sub subscribe_id{
+ my $me = shift;
+ $me->{header}->{x_up_subno};
+}
+
+################################################################
+sub serial_key{
+ my $me = shift;
+ if($me->is_softbank()){
+ return $me->softbank_serial();
+ }
+ if($me->is_ezweb()){
+ return $me->subscribe_id();
+ }
+}
+
+################################################################
+# Cookie¤ò°·¤¨¤ë¤«¤É¤¦¤«
+# ¤È¤ê¤¢¤¨¤º Cookie ¤ò³Î¼Â¤Ë°·¤¨¤Ê¤¤ DoCoMo ¤òȽÄꤷ¤Æ¤ë¤À¤±
+sub cookie_available{
+ my $me = shift;
+ unless($me->is_docomo()){
+ return 1;
+ }
+}
+
+1;
--- /dev/null
+# -*-perl-*-
+# Keitairc::SessionManager
+# $Id: SessionManager.pm,v 1.1 2008-01-10 03:23:31 morimoto Exp $
+# $Source: /home/ishikawa/work/keitairc/tmp/keitairc/lib/Keitairc/SessionManager.pm,v $
+#
+# Copyright (c) 2008 Jun Morimoto <morimoto@mrmt.net>
+# This program is covered by the GNU General Public License 2
+
+package Keitairc::SessionManager;
+use strict;
+
+################################################################
+# my $sm = new Keitairc::SessionManager;
+# ¥ª¥×¥·¥ç¥ó¤Ç ttl ¤ò»ØÄê²Äǽ
+# my $sm = new Keitairc::SessionManager({default_ttl => 120});
+sub new{
+ my $proto = shift;
+ my $arg = shift;
+ my $me = {};
+ $me->{sessions} = {};
+ $me->{default_ttl} = $arg->{default_ttl} || 60 * 30;
+ bless $me;
+}
+
+################################################################
+# $sm->verify({session_id => $session_id, user_agent => $user_agent});
+# $sm->verify({serial_key => $serial_key, user_agent => $user_agent});
+sub verify{
+ my $me = shift;
+ my $arg = shift;
+ my $user_agent = $me->normalize_user_agent($arg->{user_agent});
+ my $s;
+
+ ::log_debug("sm->verify: sid [$arg->{session_id}] serial_key [$arg->{serial_key}] user_agent [$arg->{user_agent}]");
+
+ if(defined $arg->{serial_key}){
+ if($s = $me->search_by_serial_key($arg->{serial_key}, $user_agent)){
+ # ¥¢¥¯¥»¥¹¤Ë¹çÃפ¹¤ë͸ú¤Ê¥»¥Ã¥·¥ç¥ó¤¬¸«¤Ä¤«¤Ã¤¿¤é
+ # ¥¿¥¤¥à¥¹¥¿¥ó¥×¤ò¹¹¿·¤·¤ÆÀ®¸ù¤òÊÖ¤¹
+ return $me->refresh($s->{id}, $user_agent);
+ }
+ }
+
+ if(defined $arg->{session_id}){
+ if($s = $me->search_by_session_id($arg->{session_id}, $user_agent)){
+ # ¥¢¥¯¥»¥¹¤Ë¹çÃפ¹¤ë͸ú¤Ê¥»¥Ã¥·¥ç¥ó¤¬¸«¤Ä¤«¤Ã¤¿¤é
+ # ¥¿¥¤¥à¥¹¥¿¥ó¥×¤ò¹¹¿·¤·¤ÆÀ®¸ù¤òÊÖ¤¹
+ return $me->refresh($s->{id}, $user_agent);
+ }
+ }
+}
+
+################################################################
+# »ØÄê¤Î¥»¥Ã¥·¥ç¥óIDʸ»úÎó¤Î¥»¥Ã¥·¥ç¥ó¤¬¤¢¤ë¤«Ä´¤Ù¡¢
+# ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹
+# $sm->search_by_session_id($session_id, $user_agent);
+sub search_by_session_id{
+ my $me = shift;
+ my $session_id = shift;
+ my $user_agent = shift;
+
+ $user_agent = $me->normalize_user_agent($user_agent);
+ if(my $s = $me->{sessions}->{$session_id}){
+ if($s->{user_agent} eq $user_agent){
+ if($s->{last_access_time} + $s->{ttl} >= time){
+ return $s;
+ }
+ }
+ }
+}
+
+################################################################
+# »ØÄê¤Î¥»¥Ã¥·¥ç¥óIDʸ»úÎó¤Î¥»¥Ã¥·¥ç¥ó¤¬¤¢¤ë¤«Ä´¤Ù¡¢
+# ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹
+# $sm->search_by_serial_key($serial_key, $user_agent);
+sub search_by_serial_key{
+ my $me = shift;
+ my $serial_key = shift;
+ my $user_agent = shift;
+
+ $user_agent = $me->normalize_user_agent($user_agent);
+
+ for my $id (keys(%{$me->{sessions}})){
+ if($me->{sessions}->{$id}->{serial_key} eq $serial_key){
+ if($me->{sessions}->{$id}->{user_agent} eq $user_agent){
+ return $me->{sessions}->{$id};
+ }
+ }
+ }
+}
+
+################################################################
+# »ØÄê¤Î¥»¥Ã¥·¥ç¥óIDʸ»úÎó¤Î¥»¥Ã¥·¥ç¥ó¤ÎºÇ½ª»þ¹ï¤ò¹¹¿·¤·¡¢
+# ¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹
+# $sm->refresh($session_id, $user_agent);
+sub refresh{
+ my $me = shift;
+ my $session_id = shift;
+ my $user_agent = shift;
+
+ $user_agent = $me->normalize_user_agent($user_agent);
+
+ # good time to gc, huh?
+ $me->garbage_collect();
+
+ if(my $s = $me->{sessions}->{$session_id}){
+ if($s->{user_agent} eq $user_agent){
+ $s->{last_access_time} = time;
+ return $s;
+ }
+ }
+}
+
+################################################################
+# ¿·¤¿¤Ê¥»¥Ã¥·¥ç¥ó¤ò»Ï¤á¡¢¥»¥Ã¥·¥ç¥ó¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹
+# ǧ¾Ú¤¬À®¸ù¤·¤¿Ä¾¸å¤Ê¤É¡¢Í°Õ¤Ê¤È¤°Ê³°¤Ë¤ä¤Ã¤Æ¤Ï¤¤¤±¤Ê¤¤
+# $sm->add($user_agent, [$serial_key]);
+sub add{
+ my $me = shift;
+ my $user_agent = shift;
+ my $serial_key = shift;
+
+ return unless length $user_agent;
+
+ $user_agent = $me->normalize_user_agent($user_agent);
+
+ my @id_chars = ('a'..'z', 'A'..'Z');
+ my $session_id;
+ srand(time % $$);
+ do{
+ $session_id = 'S';
+ for(1..10){
+ $session_id .= $id_chars[rand(@id_chars)];
+ }
+ }while(defined $me->{sessions}->{$session_id});
+
+ my $s = $me->{sessions}->{$session_id} = {};
+ $s->{id} = $session_id;
+ $s->{ttl} = $me->{default_ttl};
+ $s->{user_agent} = $user_agent;
+ if(defined $serial_key){
+ $s->{serial_key} = $serial_key;
+ }
+ $s->{last_access_time} = time;
+ ::log_debug("new session: " .
+ "id[$s->{id}]" .
+ "ua[$s->{user_agent}] " .
+ "time[$s->{last_access_time}] " .
+ "serial_key[$s->{serial_key}] " .
+ "ttl[$s->{ttl}]");
+ $s;
+}
+
+################################################################
+# TTL¤¬²á¤®¤¿¥»¥Ã¥·¥ç¥ó¤òËõ¾Ã
+# $sm->garbage_collect();
+sub garbage_collect{
+ my $me = shift;
+ for my $id (keys(%{$me->{sessions}})){
+ if(($me->{sessions}->{$id}->{last_access_time} +
+ $me->{sessions}->{$id}->{ttl}) < time){
+ delete $me->{sessions}->{$id};
+ ::log_debug("deleted session: id[$id]");
+ }
+ }
+}
+
+################################################################
+# USER_AGENTʸ»úÎ󤫤顢¥»¥Ã¥·¥ç¥óȽÄê¤Î˸¤²¤È¤Ê¤ëÍ×ÁǤò¼è¤ë
+sub normalize_user_agent{
+ my $me = shift;
+ my $user_agent = shift;
+
+ # ::log_debug("normalize_user_agent: user_agent[$user_agent]");
+
+ # NTT DoCoMo¤ÎFOMAüËöÀ½Â¤ÈÖ¹æ (15·å¤Î¥æ¥Ë¡¼¥¯¤Ê±Ñ¿ô»ú) ¤ª¤è¤Ó
+ # FOMA¥«¡¼¥ÉÀ½Â¤ÈÖ¹æ (20·å¤Î¥æ¥Ë¡¼¥¯¤Ê±Ñ¿ô»ú) ¤ò½üµî
+ # http://www.nttdocomo.co.jp/service/imode/make/content/html/tag/utn.html
+ # DoCoMo/2.0 P703imyu(c100;TB;W30H15)
+ # DoCoMo/2.0 P703imyu(c100;TB;W30H15;ser123451234512345;icc12345678901234567890)
+ if($user_agent =~ m|^DoCoMo/|){
+ $user_agent =~ s/;ser[0-9A-Z]{15}//;
+ $user_agent =~ s/;icc[0-9A-Z]{20}//;
+ }
+
+ # SoftBank/Vodafone/J-PHONE
+ # http://developers.softbankmobile.co.jp/dp/tool_dl/web/useragent.php
+ if($user_agent =~ m!^(SoftBank|Vodafone|J-PHONE|MOT-)/!){
+ $user_agent =~ s|/SN[0-9A-Z]+|/|;
+ }
+
+ # ::log_debug("normalize_user_agent: user_agent[$user_agent]");
+ $user_agent;
+}
+
+1;