Completed
Push — master ( 0d0ae6...7c7732 )
by Stone
19s
created

AjaxController::checkReferer()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 3
nop 0
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Core;
4
5
6
/**
7
 * Class AjaxController
8
 * @package Core
9
 *
10
 * out parent controller for all ajax calls
11
 *
12
 */
13
abstract class AjaxController extends Controller
14
{
15
16
    /**
17
     * The request object to handle all gets and posts
18
     * @var Dependency\Request
19
     *
20
     */
21
    protected $request;
22
23
    /**
24
     * The response module to handle response messages
25
     * @var Dependency\Response
26
     */
27
    protected $response;
28
29
    protected $auth;
30
31
    /**
32
     * On construction, we imediatly check for security and bail out on the first sign of fraude
33
     * Only allow XmlHTTPRequests or throw an exception
34
     * Only allowed to call if Csrf token is valid or throw a json error
35
     * AjaxController constructor.
36
     * @param Container $container
37
     * @throws \Exception
38
     *
39
     */
40
    public function __construct(Container $container)
41
    {
42
        $this->loadModules[] = 'Auth';
43
        parent::__construct($container);
44
45
        $this->request = $container->getRequest(); //adding our request object as it will be needed in the ajax calls
46
        $this->response = $container->getResponse();
47
48
        //we only allow xmlHTTPRequests here for security
49
        $this->checkXlmRequest();
50
        $this->checkReferer();
51
        $this->csrf->checkJsonCsrf();
52
    }
53
54
    /**
55
     * checks if the call is made by an admin and throws an error if not.
56
     * @throws JsonException
57
     */
58
    protected function onlyAdmin()
59
    {
60
        if (!$this->auth->isAdmin()) {
61
            throw new JsonException('You do not have the rights to perform this action');
62
        }
63
    }
64
65
    /**
66
     * Checks if we have an Xml Http request and throws an error if not
67
     * @throws \ErrorException
68
     */
69
    private function checkXlmRequest(): void
70
    {
71
        if (!$this->request->isXmlRequest()) {
72
            throw new \ErrorException('Call not permitted', 404);
73
        }
74
    }
75
76
    /**
77
     * Check if the request is coming from the same domain as the base url of the site
78
     * @throws JsonException
79
     */
80
    private function checkReferer(): void
81
    {
82
83
        $referer = $this->request->getReferer();
84
        $baseUrl = $this->request->getBaseUrl();
85
        $inUrl = strpos($referer, $baseUrl);
86
        if ($inUrl === false || $inUrl > 0) { //not at start of referer
87
            if ($referer !== null) {//the referer can be null with certain navigators, so don't block on that
88
                throw new JsonException('Illegal referer.');
89
90
            }
91
92
        }
93
    }
94
95
    /**
96
     * Construct our json reply message
97
     * @param $message
98
     * @param int $code
99
     * @return string json encoded message
100
     */
101
    public function jsonResponse($message = null, $code = 200): string
102
    {
103
        // clear the old headers
104
        //header_remove(); //->this removes our csrf error checking so no go for the moment.
105
        // set the actual code
106
        http_response_code($code);
107
        // set the header to make sure cache is forced
108
        header("Cache-Control: no-transform,public,max-age=300,s-maxage=900");
109
        // treat this as json
110
        //header('Content-Type: application/json');
111
        $this->response->setHeaderContentType('json');
112
        $status = array(
113
            200 => '200 OK',
114
            400 => '400 Bad Request',
115
            422 => 'Unprocessable Entity',
116
            500 => '500 Internal Server Error'
117
        );
118
        // ok, validation error, or failure
119
        header('Status: ' . $status[$code]);
120
        // return the encoded json
121
        return json_encode(array(
122
            'status' => $code < 300, // success or not?
123
            'message' => $message
124
        ));
125
    }
126
127
128
}