1: <?php
2: /**
3: * This file contains the the backend and frontend session class.
4: *
5: * @package Core
6: * @subpackage Session
7: * @author Frederic Schneider
8: * @copyright four for business AG <www.4fb.de>
9: * @license http://www.contenido.org/license/LIZENZ.txt
10: * @link http://www.4fb.de
11: * @link http://www.contenido.org
12: */
13:
14: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
15:
16: /**
17: * Backend session class.
18: *
19: * @package Core
20: * @subpackage Session
21: */
22: class cSession {
23:
24: /**
25: * Saves the registered variables
26: *
27: * @var array
28: */
29: protected $_pt;
30:
31: /**
32: * The prefix for the session variables
33: *
34: * @var string
35: */
36: protected $_prefix;
37:
38: /**
39: * Placeholder.
40: * This variable isn't needed to make sessions work any longer
41: * but some CONTENIDO functions/classes rely on it
42: *
43: * @var string
44: */
45: public $id;
46:
47: /**
48: * Placeholder.
49: * This variable isn't needed to make sessions work any longer
50: * but some CONTENIDO functions/classes rely on it
51: *
52: * @var string
53: */
54: public $name;
55:
56: /**
57: * Constructor to create an instance of this class.
58: *
59: * Starts the session.
60: *
61: * @param string $prefix [optional]
62: * The prefix for the session variables
63: */
64: public function __construct($prefix = 'backend') {
65: $cfg = cRegistry::getConfig();
66: $this->_pt = array();
67: $this->_prefix = $prefix;
68:
69: $this->name = 'contenido';
70:
71: if (!isset($_SESSION)) {
72: if ('backend' === $prefix) {
73: $url = cRegistry::getBackendUrl();
74: } else {
75: $url = cRegistry::getFrontendUrl();
76: }
77:
78: // remove protocol from contenido URL
79: $start = strpos($url, '://');
80: if (false === $start) {
81: $url = 'http://' . $url;
82: $start = strpos($url, '://');
83: }
84:
85: // url of contenido folder with hostname
86: $path = substr($url, $start + 3);
87:
88: $start = strpos($path, '/');
89: if (false !== $start) {
90: $path = substr($path, $start);
91: session_set_cookie_params(0, $path, null, $cfg['secure'], true);
92: } else {
93: // fall back to entire domain if no path can be computed
94: session_set_cookie_params(0, '/', null, $cfg['secure'], true);
95: }
96:
97: session_name($this->_prefix);
98: session_start();
99: $this->id = session_id();
100: }
101: }
102:
103: /**
104: * Registers a global variable which will become persistent
105: *
106: * @param string $things
107: * The name of the variable (e.g. "idclient")
108: */
109: public function register($things) {
110: $things = explode(',', $things);
111:
112: foreach ($things as $thing) {
113: $thing = trim($thing);
114: if ($thing) {
115: $this->_pt[$thing] = true;
116: }
117: }
118: }
119:
120: /**
121: * Unregisters a variable
122: *
123: * @param string $name
124: * The name of the variable (e.g. "idclient")
125: */
126: public function unregister($name) {
127: $this->_pt[$name] = false;
128: }
129:
130: /**
131: * Checks if a variable is registered
132: *
133: * @param string $name
134: * The name of the variable (e.g. "idclient")
135: * @return bool
136: */
137: public function isRegistered($name) {
138: if (isset($this->_pt[$name]) && $this->_pt[$name] == true) {
139: return true;
140: }
141: return false;
142: }
143:
144: /**
145: * Attaches "&contenido=sessionid" at the end of the URL.
146: * This is no longer needed to make sessions work but some CONTENIDO
147: * functions/classes rely on it
148: *
149: * @param string $url
150: * a URL
151: * @return mixed
152: */
153: public function url($url) {
154:
155: // Remove existing session info from url
156: $url = preg_replace('/([&?])' . quotemeta(urlencode($this->name)) . '=1(&|$)/', "\\1", $url);
157:
158: // Remove trailing ?/& if needed
159: $url = preg_replace('/[&?]+$/', '', $url);
160:
161: if (!preg_match('~\b' . quotemeta(urlencode($this->name)) . '=[a-zA-Z0-9]*\b~', $url)) {
162: $url .= (strpos($url, '?') != false? '&' : '?') . urlencode($this->name) . '=' . $this->id;
163: }
164:
165: // Encode naughty characters in the URL
166: $url = str_replace(array(
167: '<',
168: '>',
169: ' ',
170: '"',
171: '\''
172: ), array(
173: '%3C',
174: '%3E',
175: '+',
176: '%22',
177: '%27'
178: ), $url);
179: return $url;
180: }
181:
182: /**
183: * Attaches "&contenido=1" at the end of the current URL.
184: * This is no longer needed to make sessions work but some CONTENIDO
185: * functions/classes rely on it
186: *
187: * @return mixed
188: */
189: public function selfURL() {
190: return $this->url($_SERVER['PHP_SELF'] . ((isset($_SERVER['QUERY_STRING']) && ('' != $_SERVER['QUERY_STRING'])) ? '?' . $_SERVER['QUERY_STRING'] : ''));
191: }
192:
193: /**
194: * Returns PHP code which can be used to rebuild the variable by evaluating
195: * it.
196: * This will work recursevly on arrays
197: *
198: * @param mixed $var
199: * A variable which should get serialized.
200: * @return string
201: * the PHP code which can be evaluated.
202: */
203: public function serialize($var) {
204: $str = "";
205: $this->_rSerialize($var, $str);
206: return $str;
207: }
208:
209: /**
210: * This function will go recursevly through arrays and objects to serialize
211: * them.
212: *
213: * @param mixed $var
214: * The variable
215: * @param string $str
216: * The PHP code will be attached to this string
217: */
218: protected function _rSerialize($var, &$str) {
219: static $t, $l, $k;
220:
221: // Determine the type of $$var
222: eval("\$t = gettype(\$$var);");
223: switch ($t) {
224: case 'array':
225: // $$var is an array. Enumerate the elements and serialize them.
226: eval("reset(\$$var); \$l = gettype(list(\$k)=each(\$$var));");
227: $str .= "\$$var = array(); ";
228: while ('array' == $l) {
229: // Structural recursion
230: $this->_rSerialize($var . "['" . preg_replace("/([\\'])/", "\\\\1", $k) . "']", $str);
231: eval("\$l = gettype(list(\$k)=each(\$$var));");
232: }
233: break;
234: case 'object':
235: // $$var is an object. Enumerate the slots and serialize them.
236: eval("\$k = \$${var}->classname; \$l = reset(\$${var}->persistent_slots);");
237: $str .= "\$$var = new $k; ";
238: while ($l) {
239: // Structural recursion.
240: $this->_rSerialize($var . "->" . $l, $str);
241: eval("\$l = next(\$${var}->persistent_slots);");
242: }
243: break;
244: default:
245: // $$var is an atom. Extract it to $l, then generate code.
246: eval("\$l = \$$var;");
247: $str .= "\$$var = '" . preg_replace("/([\\'])/", "\\\\1", $l) . "'; ";
248: break;
249: }
250: }
251:
252: /**
253: * Stores the session using PHP's own session implementation
254: */
255: public function freeze() {
256: $str = $this->serialize("this->_pt");
257:
258: foreach ($this->_pt as $thing => $value) {
259: $thing = trim($thing);
260: if ($value) {
261: $str .= $this->serialize("GLOBALS['" . $thing . "']");
262: }
263: }
264:
265: $_SESSION[$this->_prefix . 'csession'] = $str;
266: }
267:
268: /**
269: * Rebuilds every registered variable from the session.
270: */
271: public function thaw() {
272: if (isset($_SESSION[$this->_prefix . 'csession']) && $_SESSION[$this->_prefix . 'csession'] != '') {
273: eval(sprintf(';%s', $_SESSION[$this->_prefix . 'csession']));
274: }
275: }
276:
277: /**
278: * Deletes the session by calling session_destroy()
279: */
280: public function delete() {
281: $params = session_get_cookie_params();
282: setcookie(session_name(), '', time() - 600, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
283:
284: session_destroy();
285: }
286:
287: /**
288: * Starts the session and rebuilds the variables
289: */
290: public function start() {
291: $this->thaw();
292: }
293: }
294:
295: /**
296: * Session class for the frontend.
297: * It uses a different prefix. The rest is the
298: * same
299: *
300: * @package Core
301: * @subpackage Session
302: */
303: class cFrontendSession extends cSession {
304:
305: /**
306: * Constructor to create an instance of this class.
307: *
308: * Starts the session and initilializes the class.
309: */
310: public function __construct() {
311: $client = cRegistry::getClientId();
312:
313: parent::__construct($client . "frontend");
314: }
315:
316: /**
317: * This function overrides cSession::url() so that the contenido=1 isn't
318: * attached to the URL for the frontend
319: *
320: * @see cSession::url()
321: * @param string $url
322: * a URL
323: * @return mixed
324: */
325: public function url($url) {
326: $url = preg_replace('/([&?])' . quotemeta(urlencode($this->name)) . '=' . $this->id . '(&|$)/', "\\1", $url);
327:
328: $url = preg_replace('/[&?]+$/', '', $url);
329:
330: $url = str_replace(array(
331: '<',
332: '>',
333: ' ',
334: '"',
335: '\''
336: ), array(
337: '%3C',
338: '%3E',
339: '+',
340: '%22',
341: '%27'
342: ), $url);
343:
344: return $url;
345: }
346: }
347: