Issues (273)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Model/AliasModel.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This file contains functionality relating to database objects that have a custom URL such as teams and players
4
 *
5
 * @package    BZiON\Models
6
 * @license    https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3
7
 */
8
9
/**
10
 * A Model that has a URL and an alias
11
 * @package    BZiON\Models
12
 */
13
abstract class AliasModel extends UrlModel implements NamedModel
14
{
15
    /**
16
     * The name of the object
17
     * @var string
18
     */
19
    protected $name;
20
21
    /**
22
     * A unique URL-friendly identifier for the object
23
     * @var string
24
     */
25
    protected $alias;
26
27
    /**
28
     * Get the name of the object
29
     * @return string
30
     */
31 76
    public function getName()
32
    {
33 76
        return $this->name;
34
    }
35
36
    /**
37
     * Get the name of the team, safe for use in your HTML
38
     *
39
     * @return string The name of the team
40
     */
41 1
    public function getEscapedName()
42
    {
43 1
        if (!$this->valid) {
44
            return "<em>None</em>";
45
        }
46
47 1
        return $this->escape($this->name);
48
    }
49
50
    /**
51
     * Change the object's name
52
     *
53
     * @return self
54
     */
55
    public function setName($name)
56
    {
57
        $this->updateProperty($this->name, 'name', $name);
58
        $this->resetAlias();
59
60
        return $this;
61
    }
62
63
    /**
64
     * Get an object's alias
65
     * @return string|int The alias (or ID if the alias doesn't exist)
66
     */
67 5
    public function getAlias()
68
    {
69 5
        if ($this->alias !== null && $this->alias != "") {
70 4
            return $this->alias;
71
        }
72
73 1
        return $this->getId();
74
    }
75
76
    /**
77
     * Set a model's alias
78
     * @param  string $alias The new alias
79
     * @return void
80
     */
81
    public function setAlias($alias)
82
    {
83
        $this->updateProperty($this->alias, 'alias', $alias);
84
    }
85
86
    /**
87
     * Reset a model's alias based on its name
88
     * @return self
89
     */
90
    public function resetAlias()
91
    {
92
        $alias = static::generateAlias($this->name, $this->id);
93
94
        return $this->updateProperty($this->alias, 'alias', $alias);
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     *
100
     * @todo Redirect models with wrong alias when bzion.site.url_type === 'permalink'
101
     */
102 1
    public function getURL($action = 'show', $absolute = false, $params = array(), $vanity = false)
103
    {
104 1
        if (!$this->isValid()) {
105
            return "";
106
        }
107
108 1
        $forbiddenAliases = array('edit', 'delete', 'kick', 'invite', 'change-leader', 'matches', 'members');
109
110 1
        if (Service::getParameter('bzion.site.url_type') === 'permalink' && $this instanceof DuplexUrlInterface && !$vanity) {
111
            // Add both the alias and the ID to the URL if the model supports them
112
113
            // Make sure the alias is not forbidden
114 1 View Code Duplication
            if (in_array(strtolower($action), $forbiddenAliases)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
115 1
                $alias = $this->getId();
116
            } else {
117 1
                $alias = $this->alias;
118
            }
119
120
            // Add the alias to the query parameters
121 1
            $params = $params + array('alias' => $alias);
122 1
            $alias = $this->getId();
123 View Code Duplication
        } else {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124 1
            if (in_array(strtolower($action), $forbiddenAliases)) {
125
                $alias = $this->getId();
126
            } else {
127 1
                $alias = $this->getAlias();
128
            }
129
        }
130
131 1
        return $this->getLink($alias, $action, $absolute, $params);
132
    }
133
134
    /**
135
     * Gets an entity from the supplied alias
136
     * @param  string     $alias The object's alias
137
     * @return AliasModel
138
     */
139 24
    public static function fetchFromAlias($alias)
140
    {
141 24
        return static::get(self::fetchIdFrom($alias, "alias"));
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     * @return AliasModel
147
     */
148 3
    public static function fetchFromSlug($slug)
149
    {
150 3
        if (ctype_digit((string) $slug)) {
151
            // Slug is an integer, we can fetch by ID
152 2
            return static::get((int) $slug);
153
        } else {
154
            // Slug is something else, we can fetch by alias
155 2
            return self::fetchFromAlias($slug);
156
        }
157
    }
158
159
    /**
160
     * Generate a URL-friendly unique alias for an object name
161
     *
162
     * @param  string      $name The original object name
163
     * @param  int|null    $id   The ID of the object, if it's being edited and not created
164
     * @return string|null The generated alias, or Null if we couldn't make one
165
     */
166 76
    public static function generateAlias($name, $id = null)
167
    {
168
        // Convert name to lowercase
169 76
        $name = strtolower($name);
170
171
        // List of characters which should be converted to dashes
172 76
        $makeDash = array(' ', '_');
173
174 76
        $name = str_replace($makeDash, '-', $name);
175
176
        // Only keep letters, numbers and dashes - delete everything else
177 76
        $name = preg_replace("/[^a-zA-Z\-0-9]+/", "", $name);
178
179 76
        if (str_replace('-', '', $name) == '') {
180
            // The name only contains symbols or Unicode characters!
181
            // This means we can't convert it to an alias
182 1
            return null;
183
        }
184
185
        // An alias name can't only contain numbers, because it will be
186
        // indistinguishable from an ID. If it does, add a dash in the end.
187
        // Also prevent aliases from taking names such as "new",
188 76
        while (preg_match("/^[0-9]+$/", $name)) {
189 1
            $name = $name . '-';
190
        }
191
192 76
        return self::getUniqueAlias($name, ($id) ?: 0);
193
    }
194
195
    /**
196
     * Make sure that the generated alias provided is unique
197
     *
198
     * @param  string $alias The alias
199
     * @param  int    $id    The ID of the object, if it's being edited and not created
200
     * @return string An alias that is guaranteed to be unique
201
     */
202 76
    private static function getUniqueAlias($alias, $id = 0)
203
    {
204
        // Try to find duplicates
205 76
        $db = Database::getInstance();
206 76
        $result = $db->query("SELECT alias FROM " . static::TABLE . " WHERE id != ? AND alias REGEXP ?", array($id, "^" . $alias . "[0-9]*$"));
207
208
        // Convert the multi-dimensional array that $db->query() gave us into
209
        // a single-dimensional one.
210 76
        $aliases = (is_array($result)) ? array_column($result, 'alias') : array();
211
212
        // If there's already an entry with the alias we generated, put a number
213
        // in the end of it and keep incrementing it until there is we find
214
        // an open spot.
215 76
        $currentAlias = $alias;
216 76
        for ($i = 2;; ++$i) {
217 76
            if (!in_array($currentAlias, $aliases)
218 76
            &&  !in_array($currentAlias, static::getDisallowedAliases())) {
219 76
                break;
220
            }
221
222 2
            $currentAlias = $alias . $i;
223
        }
224
225 76
        return $currentAlias;
226
    }
227
228
    /**
229
     * Get a list of aliases that should not be given to objects
230
     *
231
     * For example, you want to prevent teams from getting the "new" alias.
232
     * Otherwise, the team's link would be http://example.com/bzion/teams/new,
233
     * and the user would go to the team creation page instead of the team's page.
234
     * Disallowed aliases will have a number appended, so the URL would be
235
     * http://example.com/bzion/teams/new2
236
     *
237
     * @return string[]
238
     */
239 76
    protected static function getDisallowedAliases()
240
    {
241 76
        return array('new');
242
    }
243
}
244