Sip.php 8.59 KB
Newer Older
Carsten  Rose's avatar
Carsten Rose committed
1
2
3
4
5
6
7
8
<?php
/**
 * Created by PhpStorm.
 * User: crose
 * Date: 1/9/16
 * Time: 10:26 PM
 */

9
namespace qfq;
Carsten  Rose's avatar
Carsten Rose committed
10

11
use qfq\CodeException;
12
use qfq\UserFormException;
13
14
use qfq\OnArray;
use qfq\KeyValueStringParser;
Carsten  Rose's avatar
Carsten Rose committed
15
16
17
18

require_once(__DIR__ . '/../../qfq/helper/OnArray.php');
require_once(__DIR__ . '/../../qfq/Constants.php');
require_once(__DIR__ . '/../../qfq/exceptions/CodeException.php');
19
20
require_once(__DIR__ . '/Session.php');

Carsten  Rose's avatar
Carsten Rose committed
21

Carsten  Rose's avatar
Carsten Rose committed
22
23
24
25
/**
 * Class Sip
 * @package qfq\store
 */
Carsten  Rose's avatar
Carsten Rose committed
26
27
class Sip {

Carsten  Rose's avatar
Carsten Rose committed
28
29
30
// $_SESSION['fe_user_uid'] = <fe_user_uid>
// $_SESSION[$sip] => <urlparam>  >> $_SESSION['badcaffee1234'] => 'form=Person&r=1&z=5678'
// $_SESSION[$urlparam] => <sip>  >> $_SESSION['form=Person&r=1&z=5678'] => 'badcaffee1234'
Carsten  Rose's avatar
Carsten Rose committed
31

32
    private $phpUnit = false;
Carsten  Rose's avatar
Carsten Rose committed
33
34
35
36
37
38
    private $staticUniqId = false;

    function __construct($sessionname, $phpUnit = false) {

        $this->phpUnit = $phpUnit;

39
40
41
42
43
44
45
46
47
48
49
//        if ($sessionname == "") {
//            throw new CodeException('Missing "sessionname"', ERROR_MISSING_SESSIONNAME);
//        }
//
//        session_name();
//
//        if ($phpUnit) {
//            $_SESSION = null;
//        } else {
//            session_start();
//        }
Carsten  Rose's avatar
Carsten Rose committed
50

51
        $feUserUid = Session::get(SESSION_FE_USER_UID);
Carsten  Rose's avatar
Carsten Rose committed
52
53

        // Typo3: remember logged in FE User
54
55
        if (isset($GLOBALS["TSFE"]->fe_user->user["uid"]) && $feUserUid === false) {
            Session::set(SESSION_FE_USER_UID, $GLOBALS["TSFE"]->fe_user->user["uid"]);
Carsten  Rose's avatar
Carsten Rose committed
56
57
58
59
60
        }

    }

    /**
Carsten  Rose's avatar
Carsten Rose committed
61
     * @param string $queryString Possible variants:
62
63
64
65
66
     *   * http://www.math.uzh.ch/index.php?a=1&s=4b3403665fea6&r=45&type=99&id=person
     *   * index.php?a=1&s=4b3403665fea6&r=45&type=99&id=person
     *   * ?a=1&s=4b3403665fea6&r=45&type=99&id=person
     *   * a=1&s=4b3403665fea6&r=45&type=99&id=person
     *
Carsten  Rose's avatar
Carsten Rose committed
67
     * @param string $mode Possible values: RETURN_URL|RETURN_SIP
68
     * @return string/array
69
     *  * mode=RETURN_URL: return complete URL
Carsten  Rose's avatar
Carsten Rose committed
70
     *  * mode=RETURN_SIP: returns only the sip
71
     *  * mode=RETURN_ARRAY: returns array with url ('_url') and all decoded and created parameters.
Carsten  Rose's avatar
Carsten Rose committed
72
     * @throws CodeException
73
     * @throws UserFormException
Carsten  Rose's avatar
Carsten Rose committed
74
     */
75
    public function queryStringToSip($queryString, $mode = RETURN_URL, $phpScriptName = INDEX_PHP) {
Carsten  Rose's avatar
Carsten Rose committed
76

Carsten  Rose's avatar
Carsten Rose committed
77
        // Validate: Check if still the same fe_user is logged in.
78
        $this->checkFeUserUid();
Carsten  Rose's avatar
Carsten Rose committed
79
80
81
82
83

        $clientArray = array();
        $sipArray = array();

        // Split URL parameter:
84
        $paramArray = KeyValueStringParser::parse($queryString, "=", "&");
Carsten  Rose's avatar
Carsten Rose committed
85

86
87
88
89
90
        // If no 'r' is specified: define r=0
        if (!isset($paramArray[SIP_RECORD_ID])) {
            $paramArray[SIP_RECORD_ID] = 0;
        }

Carsten  Rose's avatar
Carsten Rose committed
91
92
93
94
        // Split parameter between Script, Client and SIP
        $script = $this->splitParamClientSip($paramArray, $clientArray, $sipArray);

        // sort array to guarantee identical respresentation in $_SESSION. Param 'a, r, b, ...' should be saved as 'a, b, r, ..'
95
        OnArray::sortKey($sipArray);
Carsten  Rose's avatar
Carsten Rose committed
96
97
98
99

        // Generate keyname for $_SESSION[]
        $sipParamString = OnArray::toString($sipArray);

100
101
102
        $sessionParamSip = Session::get($sipParamString);
        if ($sessionParamSip !== false) {
            $s = $sessionParamSip;
Carsten  Rose's avatar
Carsten Rose committed
103
104
105
        } else {
            // Not found: create new entry
            $s = $this->sipUniqId();
106
107
            Session::set($sipParamString, $s);
            Session::set($s, $sipParamString);
Carsten  Rose's avatar
Carsten Rose committed
108
109
        }

110
111
112
113
        // Append SIP to final parameter
        $clientArray[CLIENT_SIP] = $s;

        if ($script[0] === '?')
114
            $script = $phpScriptName . $script;
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129

        $clientArray['_url'] = $script . OnArray::toString($clientArray);

        switch ($mode) {
            case RETURN_URL:
                $rc = $clientArray['_url'];
                break;
            case RETURN_SIP:
                $rc = $s;
                break;
            case RETURN_ARRAY:
                $rc = array_merge($clientArray, $sipArray);
                break;
            default:
                throw new CodeException('Unknown Mode: "' . $mode . '"', ERROR_UNKNOWN_MODE);
Carsten  Rose's avatar
Carsten Rose committed
130
        }
131
132

        return $rc;
Carsten  Rose's avatar
Carsten Rose committed
133
134
    }

135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
    /**
     *
     */
    private function checkFeUserUid() {

        // Validate: Check if still the same fe_user is logged in.
        if (isset($GLOBALS["TSFE"]->fe_user->user["uid"])) {
            $feUserUid = Session::get(SESSION_FE_USER_UID);

            if ($feUserUid !== false && $feUserUid != $GLOBALS["TSFE"]->fe_user->user["uid"]) {
                Session::clear();
            }
        }

    }

Carsten  Rose's avatar
Carsten Rose committed
151
    /**
Carsten  Rose's avatar
Carsten Rose committed
152
153
154
     * Splits the $paramArray in &$clientArray and &$sipArray. $sipArray contains all key/values pairs wich are not belong to Typo3.
     *
     * @param array $paramArray
Carsten  Rose's avatar
Carsten Rose committed
155
156
     * @param array $clientArray
     * @param array $sipArray
Carsten  Rose's avatar
Carsten Rose committed
157
158
     * @return string
     * @throws \qfq\CodeException
Carsten  Rose's avatar
Carsten Rose committed
159
     */
Carsten  Rose's avatar
Carsten Rose committed
160
    private function splitParamClientSip(array $paramArray, array &$clientArray, array &$sipArray) {
Carsten  Rose's avatar
Carsten Rose committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

        $script = '';

        // Possible variants:
        //   http://www.math.uzh.ch/index.php?a=1&s=4b3403665fea6&r=45&type=99&id=person
        //   index.php?a=1&s=4b3403665fea6&r=45&type=99&id=person
        //   ?a=1&s=4b3403665fea6&r=45&type=99&id=person
        //   a=1&s=4b3403665fea6&r=45&type=99&id=person
        $flagFirst = true;
        foreach ($paramArray AS $key => $value) {

            // first key/value pair: a) save potential existing url/script part, b) if no keyname is specified, call it 'id'.
            if ($flagFirst) {
                $flagFirst = false;

                $script = $this->splitAndFix($key, $value);
            }

            // copy every parameter either to $clientArray or to $sipArray
            switch ($key) {
                //special T3 parameter.
                case 'L':
                case 'type':
                case 'id':
                    $clientArray[$key] = $value;
                    break;
                case CLIENT_SIP:
                    throw new CodeException('SIP Parameter ist not allowed to be stored as a regular URL Parameter', ERROR_SIP_NOT_ALLOWED_AS_PARAM);
                default:
190
191
                    // Values in SIP should not urlencoded.
                    $sipArray[$key] = urldecode($value);
Carsten  Rose's avatar
Carsten Rose committed
192
193
194
195
196
197
198
199
                    break;
            }
        }

        return $script;
    }

    /**
200
     * Fix first parameter mix of hostname / script / Get parameter and optional missing keyname
Carsten  Rose's avatar
Carsten Rose committed
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
     *
     * @param $key
     * @param $value
     * @return string Part upto first '?',
     */
    private function splitAndFix(&$key, &$value) {

        $script = '';
        $tmpArray = explode('?', $key, 2);

        if (count($tmpArray) > 1) {
            $script = $tmpArray[0];
            $key = $tmpArray[1]; // new key, now without the hostname / scriptname.
        }
        $script .= '?';


        // empty value: keyname omitted - define keyname as 'id'
        if ($value === '') {
            $value = $key;
            $key = 'id';
        }

        return $script;
    }

    /**
Carsten  Rose's avatar
Carsten Rose committed
228
229
     * Returns a new uniqid, which will be used as a SIP identifier
     *
Carsten  Rose's avatar
Carsten Rose committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
     * @param bool|false $staticUniqId
     * @return bool|string
     */
    public function sipUniqId($staticUniqId = false) {
        if ($this->phpUnit) {
            if ($staticUniqId !== false) {
                $this->staticUniqId = $staticUniqId;
            }
            return $this->staticUniqId;
        }

        return uniqid();
    }

    /**
     * Retrieve Params stored in $_SESSION[$s]
     *
     * @param $s
     * @return array Parameter Array
249
250
     * @throws UserFormException
     * @throws \qfq\UserFormException
Carsten  Rose's avatar
Carsten Rose committed
251
252
253
254
255
     */
    public function getVarsFromSip($s) {

        # Check if parameter is manipulated
        if (strlen($s) != 13) {
256
            throw new UserFormException("Broken Parameter", ERROR_BROKEN_PARAMETER);
Carsten  Rose's avatar
Carsten Rose committed
257
258
        }

259
260
        // Validate: Check if still the same fe_user is logged in.
        $this->checkFeUserUid();
Carsten  Rose's avatar
Carsten Rose committed
261
262

        # Check if index 's' exists.
263
264
265
        $sessionVar = Session::get($s);

        if ($sessionVar === false) {
266
            throw new UserFormException("SIP '$s' not registered - please reload the previous site and try again.", ERROR_SIP_NOT_FOUND);
Carsten  Rose's avatar
Carsten Rose committed
267
268
269
        }

        // Decode parameter
270
        return KeyValueStringParser::parse($sessionVar, "=", "&");
Carsten  Rose's avatar
Carsten Rose committed
271
272
273
    }

    /**
274
275
     * Returns the sip for the given querystring. The querystring has to be sorted.
     *
276
277
278
279
     * @param $queryString
     * @return mixed
     */
    public function getSipFromQueryString($queryString) {
280
        return Session::get($queryString);
281
282
283
    }

    /**
284
285
286
287
     * Returns the querystring for the given $sip
     *
     * @param $sip
     * @return bool
Carsten  Rose's avatar
Carsten Rose committed
288
     */
289
    public function getQueryStringFromSip($sip) {
290
        return Session::get($sip);
Carsten  Rose's avatar
Carsten Rose committed
291
292
293
    }

}