OSDN Git Service

Remove PHP closing tag
[ethna/ethna.git] / class / Ethna_Session.php
1 <?php
2 // vim: foldmethod=marker
3 /**
4  *  Ethna_Session.php
5  *
6  *  @author     Masaki Fujimoto <fujimoto@php.net>
7  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
8  *  @package    Ethna
9  *  @version    $Id$
10  */
11
12 // {{{ Ethna_Session
13 /**
14  *  セッションクラス
15  *
16  *  @author     Masaki Fujimoto <fujimoto@php.net>
17  *  @access     public
18  *  @package    Ethna
19  */
20 class Ethna_Session
21 {
22     /**#@+
23      *  @access private
24      */
25
26     /** @var    object  Ethna_Logger    loggerオブジェクト */
27     var $logger;
28
29     /** @var    string  セッション名 */
30     var $session_name;
31
32     /** @var    string  セッションデータ保存ディレクトリ */
33     var $session_save_dir;
34
35     /** @var    bool    セッション開始フラグ */
36     var $session_start = false;
37
38     /** @var    bool    匿名セッションフラグ */
39     var $anonymous = false;
40
41     /**#@-*/
42
43     /**
44      *  Ethna_Sessionクラスのコンストラクタ
45      *
46      *  @access public
47      *  @param  string  $appid      アプリケーションID(セッション名として使用)
48      *  @param  string  $save_dir   セッションデータを保存するディレクトリ
49      */
50     function Ethna_Session($appid, $save_dir, $logger)
51     {
52         $this->session_name = "${appid}SESSID";
53         $this->session_save_dir = $save_dir;
54         $this->logger =& $logger;
55
56         if ($this->session_save_dir != "") {
57             session_save_path($this->session_save_dir);
58         }
59
60         session_name($this->session_name);
61         session_cache_limiter('private, must-revalidate');
62
63         $this->session_start = false;
64         if (isset($_SERVER['REQUEST_METHOD']) == false) {
65             return;
66         }
67
68         if (strcasecmp($_SERVER['REQUEST_METHOD'], 'post') == 0) {
69             $http_vars =& $_POST;
70         } else {
71             $http_vars =& $_GET;
72         }
73         if (array_key_exists($this->session_name, $http_vars)
74             && $http_vars[$this->session_name] != null) {
75             $_COOKIE[$this->session_name] = $http_vars[$this->session_name];
76         }
77     }
78
79     /**
80      *  セッションを復帰する
81      *
82      *  @access public
83      */
84     function restore()
85     {
86         if (!empty($_COOKIE[$this->session_name]) ||
87         (ini_get("session.use_trans_sid") == 1 &&
88         !empty($_REQUEST[$this->session_name]))
89         ) {
90             session_start();
91             $this->session_start = true;
92
93             // check session
94             if ($this->isValid() == false) {
95                 setcookie($this->session_name, "", 0, "/");
96                 $this->session_start = false;
97             }
98
99             // check anonymous
100             if ($this->get('__anonymous__')) {
101                 $this->anonymous = true;
102             }
103         }
104     }
105
106     /**
107      *  セッションの正当性チェック
108      *
109      *  @access public
110      *  @return bool    true:正当なセッション false:不当なセッション
111      */
112     function isValid()
113     {
114         if (!$this->session_start) {
115             if (!empty($_COOKIE[$this->session_name]) || session_id() != null) {
116                 setcookie($this->session_name, "", 0, "/");
117             }
118             return false;
119         }
120
121         // check remote address
122         if (!isset($_SESSION['REMOTE_ADDR'])
123             || $this->_validateRemoteAddr($_SESSION['REMOTE_ADDR'],
124                                           $_SERVER['REMOTE_ADDR']) == false) {
125             // we do not allow this
126             setcookie($this->session_name, "", 0, "/");
127             session_destroy();
128             $this->session_start = false;
129             return false;
130         }
131
132         return true;
133     }
134
135     /**
136      *  セッションを開始する
137      *
138      *  @access public
139      *  @param  int     $lifetime   セッション有効期間(秒単位, 0ならセッションクッキー)
140      *  @return bool    true:正常終了 false:エラー
141      */
142     function start($lifetime = 0, $anonymous = false)
143     {
144         if ($this->session_start) {
145             // we need this?
146             $_SESSION['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
147             $_SESSION['__anonymous__'] = $anonymous;
148             return true;
149         }
150
151         if (is_null($lifetime)) {
152             ini_set('session.use_cookies', 0);
153         } else {
154             ini_set('session.use_cookies', 1);
155         }
156
157         session_set_cookie_params($lifetime);
158         session_id(Ethna_Util::getRandom());
159         session_start();
160         $_SESSION['REMOTE_ADDR'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR']: false;
161         $_SESSION['__anonymous__'] = $anonymous;
162         $this->anonymous = $anonymous;
163         $this->session_start = true;
164
165         return true;
166     }
167
168     /**
169      *  セッションを破棄する
170      *
171      *  @access public
172      *  @return bool    true:正常終了 false:エラー
173      */
174     function destroy()
175     {
176         if (!$this->session_start) {
177             return true;
178         }
179         
180         session_destroy();
181         $this->session_start = false;
182         setcookie($this->session_name, "", 0, "/");
183
184         return true;
185     }
186
187     /**
188      *  セッションIDを再生成する
189      *
190      *  @access public
191      *  @return bool    true:正常終了 false:エラー
192      */
193     function regenerateId($lifetime = 0, $anonymous = false)
194     {
195         if (! $this->session_start) {
196             return false;
197         }
198        
199         $tmp = $_SESSION;
200
201         $this->destroy();
202         $this->start($lifetime, $anonymous);
203         
204         unset($tmp['REMOTE_ADDR']);
205         unset($tmp['__anonymous__']);
206         foreach ($tmp as $key => $value) {
207             $_SESSION[$key] = $value;
208         }
209
210         return true;
211     }
212
213     /**
214      *  セッション値へのアクセサ(R)
215      *
216      *  @access public
217      *  @param  string  $name   キー
218      *  @return mixed   取得した値(null:セッションが開始されていない)
219      */
220     function get($name)
221     {
222         if (!$this->session_start) {
223             return null;
224         }
225
226         if (!isset($_SESSION[$name])) {
227             return null;
228         }
229         return $_SESSION[$name];
230     }
231
232     /**
233      *  セッション値へのアクセサ(W)
234      *
235      *  @access public
236      *  @param  string  $name   キー
237      *  @param  string  $value  値
238      *  @return bool    true:正常終了 false:エラー(セッションが開始されていない)
239      */
240     function set($name, $value)
241     {
242         if (!$this->session_start) {
243             // no way
244             return false;
245         }
246
247         $_SESSION[$name] = $value;
248
249         return true;
250     }
251
252     /**
253      *  セッションの値を破棄する
254      *
255      *  @access public
256      *  @param  string  $name   キー
257      *  @return bool    true:正常終了 false:エラー(セッションが開始されていない)
258      */
259     function remove($name)
260     {
261         if (!$this->session_start) {
262             return false;
263         }
264
265         unset($_SESSION[$name]);
266
267         return true;
268     }
269
270     /**
271      *  セッションが開始されているかどうかを返す
272      *
273      *  @access public
274      *  @param  string  $anonymous  匿名セッションを「開始」とみなすかどうか(default: false)
275      *  @return bool    true:開始済み false:開始されていない
276      */
277     function isStart($anonymous = false)
278     {
279         if ($anonymous) {
280             return $this->session_start;
281         } else {
282             if ($this->session_start && $this->isAnonymous() != true) {
283                 return true;
284             } else {
285                 return false;
286             }
287         }
288     }
289
290     /**
291      *  匿名セッションかどうかを返す
292      *
293      *  @access public
294      *  @return bool    true:匿名セッション false:非匿名セッション/セッション開始されていない
295      */
296     function isAnonymous()
297     {
298         return $this->anonymous;
299     }
300
301     /**
302      *  セッションに保存されたIPアドレスとアクセス元のIPアドレスが
303      *  同一ネットワーク範囲かどうかを判別する(16bit mask)
304      *
305      *  @access private
306      *  @param  string  $src_ip     セッション開始時のアクセス元IPアドレス
307      *  @param  string  $dst_ip     現在のアクセス元IPアドレス
308      *  @return bool    true:正常終了 false:不正なIPアドレス
309      */
310     function _validateRemoteAddr($src_ip, $dst_ip)
311     {
312         $src = ip2long($src_ip);
313         $dst = ip2long($dst_ip);
314
315         if (($src & 0xffff0000) == ($dst & 0xffff0000)) {
316             return true;
317         } else {
318             $this->logger->log(LOG_NOTICE, "session IP validation failed [%s] - [%s]",
319                                $src_ip, $dst_ip);
320             return false;
321         }
322     }
323 }
324 // }}}