携帯電話のUserAgent判定クラス
- Keitai.class.php
携帯のUserAgentを判定するファクトリメソッドなクラス これは、PEAR::Net_UserAgent_Mobileを学習目的にコピーしたものです。
キャリアごとにパースの仕方が異なるので、それぞれ別のクラスに分けているが使用するメソッドは同じため、基本クラスを継承している。しかし、インスタンス化に別々の new をかますのは面倒だからまとめて面倒をみてくれるファクトリ メソッド パターンを使っているよ。
<?php $ua =& Keitai::singleton(); if ( !$ua->isValidIp() ) { // Keitai_IP_List.class.phpが必要です die('携帯シミュレータなどのアクセスは禁止です。'); } $id = $ua->getKeitaiId(); ?>
- メソッドリスト
object factory ([string $userAgent = null])
object singleton ([string $userAgent = null])
bool isError ()
string errorMessage ()
bool isDoCoMo ()
bool isKDDI ()
bool isSoftBank ()
bool isWillcom ()
bool isMobile ()
bool isNonMobile ()
bool isSmartPhone()
string getCarrier() : キャリア名 DoCoMo, KDDI, SoftBank, Willcom
string getComment()
string getKeitaiId() : UIDを取得する UIDがない場合は端末製造番号など固有の番号を取得する
string getModel() : 端末モデル名を取得する
string getRawModel() : 端末モデル名の文字列をそのまま取得する
string getUA() : UserAgentをそのまま取得する
string getVendor() : 端末メーカー名またはブラウザ名を取得する
string getVersion() : ブラウザのバージョンを取得する
bool isValidIp() : アクセス元がキャリアゲートウェイであるか判定する
- Keitai.class.php ソース
<?php /* -*-java-*- */ require_once('PEAR.php'); /* * Constants for error handling. */ define('KEITAI_OK', 1); define('KEITAI_ERROR', -1); define('KEITAI_ERROR_NOMATCH', -2); define('KEITAI_ERROR_NOT_FOUND', -3); /* * Globals for fallback on no match. * * @global boolean $GLOBALS['_KEITAI_FALLBACK_ON_NOMATCH'] */ $GLOBALS['_KEITAI_FALLBACK_ON_NOMATCH'] = false; /** * 携帯のUserAgentを判定するファクトリメソッドなクラス * これは、PEAR::Net_UserAgent_Mobile を学習目的にコピーしたものです。 * * キャリアごとにパースの仕方が異なるので、それぞれ別のクラスに分けているが * 使用するメソッドは同じため、基本クラスを継承している。 * しかし、インスタンス化に別々の new をかますのは面倒だからまとめて面倒を * みてくれるファクトリ・メソッド・パターンを使っているよ。 * <code> * $ua =& Keitai::singleton(); * if ( !$ua->isValidIp() ) { * // シミュレータなどによるアクセスで、gwのip帯ではない * die('invalid access.'); * } * $id = $ua->getKeitaiId(); * </code> * isValidIp() を使う場合には、Keitai_IP_List.class.php が必要です。 * * @auther k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 * @see Keitai_IP_List, isValidIp() */ class Keitai { /** * ファクトリ・メソッド * 使用するクラスを隠蔽して、お任せでインスタンス化するための * メソッドだよ。普通は、直接呼び出されることはないよ。(singleton経由) * * @access public * @param string $userAgent * @return object 成功なら Keitai_* オブジェクト、 * 失敗なら Keitai_Errorオブジェクトを返す。 */ function &factory( $userAgent=null ) { if ( is_null($userAgent)) { $userAgent = $_SERVER['HTTP_USER_AGENT']; } if ( Keitai::isDoCoMo($userAgent) ) { $driver = 'DoCoMo'; } elseif ( Keitai::isKDDI($userAgent) ) { $driver = 'KDDI'; } elseif ( Keitai::isSoftBank($userAgent) ) { $driver = 'SoftBank'; } elseif ( Keitai::isWillcom($userAgent) ) { $driver = 'Willcom'; } elseif ( Keitai::isSmartPhone($userAgent) ) { $driver = 'SmartPhone'; } else { $driver = 'NonMobile'; } $class = "Keitai_".$driver; $instance =& new $class($userAgent); $error =& $instance->isError(); if ( Keitai::isError($error) ) { if ( $GLOBALS['_KEITAI_FALLBACK_ON_NOMATCH'] && $error->getCode() == KEITAI_ERROR_NOMATCH ) { $instance =& Keitai::factory('Keitai_Fallback_On_NoMatch'); return $instance; } $instance =& $error; } return $instance; } /** * シングルトン・メソッド * おんなじようなオブジェクトを使いまわすときに、新たにインスタンス化しない * ためのパターン。(んーでも、コンストラクタでやることが重要な場合は * 気をつけないといけないね。) * * @access public * @param string $userAgent * @return object $userAgentをキーとしてオブジェクトを管理。 * 同じuserAgentならインスタンスつくらないよ。 */ function &singleton($userAgent=null) { static $instance; if ( !isset($instance) ) { $instances = array(); } if ( is_null($userAgent) ) { $userAgent = $_SERVER['HTTP_USER_AGENT']; } if ( !array_key_exists($userAgent, $instances) ) { $instances["$userAgent"] = Keitai::factory($userAgent); } return $instances["$userAgent"]; } /** * エラーオブジェクト判定 * Keitai_Error オブジェクトが生成されているかを判定するよ * * @access public * @param var $value * @return bool $valueが Keitai_Error オブジェクトなら TRUE, * それ以外なら FALSE を返す。 */ function isError($value) { return is_a($value, 'Keitai_Error'); } /** * コードごとに割当てられたエラーメッセージを取得する * * @access public * @param int $value * @return string */ function errorMessage($value) { static $errorMessage; if ( !isset($errorMessage) ) { $errorMessages = array( KEITAI_ERROR => 'unkown error', KEITAI_ERROR_NOMATCH => 'no match', KEITAI_ERROR_NOT_FOUND => 'not found', KEITAI_OK => 'no error' ); } if ( Keitai::isError($value) ) { $value = $value->getCode(); } return isset($errorMessage["$value"]) ? $errorMessage["$value"] : $errorMessage[KEITAI_ERROR]; } /** * モバイルか非モバイルかを判定する * (パースしているので無駄なメソッドともいえる。) * * @access public * @param string $userAgent * @return bool モバイルならtrue, 非モバイルならfalse を返す。 */ function isMobile ( $userAgent=null ) { if ( Keitai::isDoCoMo($userAgent) ) { return true; } elseif ( Keitai::isSoftBank($userAgent) ) { return true; } elseif ( Keitai::isKDDI($userAgent) ) { return true; } elseif ( Keitai::isWillcom($userAgent) ) { return true; } elseif ( Keitai::isSmartPhone($userAgent) ) { return true; } return false; } /** * HTTP-UserAgent からキャリアを判定して返す。最初にパースをするところ * * SoftBankの端末の中にも UP.Link とかだすやつがいるので * KDDIよりも先にSoftBankを判定するよ。 * * @access private * @param string $userAgent * @return string */ function _parse($userAgent=null) { if ( is_null($userAgent) ) { $userAgent = $_SERVER['HTTP_USER_AGENT']; } /* * DoCoMo */ if ( !strncmp($userAgent, 'DoCoMo', 6) ) { return 'DoCoMo'; } /* * SoftBank (inc. J-Phone Vodafone) */ if ( !strncmp($userAgent, 'J-PHONE', 7) ) { return 'SoftBank'; } if ( !strncmp($userAgent, 'Vodafone', 8) || !strncmp($userAgent, 'MOT', 3) ) { return 'SoftBank'; } if ( !strncmp($userAgent, 'SoftBank', 8) ) { return 'SoftBank'; } /* * KDDI au */ if ( !strncmp($userAgent, 'KDDI', 4) || !strncmp($userAgent, 'UP.Browser', 10) ) { return 'KDDI'; } /* * WILLCOM (inc. DDIpocket ) */ if ( strpos($userAgent, 'WILLCOM') !== false || strpos($userAgent, 'SHARP/WS') !== false || strpos($userAgent, 'DDIPOCKET') !== false ) { return 'Willcom'; } /* * SmartPhone * - Android * - iPhone * - Windows Mobile * - etc. */ if ( strpos($userAgent, 'Android') !== false && strpos($userAgent, 'Mobile') !== false ) { return 'SmartPhone'; } if ( strpos($userAgent, 'iPhone') !== false && strpos($userAgent, 'Mobile') !== false ) { return 'SmartPhone'; } if ( strcmp($userAgent, 'iPod') !== false && strpos($userAgent, 'Mobile') !== false ) { return 'SmartPhone'; } if ( isset($_SERVER['HTTP_UA_OS']) && strpos($_SERVER['HTTP_UA_OS'], 'Windows CE') !== false ) { return 'SmartPhone'; } return 'NonMobile'; } /** * DoCoMo判定 * * @access public * @param string $userAgent * @return bool */ function isDoCoMo($userAgent) { return ('DoCoMo'==Keitai::_parse($userAgent)) ? true : false; } /** * KDDI判定 * * @access public * @param string $userAgent * @return bool */ function isKDDI($userAgent) { return ('KDDI'==Keitai::_parse($userAgent)) ? true : false; } /** * SoftBank判定 * * @access public * @param string $userAgent * @return bool */ function isSoftBank($userAgent) { return ('SoftBank'==Keitai::_parse($userAgent)) ? true : false; } /** * Willcom判定 * * @access public * @param string $userAgent * @return bool */ function isWillcom($userAgent) { return ('Willcom'==Keitai::_parse($userAgent)) ? true : false; } /** * SmartPhone判定 * * @access public * @param string $userAgent * @return bool */ function isSmartPhone($userAgent) { return ('SmartPhone'==Keitai::_parse($userAgent)) ? true : false; } /** * 非モバイル判定 * * @access public * @param string $userAgent * @return bool */ function isNonMobile($userAgent) { return ('NonMobile'==Keitai::_parse($userAgent)) ? true : false; } } /** * エラー処理用クラス * うむー、自分で作ったものにも組み込まないトナー * * @auther k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_Error extends PEAR_Error { /** * Constractor * * @access public * @param int $code * @param int $mode * @param int $level * @param bool $userinfo */ function Keitai_Error ( $code=KEITAI_ERROR, $mode=PEAR_ERROR_RETURN, $level=E_USER_NOTICE, $userinfo=null ) { if ( is_int($code) ) { $this->PEAR_Error('Keitai Error: '.Keitai::errorMessage($code), $code, $mode, $level, $userinfo ); } else { $this->PEAR_Error("Keitai Error: $code", KEITAI_ERROR, $mode, $level, $userinfo ); } } /** * PEAR::isError() のインタフェース的 * * @access public * @return bool */ function isError() { return PEAR::isError($this); } } /** * ケータイクラスの基本となるスーパークラス * インターフェース的に使うわけだが、共通化できるものはするぜ的。 * * @auther k5959k+yamada@gmail.com * @package ya--mada * @create 2007-02-13 */ class Keitai_Common extends PEAR { var $version; // var $carrier; // DoCoMo, KDDI, SoftBank, Willcom, NonMobile var $_ua; // HTTP-UserAgent var $_keitaiId; // terminal unique serial number var $_model; var $_rawModel; var $_display; var $_vendor; // vendor code like 'SH' var $_cacheSize; var $_comment; // like 'Google WAP Proxy/1.0' var $_isValidIp; var $_rawCarrier; // UserAgentの最初のワード J-PHONEとかUP.Linkとか var $_error; /** * Constractor * インターフェースだね。 * * @access public * @param string $userAgent */ function Keitai_Common ( $userAgent ) { parent::PEAR('Keitai_Error'); // 親コンストラクタの呼び出し $result = $this->parse($userAgent); if ( Keitai::isError($result) ) { $this->isError($result); } $this->_ua = $userAgent; $this->carrier = $this->getCarrier(); } /** * エラー判定 * * @access public * @param object 引数がnullならオブジェクト内のプロパティを返す。 * @return object */ function &isError( $error=null ) { if ( !is_null($error) ) { $this->_error = &$error; } return $this->_error; } /** * エラーオブジェクトの生成 * * @access public * @param int $code * @param int $mode * @param int $level * @param bool $userinfo */ function &raiseError( $code = KEITAI_ERROR, $mode = null, $options = null, $userinfo = null ) { if ( is_object($code) ) { $error =& PEAR::raiseError( $code, null, null, null, null, null, true ); return $error; } $error =& PEAR::raiseError( null, $code, $mode, $options, $userinfo, 'Keitai_Error', true ); return $error; } /** * get UserAgent * * @access public * @return string _userAgent */ function getUA () { return $this->_ua; } /** * get HTTP header * * @access public * @param string $header HTTP header entory * @return string $_SERVER['HTTP_'.$header] */ function getHeader ( $header ) { return @$_SERVER['HTTP_'.str_replace( '-', '_', $header ) ]; } /** * 携帯電話会社名を返します。 * * @access public * @return string */ function getCarrier () { return $this->carrier; } /** * 携帯アクセスのパースにマッチしないときの処理をするメソッド * * @access public * @return object Keitai_Errorを返す */ function noMatch () { return $this->raiseError( KEITAI_ERROR_NOMATCH, null, null, $this->getUA(), ': might be new variants. Please contact the authoer of Keitai class!' ); } /** * パースメソッドのインターフェース * * @access public */ function parse ( $userAgent ) {} function isNonMobile() { return false; } function isDoCoMo() { return false; } function isKDDI() { return false; } function isSoftBank() { return false; } function isWillcom() { return false; } function isSmartPhone() { return false; } /** * モデル名(機種名) * * @access public * @return string */ function getModel() { if ( is_null($this->_model) ) { return $this->_rawModel; } return $this->_model; } /** * モデル名(加工なし) * * @access public * @return string */ function getRawModel() { return $this->_rawModel; } /** * ヴァージョン番号 * * @access public * @return string */ function getVersion() { return $this->version; } /** * ディスプレイオブジェクト * * @todo 使えないし、使えるようにする気にならない * @access public * @return object */ function getDisplay() { if ( !is_object($this->_display) ) { $this->_display = $this->makeDisplay(); } return $this->_display; } /** * アクセス元のIP判定 * 携帯キャリアのgwのipからのアクセスかどうかを調べる * Keitai_IP_List.class.php に記述した IPaddr からのアクセスか確認する * * @access public * @return bool * @see PEAR::Net::IPv4, Keitai_IP_List */ function isValidIp () { include_once('Net/IPv4.php'); include_once('Keitai_IP_List.class.php'); $list =& Keitai_IP_List::getList($this->carrier); $this->_isValidIp = false; foreach ( $list as $valid_ip ) { if ( Net_IPv4::ipInNetwork($_SERVER['REMOTE_ADDR'], $valid_ip) ) { $this->_isValidIp = true; break; } } return $this->_isValidIp; } /** * 携帯電話のサブスクライバIDを取得する * 実際には、各クラスのparse()内で取得します。 * * DoCoMo: UserAgentの最後に serXXXXX;iccxxxxxx で付加される * au: $_SERVER['HTTP_X_UP_SUBNO'] xxxxxx_t*.ezweb.ne.jp で取得できる * SoftBank: UserAgent内に埋め込み、端末によって異なる */ function getKeitaiId () { return $this->_keitaiId; } /** * コメント扱いの値 * * @access public * @return string */ function getComment () { return $this->_comment; } /** * ベンダー * * @access public * @return string */ function getVendor () { return $this->_vendor; } } /** * NTT DoCoMo 用のクラス * コンストラクタ無しですが、コンストラクタを加えるときには * parent::PEAR($userAgent) を入れるのが良いと思います。 * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_DoCoMo extends Keitai_Common { var $_status; var $_bandWidth; var $_isFoma; var $_serialId; var $_fomaCardId; var $_displayBytes; /** * ドコモ判定 * * @access public * @return bool */ function isDoCoMo() { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'DoCoMo'; } /** * DoCoMoキャリアのアクセスをパースするよ * mova と FOMA でパースが異なるよ。 * * @access public * @param string $userAgent * @see _parseKeitaiId(), _parseMain(), _parseFoma() */ function parse($userAgent) { @list($main, $foma_or_comment) = explode(' ', $userAgent, 2); if ( $foma_or_comment && preg_match('/^\((.*)\)$/', $foma_or_comment, $matches) ) { // ex. DoCoMo/1.0/P209is (Google CHTML Proxy/1.0) $this->_comment = $matches[1]; $result = $this->_parseMain($main); } elseif ( $foma_or_comment ) { // ex. DoCoMo/2.0 N2001(c10;ser01234abc;icc0123456) $this->_isFoma = true; list($this->name, $this->version) = explode('/', $main); $result = $this->_parseFoma($foma_or_comment); } else { // ex. DoCoMo/1.0/R692i/c10 $result = $this->_parseMain($main); } if ( Keitai::isError($result) ) { return $result; } /* * サブスクライバIDの取得 */ $keitaiId = $this->_parseKeitaiId($userAgent); if ( !is_null($keitaiId) ) { $this->_keitaiId = $keitaiId; } /* * iモードID に対応する * HTTP拡張ヘッダ X-DCMGUID を取得する */ if ( isset($_SERVER['HTTP_X_DCMGUID']) ) { $this->_keitaiId = $this->getHeader('X-DCMGUID'); } elseif ( !is_null($this->_serialId) ) { $this->_keitaiId = $this->_serialId; } else { $this->_keitaiId = null; } } /** * 端末の個体識別番号を取得します * * @access public * @param string $userAgent * @return string $id エラーの場合は null を返します。 * @see _parseKeitaiId(), _parseMain(), _parseFoma() */ function _parseKeitaiId($userAgent) { $id = null; // mova if ( substr($userAgent, 7, 3) === '1.0' ) { // "/"区切りで最後を取り出す $pieces = explode('/', $userAgent); $ser = array_pop($pieces); if ( !strncmp($ser, 'ser', 3) ) { $id = $ser; } } // FOMA elseif ( substr($userAgent, 7, 3) === '2.0' ) { $ser = substr($userAgent, -24, -1); if ( !strncmp($ser, 'ser', 3) ) { $id = $ser; } } return $id; } /** * digital MOVA 用のパーサー * * @access public * @param string * @see _parseKeitaiId(), _parseMain(), _parseFoma() */ function _parseMain ( $main ) { @list($this->_rawCarrier, $this->version, $this->_rawModel, $cache, $rest) = explode('/', $main, 5); if ( $this->_rawModel == 'SH505i2' ) { $this->_model = 'SH505i'; } if ($cache) { if (!preg_match('/^c(\d+)$/', $cache, $matches)) { return $this->noMatch(); } $this->_cacheSize = (integer)$matches[1]; } if ($rest) { $rest = explode('/', $rest); foreach ( $rest as $value ) { if (preg_match('/^ser(\w{11})$/', $value, $matches)) { $this->_serialId = $matches[1]; continue; } if (preg_match('/^(T[CDBJ])$/', $value, $matches)) { $this->_status = $matches[1]; continue; } if (preg_match('/^s(\d+)$/', $value, $matches)) { $this->_bandwidth = (integer)$matches[1]; continue; } if (preg_match('/^W(\d+)H(\d+)$/', $value, $matches)) { $this->_displayBytes = "{$matches[1]}*{$matches[2]}"; continue; } } } } /** * FOMA 用のパーサー * * @access public * @param string * @see _parseKeitaiId(), _parseMain(), _parseFoma() */ function _parseFoma ($foma) { if (!preg_match('/^([^(\s]+)/', $foma, $matches)) { return $this->noMatch(); } $this->_rawModel = $matches[1]; if ( $this->_rawModel == 'MS_v_SH2101V' ) { $this->_model = 'SH2101V'; } if (preg_match('/^[^(\s]+\s?\((.*?)\)$/', $foma, $matches)) { // DoCoMo compatible user-agent. if (preg_match('/^compatible/', $matches[1])) { $this->_comment = $matches[1]; return; } $rest = explode(';', $matches[1]); foreach ( $rest as $value ) { if ( preg_match('/^c(\d+)$/', $value, $matches) ) { $this->_cacheSize = (integer)$matches[1]; continue; } if ( preg_match('/^ser(\w{15})$/', $value, $matches) ) { $this->_serialId = $matches[1]; continue; } if ( preg_match('/^(T[CDBJ])$/', $value, $matches) ) { $this->_status = $matches[1]; continue; } if ( preg_match('/^icc(\w{20})?$/', $value, $matches) ) { if (count($matches) == 2) { $this->_fomaCardId = $matches[1]; } continue; } if ( preg_match('/^W(\d+)H(\d+)$/', $value, $matches) ) { $this->_displayBytes = "{$matches[1]}*{$matches[2]}"; continue; } return $this->noMatch($value); } } } } /** * KDDI au 用のクラス * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_KDDI extends Keitai_Common { var $_serverName; // server string like 'UP.Link/3.2.1.2 var $_xhtmlCompliant; /** * KDDI判定 * * @access public * @return bool */ function isKDDI() { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'KDDI'; } /** * KDDIキャリアのアクセスをパースするよ * * @access public * @param string $userAgent */ function parse($userAgent) { /* * HTTP-UserAgent をパースしてプロパティに代入する */ if ( preg_match('/^KDDI-(.*)/', $userAgent, $matches) ) { // ex. KDDI-ST33 UP.Browser/6.2.0.13.2 (GUI) MMP/2.0 $this->_xhtmlCompliant = true; list($this->_rawModel, $browser, $opt, $this->_serverName) = explode( ' ', $matches[1], 4 ); list($this->_rawCarrier, $version) = explode('/',$browser); $this->version = "$version $opt"; } else { // ex. UP.Browser/3.01-HI01 UP.Link/3.4.5.2 @list($browser, $this->_serverName, $comment) = explode(' ', $userAgent, 3); list($this->_rawCarrier, $software) = explode('/', $browser); list($this->version, $this->_rawModel) = explode('-', $software); if ( $comment ) { $this->_comment = preg_replace('/^\((.*)\)$/', '$1', $comment); } } /* * subscriver id * au ではhttp拡張ヘッダで情報を送ってくる */ if ( isset($_SERVER['HTTP_X_UP_SUBNO']) ) { $this->_keitaiId = $this->getHeader('X-UP-SUBNO'); } else { $this->_keitaiId = null; } } /** * HDMLではなく、XHTMLを解釈できますよフラグ * * @access public * @return bool */ function isXHTMLCompliant() { return $this->_xhtmlCompliant; } /** * 機種名(rawModel)の3番目の文字が「3」だったら WIN端末です * * @access public * @return bool */ function isWIN () { return (substr($this->_rawModel, 2,1)==3) ? true : false; } } /** * * */ /** * SoftBank include J-Phone, Vodafone 用のクラス * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_SoftBank extends Keitai_Common { var $_packetCompliant; var $_vendorVersion; // vendor version like '0001a' var $_javaInfo; // Java profiles var $_is3G; var $_msName; // the name of the mobile phone var $_carrierModel; // Motorolaもあるでよ メーカーとも違う var $_serialId; /** * ソフトバンク判定 * * @access public * @return bool */ function isSoftBank () { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'SoftBank'; } /** * SoftBankキャリアのアクセスをパースするよ * モトローラの扱いがちょっと厄介な感じだね。 * HTTP拡張ヘッダ X_JPHONE_UID を取得するように変更 2008-12-09 * 拡張ヘッダがない場合は、UserAgent内のシリアルidを使用する。 * * @access public * @param string $userAgent * @see _parseKeitaiId(), _parseMotorola() */ function parse ($userAgent) { $agent = explode(' ', $userAgent); preg_match('!^(?:(SoftBank|Vodafone|J-PHONE)/\d.\d|MOT-|MOTEMULATOR)!', $agent[0], $matches ); if (count($matches)>1) { $this->_rawCarrier = $matches[1]; } else { $this->_rawCarrier = 'Motorola'; } switch ($this->_rawCarrier) { case 'SoftBank': case 'Vodafone': case 'J-PHONE': case 'Motorola': case 'MOTEMULATOR': $result = $this->_parseMotorola($agent); break; } if (Keitai::isError($result)) { return $result; } $this->_mSname = $this->getHeader('X-JPHONE-MSNAME'); /* * サブスクライバIDの取得 */ $this->_serialId = $this->_parseKeitaiId($userAgent); /* * HTTP拡張ヘッダ X_JPHONE_UID を取得する */ if ( isset($_SERVER['HTTP_X_JPHONE_UID']) ) { $this->_keitaiId = $this->getHeader('X-JPHONE-UID'); } else { $this->_keitaiId = $this->_serialId; } } /** * 端末の個体識別番号を取得します * * @access public * @param string $userAgent * @return string $id エラーの場合は null を返します。 * @see _parseKeitaiId(), _parseMotorola() */ function _parseKeitaiId($userAgent) { $id = null; // J-Phone(PDC) if ( !strncmp($userAgent, 'J-PHONE', 7) ) { $pieces = explode('/', $userAgent); $piece_sn = explode(' ', $pieces[3]); $sn = array_shift($piece_sn); if (!strncmp($sn, 'SN', 2)) { $id = $sn; } } // Vodafone(3G) // MOTは製造番号を取得できない?ほんとに? elseif (!strncmp($userAgent, 'Vodafone', 8)) { $pieces = explode('/', $userAgent); $piece_sn = explode(' ', $pieces[4]); $sn = array_shift($piece_sn); if (!strncmp($sn, 'SN', 2)) { $id = $sn; } } // SoftBank elseif (!strncmp($userAgent, 'SoftBank', 8)) { $pieces = explode('/', $userAgent); $piece_sn = explode(' ', $pieces[4]); $sn = array_shift($piece_sn); if (!strncmp($sn, 'SN', 2)) { $id = $sn; } } return $id; } /** * モトローラ(シミュレータ?)のパーサー * * @access public * @param string */ function _parseMotorola($agent) { $count = count($agent); $this->_packetCompliant = true; $this->_vendor = 'MOT'; // ex. MOT-V980/80.2F.2E MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1 list($this->_rawModel, $this->_vendorVersion) = explode('/', $agent[0]); $this->_model = substr(strrchr($this->_rawModel, '-'), 1); for ( $i=2 ; $i<$count ; ++$i ) { list($key, $value) = explode('/', $agent[$i]); $this->_javaInfo["$key"] = $value; } } /** * packet compliant なんやパケット完全性? * * @access public * @return */ function isPacketCompliant() { return $this->_packetCompliant; } } /** * WILLCOM include DDI Pocket, AirH" 用のクラス * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_Willcom extends Keitai_Common { var $_modelVersion; var $_browserVersion; /** * ウィルコム判定 * * @access public * @return bool */ function isWillcom () { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'Willcomm'; } /** * WILLCOMキャリアのアクセスをパースするよ * * @access public * @param string $userAgent */ function parse($userAgent) { if ( preg_match('!^Mozilla/3\.0\((?:DDIPOCKET|WILLCOM);(.*)\)!', $userAgent, $matches) ) { list($this->_vendor, $this->_rawModel, $this->_modelVersion, $this->_browserVersion, $cache) = expload('/', $matches[1]); if (!preg_match('/^[Cc](\d+)/', $cache, $matches) ) { return $this->noMatch(); } $this->_cacheSize = (integer)$matches[1]; } else { $this->noMatch(); } } /** * キャッシュサイズ * * @access public * @return string */ function getCacheSize () { return $this->_cacheSize; } } /** * スマートフォン用のクラス * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2009-11-16 */ class Keitai_SmartPhone extends Keitai_Common { /** * スマートフォン判定 * * @access public * @return bool */ function isSmartPhone() { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'SmartPhone'; } /** * スマートフォンのアクセスをパースするよ * といっても / で分解するだけだよ。 * * @todo 各OSをちゃんと見分けられるようなメソッドを用意する * @access public * @param string $userAgent */ function parse($userAgent) { @list($this->_rawCarrier, $this->version) = explode('/',$userAgent); } } /** * 非モバイル用のクラス * * @author k5959k+yamada@gmail.com * @package ya--mada * @create 2008-02-13 */ class Keitai_NonMobile extends Keitai_Common { /** * 非モバイル判定 * * @access public * @return bool */ function isNonMobile() { return true; } /** * キャリア名を返すよ * * @access public * @return string */ function getCarrier () { return 'NonMobile'; } /** * 非モバイルのアクセスをパースするよ * といっても / で分解するだけだよ。 * * @access public * @param string $userAgent */ function parse($userAgent) { @list($this->_rawCarrier, $this->version) = explode('/',$userAgent); } }