Issues (287)

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/AnimeCollection.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 declare(strict_types=1);
2
/**
3
 * Anime List Client
4
 *
5
 * An API client for Kitsu and MyAnimeList to manage anime and manga watch lists
6
 *
7
 * PHP version 7
8
 *
9
 * @package     AnimeListClient
10
 * @author      Timothy J. Warren <[email protected]>
11
 * @copyright   2015 - 2017  Timothy J. Warren
12
 * @license     http://www.opensource.org/licenses/mit-license.html  MIT License
13
 * @version     4.0
14
 * @link        https://github.com/timw4mail/HummingBirdAnimeClient
15
 */
16
17
namespace Aviat\AnimeClient\Model;
18
19
use Aviat\AnimeClient\API\Kitsu;
20
use Aviat\Ion\Di\ContainerInterface;
21
use Aviat\Ion\Json;
22
use PDO;
23
24
/**
25
 * Model for getting anime collection data
26
 */
27
class AnimeCollection extends Collection {
28
29
	/**
30
	 * Get collection from the database, and organize by media type
31
	 *
32
	 * @return array
33
	 */
34
	public function get_collection()
35
	{
36
		$raw_collection = $this->_get_collection();
37
38
		$collection = [];
39
40
		foreach ($raw_collection as $row)
41
		{
42
			if (array_key_exists($row['media'], $collection))
43
			{
44
				$collection[$row['media']][] = $row;
45
			}
46
			else
47
			{
48
				$collection[$row['media']] = [$row];
49
			}
50
		}
51
52
		return $collection;
53
	}
54
55
	/**
56
	 * Get list of media types
57
	 *
58
	 * @return array
59
	 */
60
	public function get_media_type_list()
61
	{
62
		$output = [];
63
64
		$query = $this->db->select('id, type')
65
			->from('media')
66
			->get();
67
68
		foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row)
69
		{
70
			$output[$row['id']] = $row['type'];
71
		}
72
73
		return $output;
74
	}
75
76
	/**
77
	 * Get item from collection for editing
78
	 *
79
	 * @param int $id
80
	 * @return array
81
	 */
82
	public function get_collection_entry($id)
83
	{
84
		$query = $this->db->from('anime_set')
85
			->where('hummingbird_id', (int)$id)
86
			->get();
87
88
		return $query->fetch(PDO::FETCH_ASSOC);
89
	}
90
91
	/**
92
	 * Get full collection from the database
93
	 *
94
	 * @return array
95
	 */
96
	private function _get_collection()
97
	{
98
		if ( ! $this->valid_database)
99
		{
100
			return [];
101
		}
102
103
		$query = $this->db->select('hummingbird_id, slug, title, alternate_title, show_type,
104
			 age_rating, episode_count, episode_length, cover_image, notes, media.type as media')
105
			->from('anime_set a')
106
			->join('media', 'media.id=a.media_id', 'inner')
107
			->order_by('media')
108
			->order_by('title')
109
			->get();
110
111
		return $query->fetchAll(PDO::FETCH_ASSOC);
112
	}
113
114
	/**
115
	 * Add an item to the anime collection
116
	 *
117
	 * @param array $data
118
	 * @return void
119
	 */
120
	public function add($data)
121
	{
122
		$anime = (object)$this->anime_model->getAnimeById($data['id']);
123
		$util = $this->container->get('util');
0 ignored issues
show
$util is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
124
125
		$this->db->set([
126
			'hummingbird_id' => $data['id'],
127
			'slug' => $anime->slug,
128
			'title' => array_shift($anime->titles),
129
			'alternate_title' => implode('<br />', $anime->titles),
130
			'show_type' => $anime->show_type,
131
			'age_rating' => $anime->age_rating,
132
			'cover_image' => $anime->cover_image,
133
			'episode_count' => $anime->episode_count,
134
			'episode_length' => $anime->episode_length,
135
			'media_id' => $data['media_id'],
136
			'notes' => $data['notes']
137
		])->insert('anime_set');
138
139
		$this->update_genre($data['id']);
140
	}
141
142
	/**
143
	 * Update a collection item
144
	 *
145
	 * @param array $data
146
	 * @return void
147
	 */
148
	public function update($data)
149
	{
150
		// If there's no id to update, don't update
151
		if ( ! array_key_exists('hummingbird_id', $data))
152
		{
153
			return;
154
		}
155
156
		$id = $data['hummingbird_id'];
157
		unset($data['hummingbird_id']);
158
159
		$this->db->set($data)
160
			->where('hummingbird_id', $id)
161
			->update('anime_set');
162
	}
163
164
	/**
165
	 * Remove a collection item
166
	 *
167
	 * @param  array $data
168
	 * @return void
169
	 */
170
	public function delete($data)
171
	{
172
		// If there's no id to update, don't delete
173
		if ( ! array_key_exists('hummingbird_id', $data))
174
		{
175
			return;
176
		}
177
178
		$this->db->where('hummingbird_id', $data['hummingbird_id'])
179
			->delete('genre_anime_set_link');
180
181
		$this->db->where('hummingbird_id', $data['hummingbird_id'])
182
			->delete('anime_set');
183
	}
184
185
	/**
186
	 * Get the details of a collection item
187
	 *
188
	 * @param int $hummingbird_id
189
	 * @return array
190
	 */
191
	public function get($hummingbird_id)
192
	{
193
		$query = $this->db->from('anime_set')
194
			->where('hummingbird_id', $hummingbird_id)
195
			->get();
196
197
		return $query->fetch(PDO::FETCH_ASSOC);
198
	}
199
200
	/**
201
	 * Update genre information for selected anime
202
	 *
203
	 * @param int $anime_id The current anime
204
	 * @return void
205
	 */
206
	private function update_genre($anime_id)
207
	{
208
		$genre_info = $this->get_genre_data();
209
		extract($genre_info);
210
211
		// Get api information
212
		$anime = $this->anime_model->getAnimeById($anime_id);
213
214
		foreach ($anime['genres'] as $genre)
215
		{
216
			// Add genres that don't currently exist
217
			if ( ! in_array($genre, $genres))
218
			{
219
				$this->db->set('genre', $genre)
220
					->insert('genres');
221
222
				$genres[] = $genre;
223
			}
224
225
			// Update link table
226
			// Get id of genre to put in link table
227
			$flipped_genres = array_flip($genres);
228
229
			$insert_array = [
230
				'hummingbird_id' => $anime_id,
231
				'genre_id' => $flipped_genres[$genre]
232
			];
233
234
			if (array_key_exists($anime_id, $links))
235
			{
236
				if ( ! in_array($flipped_genres[$genre], $links[$anime_id]))
237
				{
238
					$this->db->set($insert_array)->insert('genre_anime_set_link');
239
				}
240
			}
241
			else
242
			{
243
				$this->db->set($insert_array)->insert('genre_anime_set_link');
244
			}
245
		}
246
	}
247
248
	/**
249
	 * Get list of existing genres
250
	 *
251
	 * @return array
252
	 */
253
	private function get_genre_data()
254
	{
255
		$genres = [];
256
		$links = [];
257
258
		// Get existing genres
259
		$query = $this->db->select('id, genre')
260
			->from('genres')
261
			->get();
262
		foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $genre)
263
		{
264
			$genres[$genre['id']] = $genre['genre'];
265
		}
266
267
		// Get existing link table entries
268
		$query = $this->db->select('hummingbird_id, genre_id')
269
			->from('genre_anime_set_link')
270
			->get();
271
		foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $link)
272
		{
273
			if (array_key_exists($link['hummingbird_id'], $links))
274
			{
275
				$links[$link['hummingbird_id']][] = $link['genre_id'];
276
			}
277
			else
278
			{
279
				$links[$link['hummingbird_id']] = [$link['genre_id']];
280
			}
281
		}
282
283
		return [
284
			'genres' => $genres,
285
			'links' => $links
286
		];
287
	}
288
289
	/**
290
	 * Update genre information for the entire collection
291
	 *
292
	 * @return void
293
	 */
294
	private function update_genres()
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
295
	{
296
		// Get the anime collection
297
		$collection = $this->_get_collection();
298
		foreach ($collection as $anime)
299
		{
300
			// Get api information
301
			$this->update_genre($anime['hummingbird_id']);
302
		}
303
	}
304
}
305
// End of AnimeCollectionModel.php