Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
8 / 8
CRAP
100.00% covered (success)
100.00%
1 / 1
File
100.00% covered (success)
100.00%
41 / 41
100.00% covered (success)
100.00%
8 / 8
23
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getFilename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getRealm
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDelimiter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFilename
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 setRealm
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 setDelimiter
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 authenticate
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
13
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Auth;
16
17/**
18 * File auth class
19 *
20 * @category   Pop
21 * @package    Pop\Auth
22 * @author     Nick Sagona, III <nick@popphp.org>
23 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
24 * @license    https://www.popphp.org/license     New BSD License
25 * @version    5.0.0
26 */
27class File extends AbstractAuth
28{
29
30    /**
31     * Auth file
32     * @var ?string
33     */
34    protected ?string $filename = null;
35
36    /**
37     * Auth realm
38     * @var ?string
39     */
40    protected ?string $realm = null;
41
42    /**
43     * Auth file delimiter
44     * @var string
45     */
46    protected string $delimiter = ':';
47
48    /**
49     * Constructor
50     *
51     * Instantiate the File auth adapter object
52     *
53     * @param  string  $filename
54     * @param  ?string $realm
55     * @param  string  $delimiter
56     * @throws Exception
57     */
58    public function __construct(string $filename, ?string $realm = null, string $delimiter = ':')
59    {
60        $this->setFilename($filename);
61        if (!empty($realm)) {
62            $this->setRealm($realm);
63        }
64        if (!empty($delimiter)) {
65            $this->setDelimiter($delimiter);
66        }
67    }
68
69    /**
70     * Get the auth filename
71     *
72     * @return string
73     */
74    public function getFilename(): string
75    {
76        return $this->filename;
77    }
78
79    /**
80     * Get the auth realm
81     *
82     * @return ?string
83     */
84    public function getRealm(): ?string
85    {
86        return $this->realm;
87    }
88
89    /**
90     * Get the auth file delimiter
91     *
92     * @return string
93     */
94    public function getDelimiter(): string
95    {
96        return $this->delimiter;
97    }
98
99    /**
100     * Set the auth filename
101     *
102     * @param  string $filename
103     * @throws Exception
104     * @return File
105     */
106    public function setFilename(string $filename): File
107    {
108        if (!file_exists($filename)) {
109            throw new Exception("The access file '" . $filename . "' does not exist.");
110        }
111        $this->filename = $filename;
112        return $this;
113    }
114
115    /**
116     * Set the auth realm
117     *
118     * @param  string $realm
119     * @return File
120     */
121    public function setRealm(string $realm): File
122    {
123        $this->realm = $realm;
124        return $this;
125    }
126
127    /**
128     * Set the auth file delimiter
129     *
130     * @param  string $delimiter
131     * @return File
132     */
133    public function setDelimiter(string $delimiter): File
134    {
135        $this->delimiter = $delimiter;
136        return $this;
137    }
138
139    /**
140     * Method to authenticate
141     *
142     * @param  string  $username
143     * @param  ?string $password
144     * @throws Exception
145     * @return int
146     */
147    public function authenticate(string $username, ?string $password = null): int
148    {
149        $this->setUsername($username);
150
151        $this->result      = 0;
152        $this->needsRehash = false;
153
154        if ($password === null) {
155            return $this->result;
156        }
157
158        $this->setPassword($password);
159
160        $lines = @file($this->filename);
161
162        if ($lines === false) {
163            throw new Exception("The access file '" . $this->filename . "' could not be read.");
164        }
165
166        $hash = null;
167
168        foreach ($lines as $line) {
169            $line = trim($line);
170            $user = explode($this->delimiter, $line);
171            if ($user[0] == $this->username) {
172                if (($this->realm !== null) && (count($user) == 3)) {
173                    if (($this->username == $user[0]) && ($user[1] == $this->realm)) {
174                        $hash = $user[2];
175                        break;
176                    }
177                } else if (count($user) == 2) {
178                    if ($this->username == $user[0]) {
179                        $hash = $user[1];
180                        break;
181                    }
182                }
183            }
184        }
185
186        if (($this->password !== null) && ($hash !== null)) {
187            $this->result = (int)$this->verify($this->password, $hash);
188        }
189
190        return $this->result;
191    }
192
193}