Passed
Push — master ( 1b743f...79d769 )
by Nicolaas
02:00
created

CheckAllTemplatesResponseController::getTestUser()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 35
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 28
c 1
b 0
f 0
nc 7
nop 0
dl 0
loc 35
rs 9.1608
1
<?php
2
3
namespace Sunnysideup\TemplateOverview\Control;
4
5
use ReflectionClass;
6
use ReflectionMethod;
7
use Psr\SimpleCache\CacheInterface;
8
9
use Sunnysideup\TemplateOverview\Api\SiteTreeDetails;
10
use Sunnysideup\TemplateOverview\Api\AllLinks;
11
use Sunnysideup\TemplateOverview\Api\W3cValidateApi;
12
use Sunnysideup\TemplateOverview\Api\DiffMachine;
13
14
15
use SilverStripe\Control\Director;
16
use SilverStripe\Core\Convert;
17
use SilverStripe\Security\Member;
18
use SilverStripe\Security\Group;
19
use SilverStripe\Core\Injector\Injector;
20
use SilverStripe\CMS\Model\SiteTree;
21
use SilverStripe\Core\ClassInfo;
22
use SilverStripe\Core\Flushable;
23
use SilverStripe\Admin\ModelAdmin;
24
use SilverStripe\Admin\CMSMenu;
25
use SilverStripe\ORM\ArrayList;
26
use SilverStripe\ORM\DataObject;
27
use SilverStripe\ORM\DB;
28
use SilverStripe\Control\Controller;
29
use SilverStripe\Control\HTTPApplication;
30
use SilverStripe\Control\HTTPRequestBuilder;
31
use SilverStripe\Core\Manifest\ClassLoader;
32
use SilverStripe\Dev\SapphireTest;
33
use SilverStripe\Dev\BuildTask;
34
use SilverStripe\Dev\TaskRunner;
35
use SilverStripe\Core\Config\Config;
36
use SilverStripe\Core\CoreKernel;
37
use SilverStripe\Core\Startup\ErrorControlChainMiddleware;
38
use SilverStripe\Versioned\Versioned;
39
use SilverStripe\View\ArrayData;
40
use SilverStripe\View\Requirements;
41
use SilverStripe\View\SSViewer;
42
43
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
44
use SilverStripe\Security\DefaultAdminService;
45
use SilverStripe\Security\Permission;
46
47
use GuzzleHttp\Cookie\CookieJar;
48
use GuzzleHttp\Client;
49
use GuzzleHttp\Exception\RequestException;
50
use GuzzleHttp\Psr7;
51
52
/**
53
 * @description (see $this->description)
54
 *
55
 * @authors: Andrew Pett [at] sunny side up .co.nz, Nicolaas [at] Sunny Side Up .co.nz
56
 * @package: templateoverview
57
 * @sub-package: tasks
58
 **/
59
60
class CheckAllTemplatesResponseController extends Controller implements Flushable
61
{
62
63
    /**
64
     * Defines methods that can be called directly
65
     * @var array
66
     */
67
    private static $allowed_actions = [
68
        'testone' => 'ADMIN',
69
    ];
70
71
    public static function flush()
72
    {
73
        $cache = Injector::inst()->get(CacheInterface::class . '.templateoverview');
74
        $cache->clear();
75
    }
76
77
    private static $use_default_admin = true;
78
79
    private static $username = '';
80
81
    private static $password = '';
82
83
    private static $url_segment = 'templateoverviewsmoketestresponse';
84
85
    private static $use_w3_validation = false;
86
87
    private static $create_diff = false;
88
89
    public static function get_user_email()
90
    {
91
        $userName = Config::inst()->get(CheckAllTemplatesResponseController::class, 'username');
92
        if (! $userName) {
93
            if (Config::inst()->get(CheckAllTemplatesResponseController::class, 'use_default_admin')) {
94
                $userName = DefaultAdminService::getDefaultAdminUsername();
95
            } else {
96
                $userName = '[email protected]';
97
            }
98
        }
99
100
        return $userName;
101
    }
102
103
    public static function get_password()
104
    {
105
        $password = Config::inst()->get(CheckAllTemplatesResponseController::class, 'password');
106
        if (! $password) {
107
            if (Config::inst()->get(CheckAllTemplatesResponseController::class, 'use_default_admin')) {
108
                $password = DefaultAdminService::getDefaultAdminPassword();
109
            } else {
110
                $cache = Injector::inst()->get(CacheInterface::class . '.templateoverview');
111
                if (! $cache->has('password')) {
112
                    $password = strtolower('aa'.substr(uniqid(), 0, 8)).'_.,'.strtoupper('BB'.substr(uniqid(), 0, 8));
113
                    $cache->set('password', $password);
114
                }
115
                $password = $cache->get('password');
116
            }
117
        }
118
119
        return $password;
120
    }
121
122
    public static function get_test_user()
123
    {
124
        return Injector::inst()->get(CheckAllTemplatesResponseController::class)->getTestUser();
125
    }
126
127
128
    private $guzzleCookieJar = null;
129
130
    private $guzzleClient = null;
131
132
    private $guzzleHasError = false;
133
134
    private $isSuccess = false;
135
136
137
    /**
138
     * temporary Admin used to log in.
139
     * @var Member
140
     */
141
    private $member = null;
142
143
    private $rawResponse = '';
144
145
    /**
146
     * @var Boolean
147
     */
148
    private $debug = false;
149
150
151
    /**
152
     * Main function
153
     * has two streams:
154
     * 1. check on url specified in GET variable.
155
     * 2. create a list of urls to check
156
     *
157
     * @param HTTPRequest
158
     */
159
    public function testone($request)
160
    {
161
        $isCMSLink = $request->getVar('iscmslink') ? true : false;
162
        $testURL = $request->getVar('test') ? : null;
163
164
        // 1. actually test a URL and return the data
165
        if ($testURL) {
166
            $this->guzzleSetup();
167
            $this->getTestUser();
168
            $content = $this->testURL($testURL);
169
            $this->deleteUser();
170
            $this->cleanup();
171
            print $content;
172
            if(! Director::is_ajax()) {
173
                ;
174
                $diff =  '';
175
                $comparisonBaseURL = Config::inst()->get(CheckAllTemplatesResponseController::class, 'comparision_base_url');
176
                $width = '98%';
177
                $style = 'border: none;';
178
                if($comparisonBaseURL) {
179
                    $width = '48%';
180
                    $style = 'float: left;';
181
                    if($this->isSuccess && !$isCMSLink && $this->Config()->create_diff) {
182
                        $otherURL = $comparisonBaseURL . $testURL;
183
                        $testContent = str_replace(Director::absoluteBaseURL(), $comparisonBaseURL, $this->rawResponse);
184
                        $rawResponseOtherSite = @file_get_contents($otherURL);
185
                        $diff = DiffMachine::compare(
186
                            $testContent,
187
                            $rawResponseOtherSite
188
                        );
189
                        $rawResponseOtherSite = Convert::raw2htmlatt(str_replace('\'', '\\\'', $rawResponseOtherSite));
190
                        $diff = '
191
                        <iframe id="iframe2" width="'.$width.'%" height="7000" srcdoc=\''.$rawResponseOtherSite.'\' style="float: right;"></iframe>
192
193
                        <hr style="clear: both; margin-top: 20px; padding-top: 20px;" />
194
                        <h1>Diff</h1>
195
                        <link href="/resources/vendor/sunnysideup/templateoverview/client/css/checkalltemplates.css" rel="stylesheet" type="text/css" />
196
                        '.$diff;
197
                    }
198
                }
199
                $rawResponse = Convert::raw2htmlatt(str_replace('\'', '\\\'', $this->rawResponse));
200
                echo '
201
                    <h1>Response</h1>
202
                    <iframe id="iframe" width="'.$width.'%" height="7000" srcdoc=\''.$rawResponse.'\' style="'.$style.'"></iframe>
203
                ';
204
                echo $diff;
205
            }
206
            return;
207
        } else {
208
            user_error('no test url provided.');
209
        }
210
211
    }
212
213
    /**
214
     * ECHOES the result of testing the URL....
215
     * @param String $url
216
     */
217
    private function testURL($url)
218
    {
219
        if (strlen(trim($url)) < 1) {
220
            user_error("empty url"); //Checks for empty strings.
221
        }
222
        if (AllLinks::is_admin_link($url)) {
223
            $validate = false;
224
        } else {
225
            $validate = Config::inst()->get(CheckAllTemplatesResponseController::class, 'use_w3_validation');
226
        }
227
        $testURL = Director::absoluteURL('/templateoverviewloginandredirect/login/?BackURL=');
228
        $testURL .= urlencode($url);
229
        $this->guzzleSetup();
230
231
        $start = microtime(true);
232
        $response = $this->guzzleSendRequest($testURL);
233
        $end = microtime(true);
234
235
        $data = [
236
            'status' => 'success',
237
            'httpResponse' => '200',
238
            'content' => '',
239
            'responseTime' => round($end - $start, 4),
240
            'w3Content' => '',
241
        ];
242
243
        $httpResponse = $response->getStatusCode();
244
        $error = $response->getReasonPhrase();
245
        if ($this->guzzleHasError) {
246
            //we already have the body ...
247
        } else {
248
            $this->rawResponse = $response->getBody();
249
        }
250
251
        $data['httpResponse'] = $httpResponse;
252
253
        if ($httpResponse === 401) {
254
            $data['status'] = 'error';
255
            $data['content'] = 'Could not access: ' . $url;
256
257
            return json_encode($data);
258
        }
259
260
        //uncaught errors ...
261
        if ($this->rawResponse && substr($this->rawResponse, 0, 12) == "Fatal error") {
262
            $data['status'] = 'error';
263
            $data['content'] = $this->rawResponse;
264
        } elseif ($httpResponse == 200 && $this->rawResponse && strlen($this->rawResponse) < 500) {
265
            $data['status'] = 'error';
266
            $data['content'] = 'SHORT RESPONSE: ' . $this->rawResponse;
267
        }
268
269
        $data['w3Content'] = 'n/a';
270
271
        if ($httpResponse != 200) {
272
            $data['status'] = 'error';
273
            $data['content'] .= 'unexpected response: ' . $error . $this->rawResponse;
274
        } else {
275
            $this->isSuccess = true;
276
            if ($validate) {
277
                $w3Obj = new W3cValidateApi();
278
                $data['w3Content'] = $w3Obj->W3Validate("", $this->rawResponse);
279
            }
280
        }
281
282
        if (Director::is_ajax()) {
283
            return json_encode($data);
284
        }
285
        $content = '';
286
        $content .= '<p><strong>URL:</strong> ' . $url . '</p>';
287
        $content .= '<p><strong>Status:</strong> ' . $data['status'] . '</p>';
288
        $content .= '<p><strong>HTTP response:</strong> ' . $data['httpResponse'] . '</p>';
289
        $content .= '<p><strong>Content:</strong> ' . htmlspecialchars($data['content']) . '</p>';
290
        $content .= '<p><strong>Response time:</strong> ' . $data['responseTime'] . '</p>';
291
        $content .= '<p><strong>W3 Content:</strong> ' . $data['w3Content'] . '</p>';
292
293
        return $content;
294
    }
295
296
297
    /**
298
     * creates the basic curl
299
     *
300
     */
301
    private function guzzleSetup()
302
    {
303
        // $user_agent='Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0';
304
        // $post = $type == "GET" ? false : true;
305
        //
306
        // $strCookie = 'PHPSESSID=' . session_id() . '; path=/';
307
        // $options = array(
308
        //     CURLOPT_CUSTOMREQUEST  => $type,        //set request type post or get
309
        //     CURLOPT_POST           => $post,        //set to GET
310
        //     CURLOPT_USERAGENT      => $user_agent, //set user agent
311
        //     CURLOPT_COOKIE         => $strCookie, //set cookie file
312
        //     CURLOPT_COOKIEFILE     => "cookie.txt", //set cookie file
313
        //     CURLOPT_COOKIEJAR      => "cookie.txt", //set cookie jar
314
        //     CURLOPT_RETURNTRANSFER => true,     // return web page
315
        //     CURLOPT_HEADER         => false,    // don't return headers
316
        //     CURLOPT_FOLLOWLOCATION => true,     // follow redirects
317
        //     CURLOPT_ENCODING       => "",       // handle all encodings
318
        //     CURLOPT_AUTOREFERER    => true,     // set referer on redirect
319
        //     CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
320
        //     CURLOPT_TIMEOUT        => 120,      // timeout on response
321
        //     CURLOPT_MAXREDIRS      => 10,       // stop after 10 redirects
322
        // );
323
        //
324
        // $this->ch = curl_init();
325
        //
326
        // curl_setopt_array($this->ch, $options);
327
328
        $this->guzzleCookieJar = new CookieJar();
329
        $this->guzzleClient = new Client(
330
            [
331
                'base_uri' => Director::baseURL(),
332
                'cookies' => true,
333
            ]
334
        );
335
    }
336
337
    /**
338
     *
339
     * @return
340
     */
341
    protected function guzzleSendRequest($url)
342
    {
343
        $this->guzzleHasError = false;
344
        $credentials = base64_encode(self::get_user_email().':'.self::get_password());
345
        try {
346
            $response = $this->guzzleClient->request(
347
                'GET',
348
                $url,
349
                [
350
                    'cookies' => $this->guzzleCookieJar,
351
                    'headers' => [
352
                        'PHP_AUTH_USER' => self::get_user_email(),
353
                        'PHP_AUTH_PW' => self::get_password(),
354
                    ],
355
                    'auth' => [
356
                        self::get_user_email(),
357
                        self::get_password(),
358
                    ],
359
                    'Authorization' => ['Basic '.$credentials],
360
                ]
361
            );
362
        } catch (RequestException $exception) {
363
            $this->rawResponse = $exception->getResponse();
364
            $this->guzzleHasError = true;
365
            //echo Psr7\str($exception->getRequest());
366
            if ($exception->hasResponse()) {
367
                $response = $exception->getResponse();
368
                $this->rawResponse = $exception->getResponseBodySummary($response);
369
            } else {
370
                $response = null;
371
            }
372
        }
373
        return $response;
374
    }
375
376
377
378
    /**
379
     *
380
     */
381
    public function getTestUser()
382
    {
383
        if (Config::inst()->get(CheckAllTemplatesResponseController::class, 'use_default_admin')) {
384
            $this->member = Injector::inst()->get(DefaultAdminService::class)->findOrCreateDefaultAdmin();
385
            return $this->member;
386
        } else {
387
            //Make temporary admin member
388
            $filter = ["Email" => self::get_user_email()];
389
            $this->member = Member::get()
390
                ->filter($filter)
391
                ->first();
392
            if ($this->member) {
393
            } else {
394
                $this->member = Member::create($filter);
395
            }
396
            $this->member->Password = self::get_password();
397
            $this->member->LockedOutUntil = null;
398
            $this->member->FirstName = 'Test';
399
            $this->member->Surname = 'User';
400
            $this->member->write();
401
            $auth = new MemberAuthenticator();
402
            $result = $auth->checkPassword($this->member, self::get_password());
403
            if (! $result->isValid()) {
404
                user_error('Error in creating test user.', E_USER_ERROR);
405
                return;
406
            }
407
            $service = Injector::inst()->get(DefaultAdminService::class);
408
            $adminGroup = $service->findOrCreateAdminGroup();
409
            $this->member->Groups()->add($adminGroup);
410
            if (Permission::checkMember($this->member, 'ADMIN')) {
411
                user_error("No admin group exists", E_USER_ERROR);
412
                return;
413
            }
414
415
            return $this->member;
416
        }
417
    }
418
419
420
    private function deleteUser()
421
    {
422
        if (Config::inst()->get(CheckAllTemplatesResponseController::class, 'use_default_admin')) {
423
            //do nothing;
424
        } else {
425
            if ($this->member) {
426
                $this->member->delete();
427
            }
428
        }
429
    }
430
431
432
    /**
433
     * cleans up the curl connection.
434
     *
435
     */
436
    private function cleanup()
437
    {
438
    }
439
440
441
442
    // private function debugme($lineNumber, $variable = "")
443
    // {
444
    //     if ($this->debug) {
445
    //         echo "<br />" . $lineNumber . ": " . round(memory_get_usage() / 1048576) . "MB" . "=====" . print_r($variable, 1);
446
    //         ob_flush();
447
    //         flush();
448
    //     }
449
    // }
450
}
451