Completed
Push — master ( 62b2ba...927a33 )
by Patrick
03:48
created

FlipRESTFormat::getFormatFromHeader()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 18
rs 9.2
1
<?php
2
require_once('class.FlipSession.php');
3
require_once('libs/Slim/Slim/Slim.php');
4
require_once('Autoload.php');
5
\Slim\Slim::registerAutoloader();
6
7
const SUCCESS = 0;
8
const UNRECOGNIZED_METHOD = 1;
9
const INVALID_PARAM = 2;
10
const ALREADY_LOGGED_IN = 3;
11
const INVALID_LOGIN = 4;
12
const ACCESS_DENIED = 5;
13
const INTERNAL_ERROR = 6;
14
15
const UNKNOWN_ERROR = 255;
16
17
class OAuth2Auth extends \Slim\Middleware
18
{
19
    protected $headers = array();
20
21
    public function __construct($headers)
22
    {
23
        $this->headers = $headers;
24
    }
25
26
    private function getUserFromSession()
27
    {
28
        if(FlipSession::isLoggedIn())
29
        {
30
            return FlipSession::getUser();
31
        }
32
        return false;
33
    }
34
35
    /*
36
     * @SuppressWarnings("Superglobals")
37
     * @SuppressWarnings("StaticAccess")
38
     */
39
    private function getUserFromBasicAuth($header)
40
    {
41
        $auth = \AuthProvider::getInstance();
42
        $auth->login($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
43
        $user = FlipSession::getUser();
44
        if($user === false)
45
        {
46
            $data = substr($header, 6);
47
            $userpass = explode(':', base64_decode($data));
48
            $user = $auth->getUserByLogin($userpass[0], $userpass[1]);
49
        }
50
        return $user;
51
    }
52
53
    /*
54
     * @SuppressWarnings("StaticAccess")
55
     */
56
    private function getUserFromToken($header)
57
    {
58
        $auth = \AuthProvider::getInstance();
59
        $key = substr($header, 7);
60
        return $auth->getUserByAccessCode($key);
61
    }
62
63
    private function getUserFromHeader($header)
64
    {
65
        if(strncmp($header, 'Basic', 5) == 0)
66
        {
67
            return $this->getUserFromBasicAuth($header);
68
        }
69
        return $this->getUserFromToken($header);
70
    }
71
72
    public function call()
73
    {
74
        // no auth header
75
        if(!isset($this->headers['Authorization']))
76
        {
77
            $this->app->user = $this->getUserFromSession();
78
        }
79
        else
80
        {
81
            $header = $this->headers['Authorization'];
82
            $this->app->user = $this->getUserFromHeader($header);
83
        }
84
85
        if($this->app->user === false)
86
        {
87
            $this->app->getLog()->error("No user found for call");
88
        }
89
90
        // this line is required for the application to proceed
91
        $this->next->call();
92
    }
93
}
94
95
class FlipRESTFormat extends \Slim\Middleware
96
{
97
    private function fix_encoded_element($key, $value, &$array, $prefix = '')
98
    {
99
        if(is_array($value))
100
        {
101
            $array[$key] = implode(';', $value);
102
        }
103
        else if($key === '_id' && is_object($value))
104
        {
105
            $array[$key] = $value->{'$id'};
106
        }
107
        else if(is_object($value))
108
        {
109
            $array[$key] = $this->app->request->getUrl().$this->app->request->getPath().$prefix.'/'.$key;
110
        }
111
        else if(strncmp($value, 'data:', 5) === 0)
112
        {
113
            $array[$key] = $this->app->request->getUrl().$this->app->request->getPath().$prefix.'/'.$key;
114
        }
115
    }
116
117
    private function createCSV(&$array)
118
    {
119
        if(count($array) == 0)
120
        {
121
            return null;
122
        }
123
        ob_start();
124
        $df = fopen("php://output", 'w');
125
        if(is_array($array))
126
        {
127
            $first = reset($array);
128
            $keys = FALSE;
129
            if(is_array($first))
130
            {
131
                $keys = array_keys($first);
132
            }
133
            else if(is_object($first))
134
            {
135
                $keys = array_keys(get_object_vars($first));
136
            }
137
            fputcsv($df, $keys);
138
            foreach($array as $row)
139
            {
140
                if(is_array($row))
141
                {
142
                    $id = $row[$keys[0]];
143
                    foreach($row as $key=>$value)
144
                    {
145
                        $this->fix_encoded_element($key, $value, $row, '/'.$id);
146
                    }
147
                    fputcsv($df, $row);
148
                }
149
                else if(is_object($row))
150
                {
151
                    $keyName = $keys[0];
152
                    $id = $row->$keyName;
153
                    if(is_object($id))
154
                    {
155
                        $id = $id->{'$id'};
156
                    }
157
                    $values = get_object_vars($row);
158
                    foreach($values as $key=>$value)
159
                    {
160
                        $this->fix_encoded_element($key, $value, $values, '/'.$id);
161
                    }
162
                    fputcsv($df, $values);
163
                }
164
            }
165
        }
166
        else
167
        {
168
            $array = get_object_vars($array);
169
            fputcsv($df, array_keys($array));
170
            foreach($array as $key=>$value)
171
            {
172
                $this->fix_encoded_element($key, $value, $array);
173
            }
174
            fputcsv($df, $array);
175
        }
176
        fclose($df);
177
        return ob_get_clean();
178
    }
179
180
    private function createXML(&$array)
181
    {
182
        $obj = new SerializableObject($array);
183
        return $obj->xmlSerialize();
184
    }
185
186
    private function serializeData()
187
    {
188
        $data = json_decode($this->app->response->getBody());
189
        switch($this->app->fmt)
190
        {
191
            case 'data-table':
192
                $this->app->response->headers->set('Content-Type', 'application/json');
193
                return json_encode(array('data'=>$data));
194
            case 'csv':
195
                $this->app->response->headers->set('Content-Type', 'text/csv');
196
                $path = $this->app->request->getPathInfo();
197
                $path = strrchr($path, '/');
198
                $path = substr($path, 1);
199
                $this->app->response->headers->set('Content-Disposition', 'attachment; filename='.$path.'.csv');
200
                return $this->createCSV($data);
201
            case 'xml':
202
                $this->app->response->headers->set('Content-Type', 'application/xml');
203
                return $this->createXML($data);
204
            case 'passthru':
205
                return $this->app->response->getBody();
206
            default:
207
                return 'Unknown fmt '.$fmt;
0 ignored issues
show
Bug introduced by
The variable $fmt does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
208
        }
209
    }
210
211
    private function getFormatFromHeader()
212
    {
213
        $mimeType = $this->app->request->headers->get('Accept');
214
        if(strstr($mimeType, 'odata.streaming=true'))
215
        {
216
            $this->app->response->setStatus(406);
217
            return 'json';
218
        }
219
        switch($mimeType)
220
        {
221
            case 'text/csv':
222
                return 'csv';
223
            case 'text/x-vCard':
224
                return 'vcard';
225
            default:
226
                return 'json';
227
        }
228
    }
229
230
    public function call()
231
    {
232
        if($this->app->request->isOptions())
233
        {
234
            return;
235
        }
236
        $params = $this->app->request->params();
237
        $fmt = null;
238
        if(isset($params['fmt']))
239
        {
240
            $fmt = $params['fmt'];
241
        }
242
        if($fmt === null && isset($params['$format']))
243
        {
244
            $fmt = $params['$format'];
245
            if(strstr($fmt, 'odata.streaming=true'))
246
            {
247
                $this->app->response->setStatus(406);
248
                return;
249
            }
250
        }
251
        if($fmt === null)
252
        {
253
            $fmt = $this->getFormatFromHeader();
254
        }
255
256
        $this->app->fmt     = $fmt;
257
        $this->app->odata   = new ODataParams($params);
258
259
        $this->app->isLocal = false;
260
        if($_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR'])
261
        {
262
            $this->app->isLocal = true;
263
        }
264
265
        $this->next->call();
266
267
        if($this->app->response->getStatus() == 200 && $this->app->fmt !== 'json')
268
        {
269
            $text = $this->serializeData();
270
            $this->app->response->setBody($text);
271
        }
272
        else if($this->app->response->getStatus() == 200)
273
        {
274
            $this->app->response->headers->set('Content-Type', 'application/json;odata.metadata=none');
275
        }
276
    }
277
}
278
279
class FlipREST extends \Slim\Slim
280
{
281
    public function __construct()
282
    {
283
        parent::__construct();
284
        $this->config('debug', false);
285
        $headers = array();
286
        if(php_sapi_name() !== "cli")
287
        {
288
            $headers = apache_request_headers();
289
        }
290
        $this->add(new OAuth2Auth($headers));
291
        $this->add(new FlipRESTFormat());
292
        $errorHandler = array($this, 'errorHandler');
293
        $this->error($errorHandler);
294
    }
295
296
    public function get_json_body($array = false)
297
    {
298
        return $this->getJsonBody($array);
299
    }
300
301
    public function getJsonBody($array = false)
302
    {
303
        $body = $this->request->getBody();
304
        return json_decode($body, $array);
305
    }
306
307
    public function errorHandler($exception)
308
    {
309
        $error = array(
310
            'code' => $exception->getCode(),
311
            'message' => $exception->getMessage(),
312
            'file' => $exception->getFile(),
313
            'line' => $exception->getLine(),
314
        );
315
        $this->response->headers->set('Content-Type', 'application/json');
316
        error_log(print_r($error, true));
317
        echo json_encode($error);
318
    }
319
}
320
/* vim: set tabstop=4 shiftwidth=4 expandtab: */
321