Sip.php 9.01 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 {

28
    private $phpUnit = false;
Carsten  Rose's avatar
Carsten Rose committed
29
30
    private $staticUniqId = false;

31
32
33
34
    /**
     * @param bool|false $phpUnit
     */
    function __construct($phpUnit = false) {
Carsten  Rose's avatar
Carsten Rose committed
35
36
37
38
39

        $this->phpUnit = $phpUnit;
    }

    /**
Carsten  Rose's avatar
Carsten Rose committed
40
     * @param string $queryString Possible variants:
41
42
43
44
45
     *   * 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
46
     * @param string $mode Possible values: RETURN_URL|RETURN_SIP
47
     * @return string/array
48
     *  * mode=RETURN_URL: return complete URL
Carsten  Rose's avatar
Carsten Rose committed
49
     *  * mode=RETURN_SIP: returns only the sip
50
     *  * mode=RETURN_ARRAY: returns array with url ('_url') and all decoded and created parameters.
Carsten  Rose's avatar
Carsten Rose committed
51
     * @throws CodeException
52
     * @throws UserFormException
Carsten  Rose's avatar
Carsten Rose committed
53
     */
54
    public function queryStringToSip($queryString, $mode = RETURN_URL, $phpScriptName = INDEX_PHP) {
Carsten  Rose's avatar
Carsten Rose committed
55
56
57
58
59

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

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

62
63
64
65
66
        // 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
67
68
69
70
        // Split parameter between Script, Client and SIP
        $script = $this->splitParamClientSip($paramArray, $clientArray, $sipArray);

        // Generate keyname for $_SESSION[]
Carsten  Rose's avatar
#2067    
Carsten Rose committed
71
        $sipParamString = $this->buildParamStringFromArray($sipArray);
Carsten  Rose's avatar
Carsten Rose committed
72

73
        $sessionParamSip = Session::get($sipParamString);
74
        if ($sessionParamSip === false) {
Carsten  Rose's avatar
Carsten Rose committed
75
            // Not found: create new entry
76
            $s = $this->sipUniqId('badcaffee1234');
77
78
            Session::set($sipParamString, $s);
            Session::set($s, $sipParamString);
79
80
        } else {
            $s = $sessionParamSip;
Carsten  Rose's avatar
Carsten Rose committed
81
82
        }

83
84
85
86
        // Append SIP to final parameter
        $clientArray[CLIENT_SIP] = $s;

        if ($script[0] === '?')
87
            $script = $phpScriptName . $script;
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

        $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
103
        }
104
105

        return $rc;
Carsten  Rose's avatar
Carsten Rose committed
106
107
108
    }

    /**
Carsten  Rose's avatar
Carsten Rose committed
109
110
111
     * 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
112
113
     * @param array $clientArray
     * @param array $sipArray
Carsten  Rose's avatar
Carsten Rose committed
114
115
     * @return string
     * @throws \qfq\CodeException
Carsten  Rose's avatar
Carsten Rose committed
116
     */
Carsten  Rose's avatar
Carsten Rose committed
117
    private function splitParamClientSip(array $paramArray, array &$clientArray, array &$sipArray) {
Carsten  Rose's avatar
Carsten Rose committed
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

        $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:
145
146
147
148
149
                    if ($this->getQueryStringFromSip($value) === false) {
                        throw new CodeException('SIP Parameter ist not allowed to be stored as a regular URL Parameter', ERROR_SIP_NOT_ALLOWED_AS_PARAM);
                    }
                    $clientArray[$key] = $value;
                    break;
Carsten  Rose's avatar
Carsten Rose committed
150
                default:
151
152
                    // Values in SIP should not urlencoded.
                    $sipArray[$key] = urldecode($value);
Carsten  Rose's avatar
Carsten Rose committed
153
154
155
156
157
158
159
160
                    break;
            }
        }

        return $script;
    }

    /**
161
     * Fix first parameter mix of hostname / script / Get parameter and optional missing keyname
Carsten  Rose's avatar
Carsten Rose committed
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
     *
     * @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
#2067    
Carsten Rose committed
188
    /**
189
     * Takes the values form an array and creates a urlparamstring. Skip values which should not passed to the urlparamstring.
190
     * - SIP_TARGET_URL is necessary for 'delete' links (via 'report') - may be unecessary in other situations.
Carsten  Rose's avatar
Carsten Rose committed
191
     *
Carsten  Rose's avatar
#2067    
Carsten Rose committed
192
193
194
195
196
197
198
199
200
     * @param array $sipArray
     * @return string
     */
    private function buildParamStringFromArray(array $sipArray) {
        $tmpArray = array();

        foreach ($sipArray as $key => $value) {
            switch ($key) {
                case SIP_SIP:
201
202
//                case SIP_MODE_ANSWER:
//                case SIP_TABLE:
Carsten  Rose's avatar
#2067    
Carsten Rose committed
203
204
                case SIP_URLPARAM:
                    break;
205
206

                case SIP_TARGET_URL:  // Do not skip this param. Necessary for delete links (via 'report') - specifies the target where to jump after delete,php has been called (plain HTML, not AJAX)
Carsten  Rose's avatar
#2067    
Carsten Rose committed
207
208
209
210
211
212
213
214
215
216
217
                default:
                    $tmpArray[$key] = $value;
                    break;
            }
        }

        OnArray::sortKey($tmpArray);

        return OnArray::toString($tmpArray);
    }

Carsten  Rose's avatar
Carsten Rose committed
218
    /**
Carsten  Rose's avatar
Carsten Rose committed
219
220
     * Returns a new uniqid, which will be used as a SIP identifier
     *
Carsten  Rose's avatar
Carsten Rose committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
     * @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();
    }

Carsten  Rose's avatar
#2067    
Carsten Rose committed
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
    /**
     * Update the SIP in the Session according $sipArray.
     *
     * @param array $sipArray
     */
    public function updateSipToSession(array $sipArray) {
        $sip = $sipArray[SIP_SIP];

        // Remove old entry, cause the the 'key' will change.
        $sipParamStringOld = Session::get($sipArray[SIP_SIP]);
        Session::unsetItem($sipParamStringOld);

        // Generate keyname for $_SESSION[]
        $sipParamStringNew = $this->buildParamStringFromArray($sipArray);

        Session::set($sip, $sipParamStringNew);
        Session::set($sipParamStringNew, $sip);
    }

Carsten  Rose's avatar
Carsten Rose committed
254
255
256
257
258
    /**
     * Retrieve Params stored in $_SESSION[$s]
     *
     * @param $s
     * @return array Parameter Array
259
260
     * @throws UserFormException
     * @throws \qfq\UserFormException
Carsten  Rose's avatar
Carsten Rose committed
261
262
263
264
     */
    public function getVarsFromSip($s) {

        # Check if parameter is manipulated
265
        if (strlen($s) != SIP_TOKEN_LENGTH) {
266
            throw new UserFormException("Broken Parameter", ERROR_BROKEN_PARAMETER);
Carsten  Rose's avatar
Carsten Rose committed
267
268
        }

269
        // Validate: Check if still the same fe_user is logged in.
270
//        $this->checkFeUserUid();
Carsten  Rose's avatar
Carsten Rose committed
271
272

        # Check if index 's' exists.
273
274
275
        $sessionVar = Session::get($s);

        if ($sessionVar === false) {
276
            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
277
278
279
        }

        // Decode parameter
280
        return KeyValueStringParser::parse($sessionVar, "=", "&");
Carsten  Rose's avatar
Carsten Rose committed
281
282
283
    }

    /**
284
285
     * Returns the sip for the given querystring. The querystring has to be sorted.
     *
286
287
288
289
     * @param $queryString
     * @return mixed
     */
    public function getSipFromQueryString($queryString) {
290
        return Session::get($queryString);
291
292
293
    }

    /**
294
295
296
297
     * Returns the querystring for the given $sip
     *
     * @param $sip
     * @return bool
Carsten  Rose's avatar
Carsten Rose committed
298
     */
299
    public function getQueryStringFromSip($sip) {
300
        return Session::get($sip);
Carsten  Rose's avatar
Carsten Rose committed
301
302
303
    }

}