Issues (93)

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.

application/controllers/Bbs.php (13 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
 * 
4
 */
5
6
/**
7
 * @property CI_DB_query_builder $db
8
 * @property CI_User_agent $agent
9
 * @property CI_Pagination $pagination
10
 * @property CI_Form_validation $form_validation
11
 * @property CI_Input $input
12
 * @property CI_Config $config
13
 */
14
class Bbs extends CI_Controller {
15
16
# 記事表示ページで、1ページに表示する記事の件数を設定します。
17
	public $limit = 5;
18
19
	public function __construct()
20
	{
21
		parent::__construct();
22
		$this->load->helper(['form', 'url']);
23
# データベースを使うため、データベースクラスをロードします。
24
		$this->load->database();
25
26
		//$this->output->enable_profiler(TRUE);
27
	}
28
29
	// 日付順に記事を表示
30
	public function index($offset = '')
31
	{
32
# 引数から$offsetに値が渡されます。これは、3番目のURIセグメントの値です。
33
# ユーザが変更可能なデータですので、int型へ変換し、必ず整数値にします。
34
		$offset = (int) $offset;
35
36
# 新しい記事ID順に、limit値とoffset値を指定し、bbsテーブルから記事データ
37
# (オブジェクト)を取得し、$data['query']に代入します。order_by()メソッドは、
38
# フィールド名とソート順を引数にとり、ORDER BY句を指定します。
39
		$this->db->order_by('id', 'desc');
40
		$data = [];
41
		$data['query'] = $this->db->get('bbs', $this->limit, $offset);
42
43
# ページネーションを生成します。
44
		$this->load->library('pagination');
45
		$config = [];
46
		$config['base_url'] = $this->config->site_url('/bbs/index/');
47
# 記事の総件数をbbsテーブルから取得します。count_all()メソッドは、テーブル名
48
# を引数にとり、そのテーブルのレコード数を返します。
49
		$config['total_rows'] = $this->db->count_all('bbs');
50
		$config['per_page'] = $this->limit;
51
		$config['first_link']      = '&laquo;最初';
52
		$config['last_link']       = '最後&raquo;';
53
		$config['num_tag_open']    = ' ';
54
		$config['num_tag_close']   = ' ';
55
		$config['last_tag_open']   = ' ';
56
		$config['last_tag_close']  = ' ';
57
		$config['first_tag_open']  = ' ';
58
		$config['first_tag_close'] = ' ';
59
# 携帯端末かどうかを判定し、ページネーションの前後に挿入するタグを変更します。
60
		if ($this->agent->is_mobile())
61
		{
62
			$config['full_tag_open']  = '<tr><td bgcolor="#EEEEEE">';
63
			$config['full_tag_close'] = '</td></tr>';
64
		}
65
		else
66
		{
67
			$config['full_tag_open']  = '<p class="pagination">';
68
			$config['full_tag_close'] = '</p>';
69
		}
70
		$this->pagination->initialize($config);
71
		$data['pagination'] = $this->pagination->create_links();
72
73
# _load_view()メソッドは、携帯端末かどうかで、読み込むビューファイルを
74
# 切り替えするためのメソッドです。
75
		$this->_load_view('bbs_show', $data);
0 ignored issues
show
$data is of type array<string,object<CI_D..."pagination":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
76
	}
77
78
	// 新規投稿ページ
79
	public function post()
80
	{
81
# バリデーションを設定し、新規投稿ページを表示します。実際の処理は、他でも
82
# 使いますので、プライベートメソッドにしています。
83
		$this->_set_validation();
84
		$this->_show_post_page();
85
	}
86
87
	// 確認ページ
88 View Code Duplication
	public function confirm()
0 ignored issues
show
This method seems to be duplicated in 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...
89
	{
90
# 検証ルールを設定します。
91
		$this->_set_validation();
92
93
# 検証をパスしなかった場合は、新規投稿ページを表示します。検証をパスした場合
94
# は、投稿確認ページ(bbs_confirm)を表示します。
95
		if ($this->form_validation->run() == FALSE)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
96
		{
97
# 投稿されたIDのキャプチャを削除します。
98
			$this->_delete_captcha_data();
99
100
			$this->_show_post_page();
101
		}
102
		else
103
		{
104
			$data = [];
105
			$data['name']       = $this->input->post('name');
106
			$data['email']      = $this->input->post('email');
107
			$data['subject']    = $this->input->post('subject');
108
			$data['body']       = $this->input->post('body');
109
			$data['password']   = $this->input->post('password');
110
			$data['key']        = $this->input->post('key');
111
			$data['captcha']    = $this->input->post('captcha');
112
			$this->_load_view('bbs_confirm', $data);
0 ignored issues
show
$data is of type array<string,*,{"captcha":"*"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
113
		}
114
	}
115
116
# 投稿されたIDのキャプチャを削除します。
117
	private function _delete_captcha_data()
118
	{
119
		$this->db->delete('captcha', ['captcha_id' => $this->input->post('key')]);
0 ignored issues
show
array('captcha_id' => $this->input->post('key')) is of type array<string,*,{"captcha_id":"*"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
120
	}
121
122
# 新規投稿ページを表示します。
123
	private function _show_post_page()
124
	{
125
# 画像キャプチャを生成します。ランダムな文字列を生成するために文字列ヘルパーを
126
# ロードし、キャプチャプラグインをロードします。
127
		$this->load->helper('string');
128
		$this->load->helper('captcha');
129
# 画像キャプチャ生成に必要な設定をします。文字列ヘルパーのrandom_string()
130
# メソッドを使い、ランダムな4桁の数字を取得します。
131
		$vals = [
132
					'word'      => random_string('numeric', 4),
133
					'img_path'  => FCPATH . 'captcha/',
134
					'img_url'   => base_url() . 'captcha/'
135
				];
136
		$cap = create_captcha($vals);
137
		$data = [
138
					'captcha_id'   => '',
139
					'captcha_time' => $cap['time'],
140
					'word'         => $cap['word'],
141
				];
142
# 生成したキャプチャの情報をcaptchaテーブルに登録します。
143
		$this->db->insert('captcha', $data);
144
# 登録時に付けられたキャプチャのID番号を取得します。
145
		$key = $this->db->insert_id();
0 ignored issues
show
The method insert_id() does not exist on CI_DB_query_builder. Did you maybe mean insert()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
146
147
		$data['image']      = $cap['image'];
148
		$data['key']        = $key;
149
		$data['name']       = $this->input->post('name');
150
		$data['email']      = $this->input->post('email');
151
		$data['subject']    = $this->input->post('subject');
152
		$data['body']       = $this->input->post('body');
153
		$data['password']   = $this->input->post('password');
154
		$this->_load_view('bbs_post', $data);
0 ignored issues
show
$data is of type array<string,*,{"password":"*"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
155
	}
156
157
	// 削除ページ
158
	public function delete($id = '')
159
	{
160
# 第1引数、つまり、3番目のURIセグメントのデータをint型に変換します。
161
		$id = (int) $id;
162
# POSTされたpasswordフィールドの値を$passwordに代入します。
163
		$password = $this->input->post('password');
164
# POSTされたdeleteフィールドの値を$deleteに代入します。この値が
165
# 1の場合は、削除を実行します。1以外は、削除の確認ページを表示します。
166
		$delete = (int) $this->input->post('delete');
167
168
# 削除パスワードが入力されていない場合は、エラーページを表示します。
169
		if ($password == '')
170
		{
171
			$this->_load_view('bbs_delete_error');
172
		}
173
		else
174
		{
175
# 記事IDと削除パスワードを条件として、bbsテーブルを検索します。
176
			$this->db->where('id', $id);
177
			$this->db->where('password', $password);
178
			$query = $this->db->get('bbs');
179
180
# レコードが存在した場合は、削除パスワードが一致したことになりますので、
181
# 次の処理に移ります。
182
			if ($query->num_rows() == 1)
183
			{
184
# POSTされたデータのdeleteフィールドが1の場合は、確認ページからのPOSTなの
185
# で、記事を削除します。
186
				if ($delete == 1)
187
				{
188
					$this->db->where('id', $id);
189
					$this->db->delete('bbs');
190
					$this->_load_view('bbs_delete_finished');
191
				}
192
# deleteフィールドが1以外の場合は、記事表示ページからのPOSTですので、確認
193
# ページを表示します。
194
				else
195
				{
196
					$row = $query->row();
197
198
					$data = [];
199
					$data['id']       = $row->id;
200
					$data['name']     = $row->name;
201
					$data['email']    = $row->email;
202
					$data['subject']  = $row->subject;
203
					$data['datetime'] = $row->datetime;
204
					$data['body']     = $row->body;
205
					$data['password'] = $row->password;
206
					$this->_load_view('bbs_delete_confirm', $data);
0 ignored issues
show
$data is of type array<string,?,{"password":"?"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
207
				}
208
			}
209
# 削除パスワードが一致しなかった場合は、エラーページを表示します。
210
			else
211
			{
212
				$this->_load_view('bbs_delete_error');
213
			}
214
		}
215
	}
216
217
# バリデーションを設定します。
218
	private function _set_validation()
219
	{
220
		$this->load->library('form_validation');
221
222
# 携帯端末かどうかを判定して、エラー表示の前後に挿入するタグを変更します。
223
		if ($this->agent->is_mobile())
224
		{
225
			$this->form_validation->set_error_delimiters('<div>', '</div>');
226
		}
227
		else
228
		{
229
			$this->form_validation->set_error_delimiters('<div class="error">', '</div>');
230
		}
231
232
# 整形・検証ルールを設定します。alpha_numericは英数字のみ、numericは数字のみ
233
# となります。callback_captcha_checkは、ユーザが定義したcaptcha_check()メソッド
234
# で検証することを意味します。
235
		$this->form_validation->set_rules(
236
			'name', '名前', 'trim|required|max_length[16]'
237
		);
238
		$this->form_validation->set_rules(
239
			'email', 'メールアドレス', 'trim|valid_email|max_length[64]'
240
		);
241
		$this->form_validation->set_rules(
242
			'subject', '件名', 'trim|required|max_length[32]'
243
		);
244
		$this->form_validation->set_rules(
245
			'body', '内容', 'trim|required|max_length[200]'
246
		);
247
		$this->form_validation->set_rules(
248
			'password', '削除パスワード', 'max_length[32]'
249
		);
250
		$this->form_validation->set_rules(
251
			'captcha', '画像認証コード', 'trim|required|alpha_numeric|callback_captcha_check'
252
		);
253
# keyフィールドは、キャプチャのID番号です。隠しフィールドに仕込まれるのみで
254
# ユーザの目に触れることはありません。
255
		$this->form_validation->set_rules('key', 'key', 'numeric');
256
	}
257
258
# 投稿された記事をデータベースに登録します。
259 View Code Duplication
	public function insert()
0 ignored issues
show
This method seems to be duplicated in 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...
260
	{
261
# 検証ルールを設定します。
262
		$this->_set_validation();
263
264
# 検証にパスしない場合は、新規投稿ページを表示します。
265
		if ($this->form_validation->run() == FALSE)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
266
		{
267
# 投稿されたIDのキャプチャを削除します。
268
			$this->_delete_captcha_data();
269
270
			$this->_show_post_page();
271
		}
272
		else
273
		{
274
# 検証にパスした場合は、送られたデータとIPアドレスをbbsテーブルに登録します。
275
			$data = [];
276
			$data['name']       = $this->input->post('name');
277
			$data['email']      = $this->input->post('email');
278
			$data['subject']    = $this->input->post('subject');
279
			$data['body']       = $this->input->post('body');
280
			$data['password']   = $this->input->post('password');
281
			$data['ip_address'] = $this->input->server('REMOTE_ADDR');
282
			$this->db->insert('bbs', $data);
283
284
# 投稿されたIDのキャプチャを削除します。
285
			$this->_delete_captcha_data();
286
287
# URLヘルパーのredirect()メソッドで記事表示ページにリダイレクトします。
288
			redirect('/bbs');
289
		}
290
	}
291
292
# キャプチャの検証をするメソッドです。バリデーション(認証)クラスより呼ばれます。
293
	public function captcha_check($str)
294
	{
295
# 環境がtestingの場合は、キャプチャの検証をスキップします。
296
		if (ENVIRONMENT === 'testing' && $str === '8888')
297
		{
298
			return TRUE;
299
		}
300
301
# 有効期限を2時間に設定し、それ以前に生成されたキャプチャをデータベースから
302
# 削除します。delete()メソッドの第2引数では、「captcha_time <」を配列のキーに
303
# していますが、このように記述することで、WHERE句の条件の演算子を指定できます。
304
		$expiration = time() - 7200;	// 有効期限 2時間
305
		$this->db->delete('captcha', ['captcha_time <' => $expiration]);
0 ignored issues
show
array('captcha_time <' => $expiration) is of type array<string,integer,{"c...cha_time <":"integer"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
306
307
# バリデーション(検証)クラスより引数$strに渡された、ユーザからの入力値がデータ
308
# ベースに保存されている値と一致するかどうかを調べます。隠しフィールドである
309
# keyフィールドの値と$strを条件に、有効期限内のレコードをデータベースから
310
# 検索します。条件に合うレコードが存在すれば、一致したと判断します。
311
# where()メソッドは、複数回呼ばれると、AND条件になります。
312
		$this->db->select("COUNT(*) AS count");
313
		$this->db->where('word', $str);
314
		$this->db->where('captcha_id', $this->input->post('key'));
315
		$this->db->where('captcha_time >', $expiration);
316
		$query = $this->db->get('captcha');
317
		$row = $query->row();
318
319
# レコードが0件の場合、つまり、一致しなかった場合は、captcha_checkルール
320
# のエラーメッセージを設定し、FALSEを返します。
321
		if ($row->count == 0)
322
		{
323
			$this->form_validation->set_message('captcha_check', '画像認証コードが一致しません。');
324
			return FALSE;
325
		}
326
# 一致した場合は、TRUEを返します。
327
		else
328
		{
329
			return TRUE;
330
		}
331
	}
332
333
# 携帯端末かどうかを判定し、ビューをロードするプライベートメソッドです。
334
	private function _load_view($file, $data = '')
335
	{
336
# 携帯端末の場合は、「_mobile」がファイル名に付くビューファイルをロードします。
337
		if ($this->agent->is_mobile())
338
		{
339
			$this->load->view($file . '_mobile', $data);
0 ignored issues
show
$data is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
340
		}
341
		else
342
		{
343
			$this->load->view($file, $data);
0 ignored issues
show
$data is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
344
		}
345
	}
346
347
# _outputメソッドは、コントローラで定義されている特殊なメソッドです。
348
# 引数には、出力されるデータの文字列が渡されます。
349
	public function _output($output)
350
	{
351
# 携帯端末の場合は、HTTPヘッダのContent-Typeヘッダで文字エンコードがShift_JIS
352
# である旨を出力し、送信するコンテンツもShift_JISに変換したものを送ります。
353
		if ($this->agent->is_mobile())
354
		{
355
			header('Content-Type: text/html; charset=Shift_JIS');
356
			echo mb_convert_encoding($output, 'SJIS-win', 'UTF-8');
357
		}
358
# 携帯端末でない場合は、文字エンコードはUTF-8ですので、Content-Typeヘッダでも
359
# UTF-8を送り、コンテンツもデフォルトのまま送信します。
360
		else
361
		{
362
			header('Content-Type: text/html; charset=UTF-8');
363
			echo $output;
364
		}
365
	}
366
}
367