1<?php
2/**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 *
8 */
9namespace Piwik\Plugins\BulkTracking\Tracker;
10
11use Exception;
12use Piwik\Common;
13use Piwik\Tracker\Request;
14use Piwik\Tracker\TrackerConfig;
15
16class Requests
17{
18
19    public function requiresAuthentication()
20    {
21        $requiresAuth = TrackerConfig::getConfigValue('bulk_requests_require_authentication');
22
23        return !empty($requiresAuth);
24    }
25
26    /**
27     * @param Request[] $requests
28     * @throws Exception
29     */
30    public function authenticateRequests($requests)
31    {
32        foreach ($requests as $request) {
33            $this->checkTokenAuthNotEmpty($request->getTokenAuth());
34
35            if (!$request->isAuthenticated()) {
36                $msg = sprintf("token_auth specified does not have Admin permission for idsite=%s", $request->getIdSite());
37                throw new Exception($msg);
38            }
39        }
40    }
41
42    private function checkTokenAuthNotEmpty($token)
43    {
44        if (empty($token)) {
45            throw new Exception("token_auth must be specified when using Bulk Tracking Import. "
46                . " See <a href='https://developer.piwik.org/api-reference/tracking-api'>Tracking Doc</a>");
47        }
48    }
49
50    /**
51     * @return string
52     */
53    public function getRawBulkRequest()
54    {
55        return file_get_contents("php://input");
56    }
57
58    public function isUsingBulkRequest($rawData)
59    {
60        if (!empty($rawData)) {
61            return strpos($rawData, '"requests"') || strpos($rawData, "'requests'");
62        }
63
64        return false;
65    }
66
67    public function getRequestsArrayFromBulkRequest($rawData)
68    {
69        $rawData = trim($rawData);
70        $rawData = Common::sanitizeLineBreaks($rawData);
71
72        // POST data can be array of string URLs or array of arrays w/ visit info
73        $jsonData = json_decode($rawData, $assoc = true);
74
75        $tokenAuth = Common::getRequestVar('token_auth', false, 'string', $jsonData);
76
77        $requests = array();
78        if (isset($jsonData['requests'])) {
79            $requests = $jsonData['requests'];
80        }
81
82        return array($requests, $tokenAuth);
83    }
84
85    public function shouldSendResponse($rawData): bool
86    {
87        $rawData = trim($rawData);
88        $rawData = Common::sanitizeLineBreaks($rawData);
89
90        // POST data can be array of string URLs or array of arrays w/ visit info
91        $jsonData = json_decode($rawData, $assoc = true);
92
93        return !!Common::getRequestVar('send_image', true, 'string', $jsonData);
94    }
95
96    public function initRequestsAndTokenAuth($rawData)
97    {
98        list($requests, $tokenAuth) = $this->getRequestsArrayFromBulkRequest($rawData);
99
100        $validRequests = array();
101
102        if (!empty($requests)) {
103
104            foreach ($requests as $index => $request) {
105                // if a string is sent, we assume its a URL and try to parse it
106                if (is_string($request)) {
107                    $params = array();
108
109                    $url = @parse_url($request);
110                    if (!empty($url['query'])) {
111                        @parse_str($url['query'], $params);
112                        $validRequests[] = new Request($params, $tokenAuth);
113                    }
114                } else {
115                    $validRequests[] = new Request($request, $tokenAuth);
116                }
117            }
118        }
119
120        return array($validRequests, $tokenAuth);
121    }
122}
123