SenecaAuthenticatorService::getUrl()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 13
nc 2
nop 2
1
<?php
2
/*
3
  GESTCONV - Aplicación web para la gestión de la convivencia en centros educativos
4
5
  Copyright (C) 2015-2017: Luis Ramón López López
6
7
  This program is free software: you can redistribute it and/or modify
8
  it under the terms of the GNU Affero General Public License as published by
9
  the Free Software Foundation, either version 3 of the License, or
10
  (at your option) any later version.
11
12
  This program is distributed in the hope that it will be useful,
13
  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
  GNU Affero General Public License for more details.
16
17
  You should have received a copy of the GNU Affero General Public License
18
  along with this program.  If not, see [http://www.gnu.org/licenses/].
19
*/
20
21
namespace AppBundle\Service;
22
23
class SenecaAuthenticatorService
24
{
25
    const STATUS_NOT_AVAILABLE = 0;
26
    const STATUS_USER_AUTHENTICATED = 1;
27
    const STATUS_WRONG_USER_OR_PASSWORD = 2;
28
    const STATUS_USER_BLOCKED = 3;
29
30
    /** @var string */
31
    private $url;
32
33
    /** @var boolean */
34
    private $forceSecurity;
35
36
    /** @var boolean */
37
    private $enabled;
38
39
    public function __construct($url, $forceSecurity, $enabled)
40
    {
41
        $this->url = $url;
42
        $this->forceSecurity = $forceSecurity;
43
        $this->enabled = $enabled;
44
    }
45
46
    /**
47
     * @param string $user
48
     * @param string $password
49
     * @return bool
50
     */
51
    public function checkUserCredentials($user, $password)
52
    {
53
        // devolver error si no está habilitado
54
        if (false === $this->enabled) {
55
            return self::STATUS_NOT_AVAILABLE;
56
        }
57
58
        // obtener URL de entrada
59
        $str = $this->getUrl($this->url, $this->forceSecurity);
60
        if (!$str) {
61
            return self::STATUS_NOT_AVAILABLE;
62
        }
63
64
        $dom = new \DOMDocument();
65
        libxml_use_internal_errors(true);
66
        $dom->loadHTML($str);
67
        $xpath = new \DOMXPath($dom);
68
        $form = $xpath->query('//form')->item(0);
69
        $hidden = $xpath->query('//input[@name="N_V_"]')->item(0);
70
71
        if (!$form || !$hidden) {
72
            return self::STATUS_NOT_AVAILABLE;
73
        }
74
75
        // enviar datos del formulario
76
        $postUrl = $form->getAttribute('action');
77
        $hiddenValue = $hidden->getAttribute('value');
78
79
        $fields = array(
80
            'USUARIO' => urlencode($user),
81
            'CLAVE' => urlencode($password),
82
            'N_V_' => urlencode($hiddenValue)
83
        );
84
85
        $str = $this->postToUrl($fields, $postUrl, $this->url, $this->forceSecurity);
86
87
        if (!$str) {
88
            return self::STATUS_NOT_AVAILABLE;
89
        }
90
91
        $dom = new \DOMDocument();
92
        libxml_use_internal_errors(true);
93
        $dom->loadHTML($str);
94
        $xpath = new \DOMXPath($dom);
95
        $nav = $xpath->query('//nav');
96
        $error = $xpath->query('//p[@class="text-danger"]');
97
        $message = $error->length > 0 ? $error->item(0)->firstChild->nodeValue : '';
98
99
        if ($nav->length === 1 && $error->length === 0) {
100
            $result = self::STATUS_USER_AUTHENTICATED;
101
        }
102
        elseif (false !== strpos($message, 'Usuario bloqueado')) {
103
            $result = self::STATUS_USER_BLOCKED;
104
        }
105
        elseif (false !== strpos($message, 'Usuario incorrecto')) {
106
            $result = self::STATUS_WRONG_USER_OR_PASSWORD;
107
        }
108
        else {
109
            $result = self::STATUS_NOT_AVAILABLE;
110
        }
111
        return $result;
112
    }
113
114
    /**
115
     * Get URL contents
116
     *
117
     * @param string $url
118
     * @param boolean $forceSecurity
119
     * @return string
120
     */
121
    private function getUrl($url, $forceSecurity)
122
    {
123
        $curl = curl_init();
124
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $forceSecurity);
125
        curl_setopt($curl, CURLOPT_HEADER, false);
126
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
127
        curl_setopt($curl, CURLOPT_MAXREDIRS, 2);
128
        curl_setopt($curl, CURLOPT_URL, $url);
129
        curl_setopt($curl, CURLOPT_REFERER, $url);
130
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
131
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.125 Safari/533.4");
132
        $str = curl_exec($curl);
133
        curl_close($curl);
134
        return $str === false ? '' : (string) $str;
135
    }
136
137
    /**
138
     * Gets the content after POSTing into an URL
139
     *
140
     * @param array $fields
141
     * @param string $postUrl
142
     * @param string $refererUrl
143
     * @param boolean $forceSecurity
144
     * @return string
145
     */
146
    private function postToUrl($fields, $postUrl, $refererUrl, $forceSecurity)
147
    {
148
        $fieldsString = '';
149
        foreach ($fields as $key => $value) {
150
            $fieldsString .= $key.'='.$value.'&';
151
        }
152
        $fieldsString = rtrim($fieldsString, '&');
153
154
        $curl = curl_init();
155
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $forceSecurity);
156
        curl_setopt($curl, CURLOPT_HEADER, false);
157
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
158
        curl_setopt($curl, CURLOPT_URL, $postUrl);
159
        curl_setopt($curl, CURLOPT_REFERER, $refererUrl);
160
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
161
        curl_setopt($curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) Chrome/5.0.375.125 Safari/533.4");
162
        curl_setopt($curl, CURLOPT_POST, count($fields));
163
        curl_setopt($curl, CURLOPT_POSTFIELDS, $fieldsString);
164
        $str = curl_exec($curl);
165
        curl_close($curl);
166
        return $str === false ? '' : (string) $str;
167
    }
168
}
169