Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

ManageSmileys.php ➔ list_getMessageIcons()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 9

Duplication

Lines 20
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 9
nc 2
nop 3
dl 20
loc 20
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file takes care of all administration of smileys.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * This is the dispatcher of smileys administration.
21
 */
22
function ManageSmileys()
23
{
24
	global $context, $txt, $modSettings;
25
26
	isAllowedTo('manage_smileys');
27
28
	loadLanguage('ManageSmileys');
29
	loadTemplate('ManageSmileys');
30
31
	$subActions = array(
32
		'addsmiley' => 'AddSmiley',
33
		'editicon' => 'EditMessageIcons',
34
		'editicons' => 'EditMessageIcons',
35
		'editsets' => 'EditSmileySets',
36
		'editsmileys' => 'EditSmileys',
37
		'import' => 'EditSmileySets',
38
		'modifyset' => 'EditSmileySets',
39
		'modifysmiley' => 'EditSmileys',
40
		'setorder' => 'EditSmileyOrder',
41
		'settings' => 'EditSmileySettings',
42
		'install' => 'InstallSmileySet'
43
	);
44
45
	// If customized smileys is disabled don't show the setting page
46
	if (empty($modSettings['smiley_enable']))
47
	{
48
		unset($subActions['addsmiley']);
49
		unset($subActions['editsmileys']);
50
		unset($subActions['setorder']);
51
		unset($subActions['modifysmiley']);
52
	}
53
	if (empty($modSettings['messageIcons_enable']))
54
	{
55
		unset($subActions['editicon']);
56
		unset($subActions['editicons']);
57
	}
58
59
	// Default the sub-action to 'edit smiley settings'.
60
	$_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'editsets';
61
62
	$context['page_title'] = $txt['smileys_manage'];
63
	$context['sub_action'] = $_REQUEST['sa'];
64
	$context['sub_template'] = $context['sub_action'];
65
66
	// Load up all the tabs...
67
	$context[$context['admin_menu_name']]['tab_data'] = array(
68
		'title' => $txt['smileys_manage'],
69
		'help' => 'smileys',
70
		'description' => $txt['smiley_settings_explain'],
71
		'tabs' => array(
72
			'editsets' => array(
73
				'description' => $txt['smiley_editsets_explain'],
74
			),
75
			'addsmiley' => array(
76
				'description' => $txt['smiley_addsmiley_explain'],
77
			),
78
			'editsmileys' => array(
79
				'description' => $txt['smiley_editsmileys_explain'],
80
			),
81
			'setorder' => array(
82
				'description' => $txt['smiley_setorder_explain'],
83
			),
84
			'editicons' => array(
85
				'description' => $txt['icons_edit_icons_explain'],
86
			),
87
			'settings' => array(
88
				'description' => $txt['smiley_settings_explain'],
89
			),
90
		),
91
	);
92
93
	// Some settings may not be enabled, disallow these from the tabs as appropriate.
94
	if (empty($modSettings['messageIcons_enable']))
95
		$context[$context['admin_menu_name']]['tab_data']['tabs']['editicons']['disabled'] = true;
96
	if (empty($modSettings['smiley_enable']))
97
	{
98
		$context[$context['admin_menu_name']]['tab_data']['tabs']['addsmiley']['disabled'] = true;
99
		$context[$context['admin_menu_name']]['tab_data']['tabs']['editsmileys']['disabled'] = true;
100
		$context[$context['admin_menu_name']]['tab_data']['tabs']['setorder']['disabled'] = true;
101
	}
102
103
	call_integration_hook('integrate_manage_smileys', array(&$subActions));
104
105
	// Call the right function for this sub-action.
106
	call_helper($subActions[$_REQUEST['sa']]);
107
}
108
109
/**
110
 * Handles modifying smileys settings.
111
 *
112
 * @param bool $return_config Whether or not to return the config_vars array (used for admin search)
113
 * @return void|array Returns nothing or returns the $config_vars array if $return_config is true
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string[]|string|ar...|boolean|integer>>|null.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
114
 */
115
function EditSmileySettings($return_config = false)
116
{
117
	global $modSettings, $context, $txt, $boarddir, $sourcedir, $scripturl;
118
119
	// The directories...
120
	$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
121
	$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
122
123
	// Get the names of the smiley sets.
124
	$smiley_sets = explode(',', $modSettings['smiley_sets_known']);
125
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
126
127
	$smiley_context = array();
128
	foreach ($smiley_sets as $i => $set)
129
		$smiley_context[$set] = $set_names[$i];
130
131
	// All the settings for the page...
132
	$config_vars = array(
133
		array('title', 'settings'),
134
			// Inline permissions.
135
			array('permissions', 'manage_smileys'),
136
		'',
137
			array('select', 'smiley_sets_default', $smiley_context),
138
			array('check', 'smiley_sets_enable'),
139
			array('check', 'smiley_enable', 'subtext' => $txt['smileys_enable_note']),
140
			array('text', 'smileys_url', 40),
141
			array('warning', !is_dir($context['smileys_dir']) ? 'setting_smileys_dir_wrong' : ''),
142
			array('text', 'smileys_dir', 'invalid' => !$context['smileys_dir_found'], 40),
143
		'',
144
			// Message icons.
145
			array('check', 'messageIcons_enable', 'subtext' => $txt['setting_messageIcons_enable_note']),
146
	);
147
148
	call_integration_hook('integrate_modify_smiley_settings', array(&$config_vars));
149
150
	if ($return_config)
151
		return $config_vars;
152
153
	// Setup the basics of the settings template.
154
	require_once($sourcedir . '/ManageServer.php');
155
	$context['sub_template'] = 'show_settings';
156
157
	// Finish up the form...
158
	$context['post_url'] = $scripturl . '?action=admin;area=smileys;save;sa=settings';
159
160
	// Saving the settings?
161
	if (isset($_GET['save']))
162
	{
163
		checkSession();
164
165
		// Validate the smiley set name.
166
		$_POST['smiley_sets_default'] = empty($smiley_context[$_POST['smiley_sets_default']]) ? 'default' : $_POST['smiley_sets_default'];
167
168
		call_integration_hook('integrate_save_smiley_settings');
169
170
		saveDBSettings($config_vars);
171
		$_SESSION['adm-save'] = true;
172
173
		cache_put_data('parsing_smileys', null, 480);
174
		cache_put_data('posting_smileys', null, 480);
175
176
		redirectexit('action=admin;area=smileys;sa=settings');
177
	}
178
179
	// We need this for the in-line permissions
180
	createToken('admin-mp');
181
182
	prepareDBSettingContext($config_vars);
183
}
184
185
/**
186
 * List, add, remove, modify smileys sets.
187
 */
188
function EditSmileySets()
189
{
190
	global $modSettings, $context, $txt;
191
	global $smcFunc, $scripturl, $sourcedir;
192
193
	// Set the right tab to be selected.
194
	$context[$context['admin_menu_name']]['current_subsection'] = 'editsets';
195
196
	// They must've been submitted a form.
197
	if (isset($_POST['smiley_save']))
198
	{
199
		checkSession();
200
		validateToken('admin-mss', 'request');
201
202
		// Delete selected smiley sets.
203
		if (!empty($_POST['delete']) && !empty($_POST['smiley_set']))
204
		{
205
			$set_paths = explode(',', $modSettings['smiley_sets_known']);
206
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
207
			foreach ($_POST['smiley_set'] as $id => $val)
208
			{
209
				// If this is the set you've marked as default, or the only one remaining, you can't delete it
210
				if ($modSettings['smiley_sets_default'] != $set_paths[$id] && count($set_paths) != 1 && isset($set_paths[$id], $set_names[$id]))
211
					unset($set_paths[$id], $set_names[$id]);
212
			}
213
214
			// Shortcut... array_merge() on a single array resets the numeric keys
215
			$set_paths = array_merge($set_paths);
216
			$set_names = array_merge($set_names);
217
218
			updateSettings(array(
219
				'smiley_sets_known' => implode(',', $set_paths),
220
				'smiley_sets_names' => implode("\n", $set_names),
221
				'smiley_sets_default' => in_array($modSettings['smiley_sets_default'], $set_paths) ? $modSettings['smiley_sets_default'] : $set_paths[0],
222
			));
223
		}
224
		// Add a new smiley set.
225
		elseif (!empty($_POST['add']))
226
			$context['sub_action'] = 'modifyset';
227
		// Create or modify a smiley set.
228
		elseif (isset($_POST['set']))
229
		{
230
			$set_paths = explode(',', $modSettings['smiley_sets_known']);
231
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
232
233
			// Create a new smiley set.
234
			if ($_POST['set'] == -1 && isset($_POST['smiley_sets_path']))
235
			{
236
				if (in_array($_POST['smiley_sets_path'], $set_paths))
237
					fatal_lang_error('smiley_set_already_exists');
238
239
				updateSettings(array(
240
					'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . $_POST['smiley_sets_path'],
241
					'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $_POST['smiley_sets_name'],
242
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path'],
243
				));
244
			}
245
			// Modify an existing smiley set.
246
			else
247
			{
248
				// Make sure the smiley set exists.
249
				if (!isset($set_paths[$_POST['set']]) || !isset($set_names[$_POST['set']]))
250
					fatal_lang_error('smiley_set_not_found');
251
252
				// Make sure the path is not yet used by another smileyset.
253
				if (in_array($_POST['smiley_sets_path'], $set_paths) && $_POST['smiley_sets_path'] != $set_paths[$_POST['set']])
254
					fatal_lang_error('smiley_set_path_already_used');
255
256
				$set_paths[$_POST['set']] = $_POST['smiley_sets_path'];
257
				$set_names[$_POST['set']] = $_POST['smiley_sets_name'];
258
				updateSettings(array(
259
					'smiley_sets_known' => implode(',', $set_paths),
260
					'smiley_sets_names' => implode("\n", $set_names),
261
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path']
262
				));
263
			}
264
265
			// The user might have checked to also import smileys.
266
			if (!empty($_POST['smiley_sets_import']))
267
				ImportSmileys($_POST['smiley_sets_path']);
268
		}
269
		cache_put_data('parsing_smileys', null, 480);
270
		cache_put_data('posting_smileys', null, 480);
271
	}
272
273
	// Load all available smileysets...
274
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
275
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
276 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
277
		$context['smiley_sets'][$i] = array(
278
			'id' => $i,
279
			'path' => $smcFunc['htmlspecialchars']($set),
280
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
281
			'selected' => $set == $modSettings['smiley_sets_default']
282
		);
283
284
	// Importing any smileys from an existing set?
285
	if ($context['sub_action'] == 'import')
286
	{
287
		checkSession('get');
288
		validateToken('admin-mss', 'request');
289
290
		$_GET['set'] = (int) $_GET['set'];
291
292
		// Sanity check - then import.
293
		if (isset($context['smiley_sets'][$_GET['set']]))
294
			ImportSmileys(un_htmlspecialchars($context['smiley_sets'][$_GET['set']]['path']));
295
296
		// Force the process to continue.
297
		$context['sub_action'] = 'modifyset';
298
		$context['sub_template'] = 'modifyset';
299
	}
300
	// If we're modifying or adding a smileyset, some context info needs to be set.
301
	if ($context['sub_action'] == 'modifyset')
302
	{
303
		$_GET['set'] = !isset($_GET['set']) ? -1 : (int) $_GET['set'];
304
		if ($_GET['set'] == -1 || !isset($context['smiley_sets'][$_GET['set']]))
305
			$context['current_set'] = array(
306
				'id' => '-1',
307
				'path' => '',
308
				'name' => '',
309
				'selected' => false,
310
				'is_new' => true,
311
			);
312
		else
313
		{
314
			$context['current_set'] = &$context['smiley_sets'][$_GET['set']];
315
			$context['current_set']['is_new'] = false;
316
317
			// Calculate whether there are any smileys in the directory that can be imported.
318
			if (!empty($modSettings['smiley_enable']) && !empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']))
319
			{
320
				$smileys = array();
321
				$dir = dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']);
322 View Code Duplication
				while ($entry = $dir->read())
323
				{
324
					if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
325
						$smileys[strtolower($entry)] = $entry;
326
				}
327
				$dir->close();
328
329
				if (empty($smileys))
330
					fatal_lang_error('smiley_set_dir_not_found', false, array($context['current_set']['name']));
331
332
				// Exclude the smileys that are already in the database.
333
				$request = $smcFunc['db_query']('', '
334
					SELECT filename
335
					FROM {db_prefix}smileys
336
					WHERE filename IN ({array_string:smiley_list})',
337
					array(
338
						'smiley_list' => $smileys,
339
					)
340
				);
341 View Code Duplication
				while ($row = $smcFunc['db_fetch_assoc']($request))
342
					if (isset($smileys[strtolower($row['filename'])]))
343
						unset($smileys[strtolower($row['filename'])]);
344
				$smcFunc['db_free_result']($request);
345
346
				$context['current_set']['can_import'] = count($smileys);
347
				$context['current_set']['import_url'] = $scripturl . '?action=admin;area=smileys;sa=import;set=' . $context['current_set']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'];
348
			}
349
		}
350
351
		// Retrieve all potential smiley set directories.
352
		$context['smiley_set_dirs'] = array();
353
		if (!empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir']))
354
		{
355
			$dir = dir($modSettings['smileys_dir']);
356
			while ($entry = $dir->read())
357
			{
358
				if (!in_array($entry, array('.', '..')) && is_dir($modSettings['smileys_dir'] . '/' . $entry))
359
					$context['smiley_set_dirs'][] = array(
360
						'id' => $entry,
361
						'path' => $modSettings['smileys_dir'] . '/' . $entry,
362
						'selectable' => $entry == $context['current_set']['path'] || !in_array($entry, explode(',', $modSettings['smiley_sets_known'])),
363
						'current' => $entry == $context['current_set']['path'],
364
					);
365
			}
366
			$dir->close();
367
		}
368
	}
369
370
	// This is our save haven.
371
	createToken('admin-mss', 'request');
372
373
	// In case we need to import smileys, we need to add the token in now.
374
	if (isset($context['current_set']['import_url']))
375
		$context['current_set']['import_url'] .= ';' . $context['admin-mss_token_var'] . '=' . $context['admin-mss_token'];
376
377
	$listOptions = array(
378
		'id' => 'smiley_set_list',
379
		'title' => $txt['smiley_sets'],
380
		'no_items_label' => $txt['smiley_sets_none'],
381
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
382
		'default_sort_col' => 'default',
383
		'get_items' => array(
384
			'function' => 'list_getSmileySets',
385
		),
386
		'get_count' => array(
387
			'function' => 'list_getNumSmileySets',
388
		),
389
		'columns' => array(
390
			'default' => array(
391
				'header' => array(
392
					'value' => $txt['smiley_sets_default'],
393
					'class' => 'centercol',
394
				),
395
				'data' => array(
396
					'function' => function ($rowData)
397
					{
398
						return $rowData['selected'] ? '<span class="generic_icons valid"></span>' : '';
399
					},
400
					'class' => 'centercol',
401
				),
402
				'sort' => array(
403
					'default' => 'selected DESC',
404
				),
405
			),
406
			'name' => array(
407
				'header' => array(
408
					'value' => $txt['smiley_sets_name'],
409
				),
410
				'data' => array(
411
					'db_htmlsafe' => 'name',
412
				),
413
				'sort' => array(
414
					'default' => 'name',
415
					'reverse' => 'name DESC',
416
				),
417
			),
418
			'url' => array(
419
				'header' => array(
420
					'value' => $txt['smiley_sets_url'],
421
				),
422
				'data' => array(
423
					'sprintf' => array(
424
						'format' => $modSettings['smileys_url'] . '/<strong>%1$s</strong>/...',
425
						'params' => array(
426
							'path' => true,
427
						),
428
					),
429
				),
430
				'sort' => array(
431
					'default' => 'path',
432
					'reverse' => 'path DESC',
433
				),
434
			),
435
			'modify' => array(
436
				'header' => array(
437
					'value' => $txt['smiley_set_modify'],
438
					'class' => 'centercol',
439
				),
440
				'data' => array(
441
					'sprintf' => array(
442
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset;set=%1$d">' . $txt['smiley_set_modify'] . '</a>',
443
						'params' => array(
444
							'id' => true,
445
						),
446
					),
447
					'class' => 'centercol',
448
				),
449
			),
450
			'check' => array(
451
				'header' => array(
452
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
453
					'class' => 'centercol',
454
				),
455
				'data' => array(
456
					'function' => function ($rowData)
457
					{
458
						return $rowData['selected'] ? '' : sprintf('<input type="checkbox" name="smiley_set[%1$d]" class="input_check">', $rowData['id']);
459
					},
460
					'class' => 'centercol',
461
				),
462
			),
463
		),
464
		'form' => array(
465
			'href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
466
			'token' => 'admin-mss',
467
		),
468
		'additional_rows' => array(
469
			array(
470
				'position' => 'above_table_headers',
471
				'value' => '<input type="hidden" name="smiley_save"><input type="submit" name="delete" value="' . $txt['smiley_sets_delete'] . '" data-confirm="' . $txt['smiley_sets_confirm'] . '" class="button_submit you_sure"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
472
			),
473
			array(
474
				'position' => 'below_table_data',
475
				'value' => '<input type="hidden" name="smiley_save"><input type="submit" name="delete" value="' . $txt['smiley_sets_delete'] . '" data-confirm="' . $txt['smiley_sets_confirm'] . '" class="button_submit you_sure"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
476
			),
477
		),
478
	);
479
480
	require_once($sourcedir . '/Subs-List.php');
481
	createList($listOptions);
482
}
483
484
/**
485
 * Callback function for createList().
486
 * @todo to be moved to Subs-Smileys?
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
487
 *
488
 * @param int $start The item to start with (not used here)
489
 * @param int $items_per_page The number of items to show per page (not used here)
490
 * @param string $sort A string indicating how to sort the results
491
 * @return array An array of info about the smiley sets
492
 */
493
function list_getSmileySets($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
494
{
495
	global $modSettings;
496
497
	$known_sets = explode(',', $modSettings['smiley_sets_known']);
498
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
499
	$cols = array(
500
		'id' => array(),
501
		'selected' => array(),
502
		'path' => array(),
503
		'name' => array(),
504
	);
505
	foreach ($known_sets as $i => $set)
506
	{
507
		$cols['id'][] = $i;
508
		$cols['selected'][] = $i;
509
		$cols['path'][] = $set;
510
		$cols['name'][] = $set_names[$i];
511
	}
512
	$sort_flag = strpos($sort, 'DESC') === false ? SORT_ASC : SORT_DESC;
513
	if (substr($sort, 0, 4) === 'name')
514
		array_multisort($cols['name'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['selected'], $cols['id']);
515
	elseif (substr($sort, 0, 4) === 'path')
516
		array_multisort($cols['path'], $sort_flag, SORT_REGULAR, $cols['name'], $cols['selected'], $cols['id']);
517
	else
518
		array_multisort($cols['selected'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['name'], $cols['id']);
519
520
	$smiley_sets = array();
521 View Code Duplication
	foreach ($cols['id'] as $i => $id)
522
		$smiley_sets[] = array(
523
			'id' => $id,
524
			'path' => $cols['path'][$i],
525
			'name' => $cols['name'][$i],
526
			'selected' => $cols['path'][$i] == $modSettings['smiley_sets_default']
527
		);
528
529
	return $smiley_sets;
530
}
531
532
/**
533
 * Callback function for createList().
534
 * @todo to be moved to Subs-Smileys?
0 ignored issues
show
Coding Style introduced by
Comment refers to a TODO task

This check looks TODO comments that have been left in the code.

``TODO``s show that something is left unfinished and should be attended to.

Loading history...
535
 * @return int The total number of known smiley sets
536
 */
537
function list_getNumSmileySets()
538
{
539
	global $modSettings;
540
541
	return count(explode(',', $modSettings['smiley_sets_known']));
542
}
543
544
/**
545
 * Add a smiley, that's right.
546
 */
547
function AddSmiley()
548
{
549
	global $modSettings, $context, $txt, $boarddir, $smcFunc;
550
551
	// Get a list of all known smiley sets.
552
	$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
553
	$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
554
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
555
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
556 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
557
		$context['smiley_sets'][$i] = array(
558
			'id' => $i,
559
			'path' => $smcFunc['htmlspecialchars']($set),
560
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
561
			'selected' => $set == $modSettings['smiley_sets_default']
562
		);
563
564
	// Submitting a form?
565
	if (isset($_POST[$context['session_var']], $_POST['smiley_code']))
566
	{
567
		checkSession();
568
569
		// Some useful arrays... types we allow - and ports we don't!
570
		$allowedTypes = array('jpeg', 'jpg', 'gif', 'png', 'bmp');
571
		$disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php');
572
573
		$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
574
		$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
575
		$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
576
577
		// Make sure some code was entered.
578
		if (empty($_POST['smiley_code']))
579
			fatal_lang_error('smiley_has_no_code');
580
581
		// Check whether the new code has duplicates. It should be unique.
582
		$request = $smcFunc['db_query']('', '
583
			SELECT id_smiley
584
			FROM {db_prefix}smileys
585
			WHERE code = {raw:mysql_binary_statement} {string:smiley_code}',
586
			array(
587
				'mysql_binary_statement' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
588
				'smiley_code' => $_POST['smiley_code'],
589
			)
590
		);
591
		if ($smcFunc['db_num_rows']($request) > 0)
592
			fatal_lang_error('smiley_not_unique');
593
		$smcFunc['db_free_result']($request);
594
595
		// If we are uploading - check all the smiley sets are writable!
596
		if ($_POST['method'] != 'existing')
597
		{
598
			$writeErrors = array();
599
			foreach ($context['smiley_sets'] as $set)
600
			{
601
				if (!is_writable($context['smileys_dir'] . '/' . un_htmlspecialchars($set['path'])))
602
					$writeErrors[] = $set['path'];
603
			}
604
			if (!empty($writeErrors))
605
				fatal_lang_error('smileys_upload_error_notwritable', true, array(implode(', ', $writeErrors)));
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a string|false.

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...
606
		}
607
608
		// Uploading just one smiley for all of them?
609
		if (isset($_POST['sameall']) && isset($_FILES['uploadSmiley']['name']) && $_FILES['uploadSmiley']['name'] != '')
610
		{
611 View Code Duplication
			if (!is_uploaded_file($_FILES['uploadSmiley']['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['uploadSmiley']['tmp_name'])))
612
				fatal_lang_error('smileys_upload_error');
613
614
			// Sorry, no spaces, dots, or anything else but letters allowed.
615
			$_FILES['uploadSmiley']['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['uploadSmiley']['name']);
616
617
			// We only allow image files - it's THAT simple - no messing around here...
618 View Code Duplication
			if (!in_array(strtolower(substr(strrchr($_FILES['uploadSmiley']['name'], '.'), 1)), $allowedTypes))
619
				fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
620
621
			// We only need the filename...
622
			$destName = basename($_FILES['uploadSmiley']['name']);
623
624
			// Make sure they aren't trying to upload a nasty file - for their own good here!
625
			if (in_array(strtolower($destName), $disabledFiles))
626
				fatal_lang_error('smileys_upload_error_illegal');
627
628
			// Check if the file already exists... and if not move it to EVERY smiley set directory.
629
			$i = 0;
630
			// Keep going until we find a set the file doesn't exist in. (or maybe it exists in all of them?)
631
			while (isset($context['smiley_sets'][$i]) && file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName))
632
				$i++;
633
634
			// Okay, we're going to put the smiley right here, since it's not there yet!
635
			if (isset($context['smiley_sets'][$i]['path']))
636
			{
637
				$smileyLocation = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
638
				move_uploaded_file($_FILES['uploadSmiley']['tmp_name'], $smileyLocation);
639
				smf_chmod($smileyLocation, 0644);
640
641
				// Now, we want to move it from there to all the other sets.
642
				for ($n = count($context['smiley_sets']); $i < $n; $i++)
643
				{
644
					$currentPath = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
645
646
					// The file is already there!  Don't overwrite it!
647
					if (file_exists($currentPath))
648
						continue;
649
650
					// Okay, so copy the first one we made to here.
651
					copy($smileyLocation, $currentPath);
652
					smf_chmod($currentPath, 0644);
653
				}
654
			}
655
656
			// Finally make sure it's saved correctly!
657
			$_POST['smiley_filename'] = $destName;
658
		}
659
		// What about uploading several files?
660
		elseif ($_POST['method'] != 'existing')
661
		{
662
			$newName = '';
663
			foreach ($_FILES as $name => $data)
664
			{
665
				if ($_FILES[$name]['name'] == '')
666
					fatal_lang_error('smileys_upload_error_blank');
667
668
				if (empty($newName))
669
					$newName = basename($_FILES[$name]['name']);
670
				elseif (basename($_FILES[$name]['name']) != $newName)
671
					fatal_lang_error('smileys_upload_error_name');
672
			}
673
674
			foreach ($context['smiley_sets'] as $i => $set)
675
			{
676
				$set['name'] = un_htmlspecialchars($set['name']);
677
				$set['path'] = un_htmlspecialchars($set['path']);
678
679
				if (!isset($_FILES['individual_' . $set['name']]['name']) || $_FILES['individual_' . $set['name']]['name'] == '')
680
					continue;
681
682
				// Got one...
683
				if (!is_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['individual_' . $set['name']]['tmp_name'])))
684
					fatal_lang_error('smileys_upload_error');
685
686
				// Sorry, no spaces, dots, or anything else but letters allowed.
687
				$_FILES['individual_' . $set['name']]['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['individual_' . $set['name']]['name']);
688
689
				// We only allow image files - it's THAT simple - no messing around here...
690 View Code Duplication
				if (!in_array(strtolower(substr(strrchr($_FILES['individual_' . $set['name']]['name'], '.'), 1)), $allowedTypes))
691
					fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
692
693
				// We only need the filename...
694
				$destName = basename($_FILES['individual_' . $set['name']]['name']);
695
696
				// Make sure they aren't trying to upload a nasty file - for their own good here!
697
				if (in_array(strtolower($destName), $disabledFiles))
698
					fatal_lang_error('smileys_upload_error_illegal');
699
700
				// If the file exists - ignore it.
701
				$smileyLocation = $context['smileys_dir'] . '/' . $set['path'] . '/' . $destName;
702
				if (file_exists($smileyLocation))
703
					continue;
704
705
				// Finally - move the image!
706
				move_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name'], $smileyLocation);
707
				smf_chmod($smileyLocation, 0644);
708
709
				// Should always be saved correctly!
710
				$_POST['smiley_filename'] = $destName;
711
			}
712
		}
713
714
		// Also make sure a filename was given.
715
		if (empty($_POST['smiley_filename']))
716
			fatal_lang_error('smiley_has_no_filename');
717
718
		// Find the position on the right.
719
		$smiley_order = '0';
720
		if ($_POST['smiley_location'] != 1)
721
		{
722
			$request = $smcFunc['db_query']('', '
723
				SELECT MAX(smiley_order) + 1
724
				FROM {db_prefix}smileys
725
				WHERE hidden = {int:smiley_location}
726
					AND smiley_row = {int:first_row}',
727
				array(
728
					'smiley_location' => $_POST['smiley_location'],
729
					'first_row' => 0,
730
				)
731
			);
732
			list ($smiley_order) = $smcFunc['db_fetch_row']($request);
733
			$smcFunc['db_free_result']($request);
734
735
			if (empty($smiley_order))
736
				$smiley_order = '0';
737
		}
738
		$smcFunc['db_insert']('',
739
			'{db_prefix}smileys',
740
			array(
741
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'hidden' => 'int', 'smiley_order' => 'int',
742
			),
743
			array(
744
				$_POST['smiley_code'], $_POST['smiley_filename'], $_POST['smiley_description'], $_POST['smiley_location'], $smiley_order,
745
			),
746
			array('id_smiley')
747
		);
748
749
		cache_put_data('parsing_smileys', null, 480);
750
		cache_put_data('posting_smileys', null, 480);
751
752
		// No errors? Out of here!
753
		redirectexit('action=admin;area=smileys;sa=editsmileys');
754
	}
755
756
	$context['selected_set'] = $modSettings['smiley_sets_default'];
757
758
	// Get all possible filenames for the smileys.
759
	$context['filenames'] = array();
760 View Code Duplication
	if ($context['smileys_dir_found'])
761
	{
762
		foreach ($context['smiley_sets'] as $smiley_set)
763
		{
764
			if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
765
				continue;
766
767
			$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
768
			while ($entry = $dir->read())
769
			{
770
				if (!in_array($entry, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
771
					$context['filenames'][strtolower($entry)] = array(
772
						'id' => $smcFunc['htmlspecialchars']($entry),
773
						'selected' => false,
774
					);
775
			}
776
			$dir->close();
777
		}
778
		ksort($context['filenames']);
779
	}
780
781
	// Create a new smiley from scratch.
782
	$context['filenames'] = array_values($context['filenames']);
783
	$context['current_smiley'] = array(
784
		'id' => 0,
785
		'code' => '',
786
		'filename' => $context['filenames'][0]['id'],
787
		'description' => $txt['smileys_default_description'],
788
		'location' => 0,
789
		'is_new' => true,
790
	);
791
}
792
793
/**
794
 * Add, remove, edit smileys.
795
 */
796
function EditSmileys()
797
{
798
	global $modSettings, $context, $txt, $boarddir;
799
	global $smcFunc, $scripturl, $sourcedir;
800
801
	// Force the correct tab to be displayed.
802
	$context[$context['admin_menu_name']]['current_subsection'] = 'editsmileys';
803
804
	// Submitting a form?
805
	if (isset($_POST['smiley_save']) || isset($_POST['smiley_action']))
806
	{
807
		checkSession();
808
809
		// Changing the selected smileys?
810
		if (isset($_POST['smiley_action']) && !empty($_POST['checked_smileys']))
811
		{
812
			foreach ($_POST['checked_smileys'] as $id => $smiley_id)
813
				$_POST['checked_smileys'][$id] = (int) $smiley_id;
814
815
			if ($_POST['smiley_action'] == 'delete')
816
				$smcFunc['db_query']('', '
817
					DELETE FROM {db_prefix}smileys
818
					WHERE id_smiley IN ({array_int:checked_smileys})',
819
					array(
820
						'checked_smileys' => $_POST['checked_smileys'],
821
					)
822
				);
823
			// Changing the status of the smiley?
824
			else
825
			{
826
				// Check it's a valid type.
827
				$displayTypes = array(
828
					'post' => 0,
829
					'hidden' => 1,
830
					'popup' => 2
831
				);
832
				if (isset($displayTypes[$_POST['smiley_action']]))
833
					$smcFunc['db_query']('', '
834
						UPDATE {db_prefix}smileys
835
						SET hidden = {int:display_type}
836
						WHERE id_smiley IN ({array_int:checked_smileys})',
837
						array(
838
							'checked_smileys' => $_POST['checked_smileys'],
839
							'display_type' => $displayTypes[$_POST['smiley_action']],
840
						)
841
					);
842
			}
843
		}
844
		// Create/modify a smiley.
845
		elseif (isset($_POST['smiley']))
846
		{
847
			// Is it a delete?
848
			if (!empty($_POST['deletesmiley']))
849
			{
850
				$smcFunc['db_query']('', '
851
					DELETE FROM {db_prefix}smileys
852
					WHERE id_smiley = {int:current_smiley}',
853
					array(
854
						'current_smiley' => $_POST['smiley'],
855
					)
856
				);
857
			}
858
			// Otherwise an edit.
859
			else
860
			{
861
				$_POST['smiley'] = (int) $_POST['smiley'];
862
				$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
863
				$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
864
				$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
865
866
				// Make sure some code was entered.
867
				if (empty($_POST['smiley_code']))
868
					fatal_lang_error('smiley_has_no_code');
869
870
				// Also make sure a filename was given.
871
				if (empty($_POST['smiley_filename']))
872
					fatal_lang_error('smiley_has_no_filename');
873
874
				// Check whether the new code has duplicates. It should be unique.
875
				$request = $smcFunc['db_query']('', '
876
					SELECT id_smiley
877
					FROM {db_prefix}smileys
878
					WHERE code = {raw:mysql_binary_type} {string:smiley_code}' . (empty($_POST['smiley']) ? '' : '
879
						AND id_smiley != {int:current_smiley}'),
880
					array(
881
						'current_smiley' => $_POST['smiley'],
882
						'mysql_binary_type' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
883
						'smiley_code' => $_POST['smiley_code'],
884
					)
885
				);
886
				if ($smcFunc['db_num_rows']($request) > 0)
887
					fatal_lang_error('smiley_not_unique');
888
				$smcFunc['db_free_result']($request);
889
890
				$smcFunc['db_query']('', '
891
					UPDATE {db_prefix}smileys
892
					SET
893
						code = {string:smiley_code},
894
						filename = {string:smiley_filename},
895
						description = {string:smiley_description},
896
						hidden = {int:smiley_location}
897
					WHERE id_smiley = {int:current_smiley}',
898
					array(
899
						'smiley_location' => $_POST['smiley_location'],
900
						'current_smiley' => $_POST['smiley'],
901
						'smiley_code' => $_POST['smiley_code'],
902
						'smiley_filename' => $_POST['smiley_filename'],
903
						'smiley_description' => $_POST['smiley_description'],
904
					)
905
				);
906
			}
907
		}
908
909
		cache_put_data('parsing_smileys', null, 480);
910
		cache_put_data('posting_smileys', null, 480);
911
	}
912
913
	// Load all known smiley sets.
914
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
915
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
916 View Code Duplication
	foreach ($context['smiley_sets'] as $i => $set)
917
		$context['smiley_sets'][$i] = array(
918
			'id' => $i,
919
			'path' => $smcFunc['htmlspecialchars']($set),
920
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
921
			'selected' => $set == $modSettings['smiley_sets_default']
922
		);
923
924
	// Prepare overview of all (custom) smileys.
925
	if ($context['sub_action'] == 'editsmileys')
926
	{
927
		// Determine the language specific sort order of smiley locations.
928
		$smiley_locations = array(
929
			$txt['smileys_location_form'],
930
			$txt['smileys_location_hidden'],
931
			$txt['smileys_location_popup'],
932
		);
933
		asort($smiley_locations);
934
935
		// Create a list of options for selecting smiley sets.
936
		$smileyset_option_list = '
937
			<select name="set" onchange="changeSet(this.options[this.selectedIndex].value);">';
938
		foreach ($context['smiley_sets'] as $smiley_set)
939
			$smileyset_option_list .= '
940
				<option value="' . $smiley_set['path'] . '"' . ($modSettings['smiley_sets_default'] == $smiley_set['path'] ? ' selected' : '') . '>' . $smiley_set['name'] . '</option>';
941
		$smileyset_option_list .= '
942
			</select>';
943
944
		$listOptions = array(
945
			'id' => 'smiley_list',
946
			'title' => $txt['smileys_edit'],
947
			'items_per_page' => 40,
948
			'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
949
			'default_sort_col' => 'filename',
950
			'get_items' => array(
951
				'function' => 'list_getSmileys',
952
			),
953
			'get_count' => array(
954
				'function' => 'list_getNumSmileys',
955
			),
956
			'no_items_label' => $txt['smileys_no_entries'],
957
			'columns' => array(
958
				'picture' => array(
959
					'data' => array(
960
						'sprintf' => array(
961
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d"><img src="' . $modSettings['smileys_url'] . '/' . $modSettings['smiley_sets_default'] . '/%2$s" alt="%3$s" style="padding: 2px;" id="smiley%1$d"><input type="hidden" name="smileys[%1$d][filename]" value="%2$s"></a>',
962
							'params' => array(
963
								'id_smiley' => false,
964
								'filename' => true,
965
								'description' => true,
966
							),
967
						),
968
						'class' => 'centercol',
969
					),
970
				),
971
				'code' => array(
972
					'header' => array(
973
						'value' => $txt['smileys_code'],
974
					),
975
					'data' => array(
976
						'db_htmlsafe' => 'code',
977
					),
978
					'sort' => array(
979
						'default' => 'code',
980
						'reverse' => 'code DESC',
981
					),
982
				),
983
				'filename' => array(
984
					'header' => array(
985
						'value' => $txt['smileys_filename'],
986
					),
987
					'data' => array(
988
						'db_htmlsafe' => 'filename',
989
					),
990
					'sort' => array(
991
						'default' => 'filename',
992
						'reverse' => 'filename DESC',
993
					),
994
				),
995
				'location' => array(
996
					'header' => array(
997
						'value' => $txt['smileys_location'],
998
					),
999
					'data' => array(
1000
						'function' => function ($rowData) use ($txt)
1001
						{
1002
							if (empty($rowData['hidden']))
1003
								return $txt['smileys_location_form'];
1004
							elseif ($rowData['hidden'] == 1)
1005
								return $txt['smileys_location_hidden'];
1006
							else
1007
								return $txt['smileys_location_popup'];
1008
						},
1009
					),
1010
					'sort' => array(
1011
						'default' => 'FIND_IN_SET(hidden, \'' . implode(',', array_keys($smiley_locations)) . '\')',
1012
						'reverse' => 'FIND_IN_SET(hidden, \'' . implode(',', array_keys($smiley_locations)) . '\') DESC',
1013
					),
1014
				),
1015
				'tooltip' => array(
1016
					'header' => array(
1017
						'value' => $txt['smileys_description'],
1018
					),
1019
					'data' => array(
1020
						'function' => function ($rowData) use ($context, $txt, $modSettings, $smcFunc)
1021
						{
1022
							if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir']))
1023
								return $smcFunc['htmlspecialchars']($rowData['description']);
1024
1025
							// Check if there are smileys missing in some sets.
1026
							$missing_sets = array();
1027
							foreach ($context['smiley_sets'] as $smiley_set)
1028
								if (!file_exists(sprintf('%1$s/%2$s/%3$s', $modSettings['smileys_dir'], $smiley_set['path'], $rowData['filename'])))
1029
									$missing_sets[] = $smiley_set['path'];
1030
1031
							$description = $smcFunc['htmlspecialchars']($rowData['description']);
1032
1033
							if (!empty($missing_sets))
1034
								$description .= sprintf('<br><span class="smalltext"><strong>%1$s:</strong> %2$s</span>', $txt['smileys_not_found_in_set'], implode(', ', $missing_sets));
1035
1036
							return $description;
1037
						},
1038
					),
1039
					'sort' => array(
1040
						'default' => 'description',
1041
						'reverse' => 'description DESC',
1042
					),
1043
				),
1044
				'modify' => array(
1045
					'header' => array(
1046
						'value' => $txt['smileys_modify'],
1047
						'class' => 'centercol',
1048
					),
1049
					'data' => array(
1050
						'sprintf' => array(
1051
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d">' . $txt['smileys_modify'] . '</a>',
1052
							'params' => array(
1053
								'id_smiley' => false,
1054
							),
1055
						),
1056
						'class' => 'centercol',
1057
					),
1058
				),
1059
				'check' => array(
1060
					'header' => array(
1061
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
1062
						'class' => 'centercol',
1063
					),
1064
					'data' => array(
1065
						'sprintf' => array(
1066
							'format' => '<input type="checkbox" name="checked_smileys[]" value="%1$d" class="input_check">',
1067
							'params' => array(
1068
								'id_smiley' => false,
1069
							),
1070
						),
1071
						'class' => 'centercol',
1072
					),
1073
				),
1074
			),
1075
			'form' => array(
1076
				'href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
1077
				'name' => 'smileyForm',
1078
			),
1079
			'additional_rows' => array(
1080
				array(
1081
					'position' => 'above_column_headers',
1082
					'value' => $smileyset_option_list,
1083
					'class' => 'righttext',
1084
				),
1085
				array(
1086
					'position' => 'below_table_data',
1087
					'value' => '
1088
						<select name="smiley_action" onchange="makeChanges(this.value);">
1089
							<option value="-1">' . $txt['smileys_with_selected'] . ':</option>
1090
							<option value="-1" disabled>--------------</option>
1091
							<option value="hidden">' . $txt['smileys_make_hidden'] . '</option>
1092
							<option value="post">' . $txt['smileys_show_on_post'] . '</option>
1093
							<option value="popup">' . $txt['smileys_show_on_popup'] . '</option>
1094
							<option value="delete">' . $txt['smileys_remove'] . '</option>
1095
						</select>
1096
						<noscript>
1097
							<input type="submit" name="perform_action" value="' . $txt['go'] . '" class="button_submit">
1098
						</noscript>',
1099
					'class' => 'righttext',
1100
				),
1101
			),
1102
			'javascript' => '
1103
				function makeChanges(action)
1104
				{
1105
					if (action == \'-1\')
1106
						return false;
1107
					else if (action == \'delete\')
1108
					{
1109
						if (confirm(\'' . $txt['smileys_confirm'] . '\'))
1110
							document.forms.smileyForm.submit();
1111
					}
1112
					else
1113
						document.forms.smileyForm.submit();
1114
					return true;
1115
				}
1116
				function changeSet(newSet)
1117
				{
1118
					var currentImage, i, knownSmileys = [];
1119
1120
					if (knownSmileys.length == 0)
1121
					{
1122
						for (var i = 0, n = document.images.length; i < n; i++)
1123
							if (document.images[i].id.substr(0, 6) == \'smiley\')
1124
								knownSmileys[knownSmileys.length] = document.images[i].id.substr(6);
1125
					}
1126
1127
					for (i = 0; i < knownSmileys.length; i++)
1128
					{
1129
						currentImage = document.getElementById("smiley" + knownSmileys[i]);
1130
						currentImage.src = "' . $modSettings['smileys_url'] . '/" + newSet + "/" + document.forms.smileyForm["smileys[" + knownSmileys[i] + "][filename]"].value;
1131
					}
1132
				}',
1133
		);
1134
1135
		require_once($sourcedir . '/Subs-List.php');
1136
		createList($listOptions);
1137
1138
		// The list is the only thing to show, so make it the main template.
1139
		$context['default_list'] = 'smiley_list';
1140
		$context['sub_template'] = 'show_list';
1141
	}
1142
	// Modifying smileys.
1143
	elseif ($context['sub_action'] == 'modifysmiley')
1144
	{
1145
		// Get a list of all known smiley sets.
1146
		$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
1147
		$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
1148
		$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
1149
		$set_names = explode("\n", $modSettings['smiley_sets_names']);
1150 View Code Duplication
		foreach ($context['smiley_sets'] as $i => $set)
1151
			$context['smiley_sets'][$i] = array(
1152
				'id' => $i,
1153
				'path' => $smcFunc['htmlspecialchars']($set),
1154
				'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
1155
				'selected' => $set == $modSettings['smiley_sets_default']
1156
			);
1157
1158
		$context['selected_set'] = $modSettings['smiley_sets_default'];
1159
1160
		// Get all possible filenames for the smileys.
1161
		$context['filenames'] = array();
1162 View Code Duplication
		if ($context['smileys_dir_found'])
1163
		{
1164
			foreach ($context['smiley_sets'] as $smiley_set)
1165
			{
1166
				if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
1167
					continue;
1168
1169
				$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
1170
				while ($entry = $dir->read())
1171
				{
1172
					if (!in_array($entry, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
1173
						$context['filenames'][strtolower($entry)] = array(
1174
							'id' => $smcFunc['htmlspecialchars']($entry),
1175
							'selected' => false,
1176
						);
1177
				}
1178
				$dir->close();
1179
			}
1180
			ksort($context['filenames']);
1181
		}
1182
1183
		$request = $smcFunc['db_query']('', '
1184
			SELECT id_smiley AS id, code, filename, description, hidden AS location, 0 AS is_new
1185
			FROM {db_prefix}smileys
1186
			WHERE id_smiley = {int:current_smiley}',
1187
			array(
1188
				'current_smiley' => (int) $_REQUEST['smiley'],
1189
			)
1190
		);
1191
		if ($smcFunc['db_num_rows']($request) != 1)
1192
			fatal_lang_error('smiley_not_found');
1193
		$context['current_smiley'] = $smcFunc['db_fetch_assoc']($request);
1194
		$smcFunc['db_free_result']($request);
1195
1196
		$context['current_smiley']['code'] = $smcFunc['htmlspecialchars']($context['current_smiley']['code']);
1197
		$context['current_smiley']['filename'] = $smcFunc['htmlspecialchars']($context['current_smiley']['filename']);
1198
		$context['current_smiley']['description'] = $smcFunc['htmlspecialchars']($context['current_smiley']['description']);
1199
1200
		if (isset($context['filenames'][strtolower($context['current_smiley']['filename'])]))
1201
			$context['filenames'][strtolower($context['current_smiley']['filename'])]['selected'] = true;
1202
	}
1203
}
1204
1205
/**
1206
 * Callback function for createList().
1207
 *
1208
 * @param int $start The item to start with (not used here)
1209
 * @param int $items_per_page The number of items to show per page (not used here)
1210
 * @param string $sort A string indicating how to sort the results
1211
 * @return array An array of info about the smileys
1212
 */
1213 View Code Duplication
function list_getSmileys($start, $items_per_page, $sort)
0 ignored issues
show
Duplication introduced by
This function 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...
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1214
{
1215
	global $smcFunc;
1216
1217
	$request = $smcFunc['db_query']('', '
1218
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1219
		FROM {db_prefix}smileys
1220
		ORDER BY {raw:sort}',
1221
		array(
1222
			'sort' => $sort,
1223
		)
1224
	);
1225
	$smileys = array();
1226
	while ($row = $smcFunc['db_fetch_assoc']($request))
1227
		$smileys[] = $row;
1228
	$smcFunc['db_free_result']($request);
1229
1230
	return $smileys;
1231
}
1232
1233
/**
1234
 * Callback function for createList().
1235
 * @return int The number of smileys
1236
 */
1237
function list_getNumSmileys()
1238
{
1239
	global $smcFunc;
1240
1241
	$request = $smcFunc['db_query']('', '
1242
		SELECT COUNT(*)
1243
		FROM {db_prefix}smileys',
1244
		array()
1245
	);
1246
	list($numSmileys) = $smcFunc['db_fetch_row'];
1247
	$smcFunc['db_free_result']($request);
1248
1249
	return $numSmileys;
1250
}
1251
1252
/**
1253
 * Allows to edit smileys order.
1254
 */
1255
function EditSmileyOrder()
1256
{
1257
	global $context, $txt, $smcFunc;
1258
1259
	// Move smileys to another position.
1260
	if (isset($_REQUEST['reorder']))
1261
	{
1262
		checkSession('get');
1263
1264
		$_GET['location'] = empty($_GET['location']) || $_GET['location'] != 'popup' ? 0 : 2;
1265
		$_GET['source'] = empty($_GET['source']) ? 0 : (int) $_GET['source'];
1266
1267
		if (empty($_GET['source']))
1268
			fatal_lang_error('smiley_not_found');
1269
1270
		if (!empty($_GET['after']))
1271
		{
1272
			$_GET['after'] = (int) $_GET['after'];
1273
1274
			$request = $smcFunc['db_query']('', '
1275
				SELECT smiley_row, smiley_order, hidden
1276
				FROM {db_prefix}smileys
1277
				WHERE hidden = {int:location}
1278
					AND id_smiley = {int:after_smiley}',
1279
				array(
1280
					'location' => $_GET['location'],
1281
					'after_smiley' => $_GET['after'],
1282
				)
1283
			);
1284
			if ($smcFunc['db_num_rows']($request) != 1)
1285
				fatal_lang_error('smiley_not_found');
1286
			list ($smiley_row, $smiley_order, $smileyLocation) = $smcFunc['db_fetch_row']($request);
1287
			$smcFunc['db_free_result']($request);
1288
		}
1289
		else
1290
		{
1291
			$smiley_row = (int) $_GET['row'];
1292
			$smiley_order = -1;
1293
			$smileyLocation = (int) $_GET['location'];
1294
		}
1295
1296
		$smcFunc['db_query']('', '
1297
			UPDATE {db_prefix}smileys
1298
			SET smiley_order = smiley_order + 1
1299
			WHERE hidden = {int:new_location}
1300
				AND smiley_row = {int:smiley_row}
1301
				AND smiley_order > {int:smiley_order}',
1302
			array(
1303
				'new_location' => $_GET['location'],
1304
				'smiley_row' => $smiley_row,
1305
				'smiley_order' => $smiley_order,
1306
			)
1307
		);
1308
1309
		$smcFunc['db_query']('', '
1310
			UPDATE {db_prefix}smileys
1311
			SET
1312
				smiley_order = {int:smiley_order} + 1,
1313
				smiley_row = {int:smiley_row},
1314
				hidden = {int:new_location}
1315
			WHERE id_smiley = {int:current_smiley}',
1316
			array(
1317
				'smiley_order' => $smiley_order,
1318
				'smiley_row' => $smiley_row,
1319
				'new_location' => $smileyLocation,
1320
				'current_smiley' => $_GET['source'],
1321
			)
1322
		);
1323
1324
		cache_put_data('parsing_smileys', null, 480);
1325
		cache_put_data('posting_smileys', null, 480);
1326
	}
1327
1328
	$request = $smcFunc['db_query']('', '
1329
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1330
		FROM {db_prefix}smileys
1331
		WHERE hidden != {int:popup}
1332
		ORDER BY smiley_order, smiley_row',
1333
		array(
1334
			'popup' => 1,
1335
		)
1336
	);
1337
	$context['smileys'] = array(
1338
		'postform' => array(
1339
			'rows' => array(),
1340
		),
1341
		'popup' => array(
1342
			'rows' => array(),
1343
		),
1344
	);
1345
	while ($row = $smcFunc['db_fetch_assoc']($request))
1346
	{
1347
		$location = empty($row['hidden']) ? 'postform' : 'popup';
1348
		$context['smileys'][$location]['rows'][$row['smiley_row']][] = array(
1349
			'id' => $row['id_smiley'],
1350
			'code' => $smcFunc['htmlspecialchars']($row['code']),
1351
			'filename' => $smcFunc['htmlspecialchars']($row['filename']),
1352
			'description' => $smcFunc['htmlspecialchars']($row['description']),
1353
			'row' => $row['smiley_row'],
1354
			'order' => $row['smiley_order'],
1355
			'selected' => !empty($_REQUEST['move']) && $_REQUEST['move'] == $row['id_smiley'],
1356
		);
1357
	}
1358
	$smcFunc['db_free_result']($request);
1359
1360
	$context['move_smiley'] = empty($_REQUEST['move']) ? 0 : (int) $_REQUEST['move'];
1361
1362
	// Make sure all rows are sequential.
1363
	foreach (array_keys($context['smileys']) as $location)
1364
		$context['smileys'][$location] = array(
1365
			'id' => $location,
1366
			'title' => $location == 'postform' ? $txt['smileys_location_form'] : $txt['smileys_location_popup'],
1367
			'description' => $location == 'postform' ? $txt['smileys_location_form_description'] : $txt['smileys_location_popup_description'],
1368
			'last_row' => count($context['smileys'][$location]['rows']),
1369
			'rows' => array_values($context['smileys'][$location]['rows']),
1370
		);
1371
1372
	// Check & fix smileys that are not ordered properly in the database.
1373
	foreach (array_keys($context['smileys']) as $location)
1374
	{
1375
		foreach ($context['smileys'][$location]['rows'] as $id => $smiley_row)
1376
		{
1377
			// Fix empty rows if any.
1378
			if ($id != $smiley_row[0]['row'])
1379
			{
1380
				$smcFunc['db_query']('', '
1381
					UPDATE {db_prefix}smileys
1382
					SET smiley_row = {int:new_row}
1383
					WHERE smiley_row = {int:current_row}
1384
						AND hidden = {int:location}',
1385
					array(
1386
						'new_row' => $id,
1387
						'current_row' => $smiley_row[0]['row'],
1388
						'location' => $location == 'postform' ? '0' : '2',
1389
					)
1390
				);
1391
				// Only change the first row value of the first smiley (we don't need the others :P).
1392
				$context['smileys'][$location]['rows'][$id][0]['row'] = $id;
1393
			}
1394
			// Make sure the smiley order is always sequential.
1395
			foreach ($smiley_row as $order_id => $smiley)
1396
				if ($order_id != $smiley['order'])
1397
					$smcFunc['db_query']('', '
1398
						UPDATE {db_prefix}smileys
1399
						SET smiley_order = {int:new_order}
1400
						WHERE id_smiley = {int:current_smiley}',
1401
						array(
1402
							'new_order' => $order_id,
1403
							'current_smiley' => $smiley['id'],
1404
						)
1405
					);
1406
		}
1407
	}
1408
1409
	cache_put_data('parsing_smileys', null, 480);
1410
	cache_put_data('posting_smileys', null, 480);
1411
}
1412
1413
/**
1414
 * Install a smiley set.
1415
 */
1416
function InstallSmileySet()
1417
{
1418
	global $sourcedir, $boarddir, $packagesdir, $modSettings, $smcFunc, $scripturl, $context, $txt, $user_info;
1419
1420
	isAllowedTo('manage_smileys');
1421
	checkSession('request');
1422
	// One of these two may be necessary
1423
	loadLanguage('Errors');
1424
	loadLanguage('Packages');
1425
1426
	require_once($sourcedir . '/Subs-Package.php');
1427
1428
	// Installing unless proven otherwise
1429
	$testing = false;
1430
1431
	if (isset($_REQUEST['set_gz']))
1432
	{
1433
		$base_name = strtr(basename($_REQUEST['set_gz']), ':/', '-_');
1434
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['set_gz']), '.'));
1435
		$context['filename'] = $base_name;
1436
1437
		// Check that the smiley is from simplemachines.org, for now... maybe add mirroring later.
1438
		// @ TODO: Our current xml files serve http links.  Allowing both for now until we serve https.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1439
		if (preg_match('~^https?://[\w_\-]+\.simplemachines\.org/~', $_REQUEST['set_gz']) == 0 || strpos($_REQUEST['set_gz'], 'dlattach') !== false)
1440
			fatal_lang_error('not_on_simplemachines');
1441
1442
		$destination = $packagesdir . '/' . $base_name;
1443
1444
		if (file_exists($destination))
1445
			fatal_lang_error('package_upload_error_exists');
1446
1447
		// Let's copy it to the Packages directory
1448
		file_put_contents($destination, fetch_web_data($_REQUEST['set_gz']));
1449
		$testing = true;
1450
	}
1451
	elseif (isset($_REQUEST['package']))
1452
	{
1453
		$base_name = basename($_REQUEST['package']);
1454
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['package']), '.'));
1455
		$context['filename'] = $base_name;
1456
1457
		$destination = $packagesdir . '/' . basename($_REQUEST['package']);
1458
	}
1459
1460
	if (empty($destination) || !file_exists($destination))
1461
		fatal_lang_error('package_no_file', false);
1462
1463
	// Make sure temp directory exists and is empty.
1464
	if (file_exists($packagesdir . '/temp'))
1465
		deltree($packagesdir . '/temp', false);
1466
1467
	if (!mktree($packagesdir . '/temp', 0755))
1468
	{
1469
		deltree($packagesdir . '/temp', false);
1470
		if (!mktree($packagesdir . '/temp', 0777))
1471
		{
1472
			deltree($packagesdir . '/temp', false);
1473
			// @todo not sure about url in destination_url
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1474
			create_chmod_control(array($packagesdir . '/temp/delme.tmp'), array('destination_url' => $scripturl . '?action=admin;area=smileys;sa=install;set_gz=' . $_REQUEST['set_gz'], 'crash_on_error' => true));
1475
1476
			deltree($packagesdir . '/temp', false);
1477
			if (!mktree($packagesdir . '/temp', 0777))
1478
				fatal_lang_error('package_cant_download', false);
1479
		}
1480
	}
1481
1482
	$extracted = read_tgz_file($destination, $packagesdir . '/temp');
0 ignored issues
show
Bug introduced by
The variable $destination does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1483
	if (!$extracted)
1484
		fatal_lang_error('packageget_unable', false, array('https://custom.simplemachines.org/mods/index.php?action=search;type=12;basic_search=' . $name));
0 ignored issues
show
Bug introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1485
	if ($extracted && !file_exists($packagesdir . '/temp/package-info.xml'))
1486
		foreach ($extracted as $file)
1487
			if (basename($file['filename']) == 'package-info.xml')
1488
			{
1489
				$base_path = dirname($file['filename']) . '/';
1490
				break;
1491
			}
1492
1493
	if (!isset($base_path))
1494
		$base_path = '';
1495
1496
	if (!file_exists($packagesdir . '/temp/' . $base_path . 'package-info.xml'))
1497
		fatal_lang_error('package_get_error_missing_xml', false);
1498
1499
	$smileyInfo = getPackageInfo($context['filename']);
1500
	if (!is_array($smileyInfo))
1501
		fatal_lang_error($smileyInfo);
1502
1503
	// See if it is installed?
1504
	$request = $smcFunc['db_query']('', '
1505
		SELECT version, themes_installed, db_changes
1506
		FROM {db_prefix}log_packages
1507
		WHERE package_id = {string:current_package}
1508
			AND install_state != {int:not_installed}
1509
		ORDER BY time_installed DESC
1510
		LIMIT 1',
1511
		array(
1512
			'not_installed'	=> 0,
1513
			'current_package' => $smileyInfo['id'],
1514
		)
1515
	);
1516
1517
	if ($smcFunc['db_num_rows']($request) > 0)
1518
		fatal_lang_error('package_installed_warning1');
1519
1520
	// Everything is fine, now it's time to do something
1521
	$actions = parsePackageInfo($smileyInfo['xml'], true, 'install');
1522
1523
	$context['post_url'] = $scripturl . '?action=admin;area=smileys;sa=install;package=' . $base_name;
0 ignored issues
show
Bug introduced by
The variable $base_name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1524
	$context['has_failure'] = false;
1525
	$context['actions'] = array();
1526
	$context['ftp_needed'] = false;
1527
1528
	foreach ($actions as $action)
1529
	{
1530
		if ($action['type'] == 'readme' || $action['type'] == 'license')
1531
		{
1532
			$type = 'package_' . $action['type'];
1533 View Code Duplication
			if (file_exists($packagesdir . '/temp/' . $base_path . $action['filename']))
1534
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($packagesdir . '/temp/' . $base_path . $action['filename']), "\n\r"));
1535
			elseif (file_exists($action['filename']))
1536
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($action['filename']), "\n\r"));
1537
1538
			if (!empty($action['parse_bbc']))
1539
			{
1540
				require_once($sourcedir . '/Subs-Post.php');
1541
				preparsecode($context[$type]);
1542
				$context[$type] = parse_bbc($context[$type]);
1543
			}
1544
			else
1545
				$context[$type] = nl2br($context[$type]);
1546
1547
			continue;
1548
		}
1549
		elseif ($action['type'] == 'require-dir')
1550
		{
1551
			// Do this one...
1552
			$thisAction = array(
1553
				'type' => $txt['package_extract'] . ' ' . ($action['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']),
1554
				'action' => $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.')))
1555
			);
1556
1557
			$file =  $packagesdir . '/temp/' . $base_path . $action['filename'];
1558
			if (isset($action['filename']) && (!file_exists($file) || !is_writable(dirname($action['destination']))))
1559
			{
1560
				$context['has_failure'] = true;
1561
1562
				$thisAction += array(
1563
					'description' => $txt['package_action_error'],
1564
					'failed' => true,
1565
				);
1566
			}
1567
			// @todo None given?
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1568 View Code Duplication
			if (empty($thisAction['description']))
1569
				$thisAction['description'] = isset($action['description']) ? $action['description'] : '';
1570
1571
			$context['actions'][] = $thisAction;
1572
		}
1573 View Code Duplication
		elseif ($action['type'] == 'credits')
1574
		{
1575
			// Time to build the billboard
1576
			$credits_tag = array(
1577
				'url' => $action['url'],
1578
				'license' => $action['license'],
1579
				'copyright' => $action['copyright'],
1580
				'title' => $action['title'],
1581
			);
1582
		}
1583
	}
1584
1585
	if ($testing)
1586
	{
1587
		$context['sub_template'] = 'view_package';
1588
		$context['uninstalling'] = false;
1589
		$context['is_installed'] = false;
1590
		$context['package_name'] = $smileyInfo['name'];
1591
		loadTemplate('Packages');
1592
	}
1593
	// Do the actual install
1594
	else
1595
	{
1596
		// @TODO Does this call have side effects? ($actions is not used)
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
1597
		$actions = parsePackageInfo($smileyInfo['xml'], false, 'install');
0 ignored issues
show
Unused Code introduced by
$actions 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...
1598
		foreach ($context['actions'] as $action)
1599
		{
1600
			updateSettings(array(
1601
				'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . basename($action['action']),
1602
				'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $smileyInfo['name'] . (count($context['actions']) > 1 ? ' ' .  (!empty($action['description']) ? $smcFunc['htmlspecialchars']($action['description']) : basename($action['action'])) : ''),
1603
			));
1604
		}
1605
1606
		package_flush_cache();
1607
1608
		// Credits tag?
1609
		$credits_tag = (empty($credits_tag)) ? '' : $smcFunc['json_encode']($credits_tag);
1610
		$smcFunc['db_insert']('',
1611
			'{db_prefix}log_packages',
1612
			array(
1613
				'filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string',
1614
				'id_member_installed' => 'int', 'member_installed' => 'string','time_installed' => 'int',
1615
				'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string',
1616
				'member_removed' => 'int', 'db_changes' => 'string', 'credits' => 'string',
1617
			),
1618
			array(
1619
				$smileyInfo['filename'], $smileyInfo['name'], $smileyInfo['id'], $smileyInfo['version'],
1620
				$user_info['id'], $user_info['name'], time(),
1621
				1, '', '',
1622
				0, '', $credits_tag,
1623
			),
1624
			array('id_install')
1625
		);
1626
1627
		logAction('install_package', array('package' => $smcFunc['htmlspecialchars']($smileyInfo['name']), 'version' => $smcFunc['htmlspecialchars']($smileyInfo['version'])), 'admin');
1628
1629
		cache_put_data('parsing_smileys', null, 480);
1630
		cache_put_data('posting_smileys', null, 480);
1631
	}
1632
1633
	if (file_exists($packagesdir . '/temp'))
1634
		deltree($packagesdir . '/temp');
1635
1636
	if (!$testing)
1637
		redirectexit('action=admin;area=smileys');
1638
}
1639
1640
/**
1641
 * A function to import new smileys from an existing directory into the database.
1642
 *
1643
 * @param string $smileyPath The path to the directory to import smileys from
1644
 */
1645
function ImportSmileys($smileyPath)
1646
{
1647
	global $modSettings, $smcFunc;
1648
1649
	if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir'] . '/' . $smileyPath))
1650
		fatal_lang_error('smiley_set_unable_to_import');
1651
1652
	$smileys = array();
1653
	$dir = dir($modSettings['smileys_dir'] . '/' . $smileyPath);
1654 View Code Duplication
	while ($entry = $dir->read())
1655
	{
1656
		if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png')))
1657
			$smileys[strtolower($entry)] = $entry;
1658
	}
1659
	$dir->close();
1660
1661
	// Exclude the smileys that are already in the database.
1662
	$request = $smcFunc['db_query']('', '
1663
		SELECT filename
1664
		FROM {db_prefix}smileys
1665
		WHERE filename IN ({array_string:smiley_list})',
1666
		array(
1667
			'smiley_list' => $smileys,
1668
		)
1669
	);
1670 View Code Duplication
	while ($row = $smcFunc['db_fetch_assoc']($request))
1671
		if (isset($smileys[strtolower($row['filename'])]))
1672
			unset($smileys[strtolower($row['filename'])]);
1673
	$smcFunc['db_free_result']($request);
1674
1675
	$request = $smcFunc['db_query']('', '
1676
		SELECT MAX(smiley_order)
1677
		FROM {db_prefix}smileys
1678
		WHERE hidden = {int:postform}
1679
			AND smiley_row = {int:first_row}',
1680
		array(
1681
			'postform' => 0,
1682
			'first_row' => 0,
1683
		)
1684
	);
1685
	list ($smiley_order) = $smcFunc['db_fetch_row']($request);
1686
	$smcFunc['db_free_result']($request);
1687
1688
	$new_smileys = array();
1689
	foreach ($smileys as $smiley)
1690
		if (strlen($smiley) <= 48)
1691
			$new_smileys[] = array(':' . strtok($smiley, '.') . ':', $smiley, strtok($smiley, '.'), 0, ++$smiley_order);
1692
1693
	if (!empty($new_smileys))
1694
	{
1695
		$smcFunc['db_insert']('',
1696
			'{db_prefix}smileys',
1697
			array(
1698
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'smiley_row' => 'int', 'smiley_order' => 'int',
1699
			),
1700
			$new_smileys,
1701
			array('id_smiley')
1702
		);
1703
1704
		cache_put_data('parsing_smileys', null, 480);
1705
		cache_put_data('posting_smileys', null, 480);
1706
	}
1707
}
1708
1709
/**
1710
 * Handles editing message icons
1711
 */
1712
function EditMessageIcons()
1713
{
1714
	global $context, $settings, $txt;
1715
	global $smcFunc, $scripturl, $sourcedir;
1716
1717
	// Get a list of icons.
1718
	$context['icons'] = array();
1719
	$request = $smcFunc['db_query']('', '
1720
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
1721
		FROM {db_prefix}message_icons AS m
1722
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1723
		WHERE ({query_see_board} OR b.id_board IS NULL)
1724
		ORDER BY m.icon_order',
1725
		array(
1726
		)
1727
	);
1728
	$last_icon = 0;
1729
	$trueOrder = 0;
1730
	while ($row = $smcFunc['db_fetch_assoc']($request))
1731
	{
1732
		$context['icons'][$row['id_icon']] = array(
1733
			'id' => $row['id_icon'],
1734
			'title' => $row['title'],
1735
			'filename' => $row['filename'],
1736
			'image_url' => $settings[file_exists($settings['theme_dir'] . '/images/post/' . $row['filename'] . '.png') ? 'actual_images_url' : 'default_images_url'] . '/post/' . $row['filename'] . '.png',
1737
			'board_id' => $row['id_board'],
1738
			'board' => empty($row['board_name']) ? $txt['icons_edit_icons_all_boards'] : $row['board_name'],
1739
			'order' => $row['icon_order'],
1740
			'true_order' => $trueOrder++,
1741
			'after' => $last_icon,
1742
		);
1743
		$last_icon = $row['id_icon'];
1744
	}
1745
	$smcFunc['db_free_result']($request);
1746
1747
	// Submitting a form?
1748
	if (isset($_POST['icons_save']) || isset($_POST['delete']))
1749
	{
1750
		checkSession();
1751
1752
		// Deleting icons?
1753
		if (isset($_POST['delete']) && !empty($_POST['checked_icons']))
1754
		{
1755
			$deleteIcons = array();
1756
			foreach ($_POST['checked_icons'] as $icon)
1757
				$deleteIcons[] = (int) $icon;
1758
1759
			// Do the actual delete!
1760
			$smcFunc['db_query']('', '
1761
				DELETE FROM {db_prefix}message_icons
1762
				WHERE id_icon IN ({array_int:icon_list})',
1763
				array(
1764
					'icon_list' => $deleteIcons,
1765
				)
1766
			);
1767
		}
1768
		// Editing/Adding an icon?
1769
		elseif ($context['sub_action'] == 'editicon' && isset($_GET['icon']))
1770
		{
1771
			$_GET['icon'] = (int) $_GET['icon'];
1772
1773
			// Do some preperation with the data... like check the icon exists *somewhere*
1774
			if (strpos($_POST['icon_filename'], '.png') !== false)
1775
				$_POST['icon_filename'] = substr($_POST['icon_filename'], 0, -4);
1776
			if (!file_exists($settings['default_theme_dir'] . '/images/post/' . $_POST['icon_filename'] . '.png'))
1777
				fatal_lang_error('icon_not_found');
1778
			// There is a 16 character limit on message icons...
1779
			elseif (strlen($_POST['icon_filename']) > 16)
1780
				fatal_lang_error('icon_name_too_long');
1781
			elseif ($_POST['icon_location'] == $_GET['icon'] && !empty($_GET['icon']))
1782
				fatal_lang_error('icon_after_itself');
1783
1784
			// First do the sorting... if this is an edit reduce the order of everything after it by one ;)
1785
			if ($_GET['icon'] != 0)
1786
			{
1787
				$oldOrder = $context['icons'][$_GET['icon']]['true_order'];
1788
				foreach ($context['icons'] as $id => $data)
1789
					if ($data['true_order'] > $oldOrder)
1790
						$context['icons'][$id]['true_order']--;
1791
			}
1792
1793
			// If there are no existing icons and this is a new one, set the id to 1 (mainly for non-mysql)
1794
			if (empty($_GET['icon']) && empty($context['icons']))
1795
				$_GET['icon'] = 1;
1796
1797
			// Get the new order.
1798
			$newOrder = $_POST['icon_location'] == 0 ? 0 : $context['icons'][$_POST['icon_location']]['true_order'] + 1;
1799
			// Do the same, but with the one that used to be after this icon, done to avoid conflict.
1800
			foreach ($context['icons'] as $id => $data)
1801
				if ($data['true_order'] >= $newOrder)
1802
					$context['icons'][$id]['true_order']++;
1803
1804
			// Finally set the current icon's position!
1805
			$context['icons'][$_GET['icon']]['true_order'] = $newOrder;
1806
1807
			// Simply replace the existing data for the other bits.
1808
			$context['icons'][$_GET['icon']]['title'] = $_POST['icon_description'];
1809
			$context['icons'][$_GET['icon']]['filename'] = $_POST['icon_filename'];
1810
			$context['icons'][$_GET['icon']]['board_id'] = (int) $_POST['icon_board'];
1811
1812
			// Do a huge replace ;)
1813
			$iconInsert = array();
1814
			$iconInsert_new = array();
1815
			foreach ($context['icons'] as $id => $icon)
1816
			{
1817
				if ($id != 0)
1818
				{
1819
					$iconInsert[] = array($id, $icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1820
				}
1821
				else
1822
				{
1823
					$iconInsert_new[] = array($icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1824
				}
1825
			}
1826
1827
			$smcFunc['db_insert']('replace',
1828
				'{db_prefix}message_icons',
1829
				array('id_icon' => 'int', 'id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1830
				$iconInsert,
1831
				array('id_icon')
1832
			);
1833
1834
			if (!empty($iconInsert_new))
1835
			{
1836
				$smcFunc['db_insert']('replace',
1837
					'{db_prefix}message_icons',
1838
					array('id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1839
					$iconInsert_new,
1840
					array('id_icon')
1841
				);
1842
			}
1843
		}
1844
1845
		// Unless we're adding a new thing, we'll escape
1846
		if (!isset($_POST['add']))
1847
			redirectexit('action=admin;area=smileys;sa=editicons');
1848
	}
1849
1850
	$context[$context['admin_menu_name']]['current_subsection'] = 'editicons';
1851
1852
	$listOptions = array(
1853
		'id' => 'message_icon_list',
1854
		'title' => $txt['icons_edit_message_icons'],
1855
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1856
		'get_items' => array(
1857
			'function' => 'list_getMessageIcons',
1858
		),
1859
		'no_items_label' => $txt['icons_no_entries'],
1860
		'columns' => array(
1861
			'icon' => array(
1862
				'data' => array(
1863
					'function' => function ($rowData) use ($settings, $smcFunc)
1864
					{
1865
						$images_url = $settings[file_exists(sprintf('%1$s/images/post/%2$s.png', $settings['theme_dir'], $rowData['filename'])) ? 'actual_images_url' : 'default_images_url'];
1866
						return sprintf('<img src="%1$s/post/%2$s.png" alt="%3$s">', $images_url, $rowData['filename'], $smcFunc['htmlspecialchars']($rowData['title']));
1867
					},
1868
					'class' => 'centercol',
1869
				),
1870
			),
1871
			'filename' => array(
1872
				'header' => array(
1873
					'value' => $txt['smileys_filename'],
1874
				),
1875
				'data' => array(
1876
					'sprintf' => array(
1877
						'format' => '%1$s.png',
1878
						'params' => array(
1879
							'filename' => true,
1880
						),
1881
					),
1882
				),
1883
			),
1884
			'tooltip' => array(
1885
				'header' => array(
1886
					'value' => $txt['smileys_description'],
1887
				),
1888
				'data' => array(
1889
					'db_htmlsafe' => 'title',
1890
				),
1891
			),
1892
			'board' => array(
1893
				'header' => array(
1894
					'value' => $txt['icons_board'],
1895
				),
1896
				'data' => array(
1897
					'function' => function ($rowData) use ($txt)
1898
					{
1899
						return empty($rowData['board_name']) ? $txt['icons_edit_icons_all_boards'] : $rowData['board_name'];
1900
					},
1901
				),
1902
			),
1903
			'modify' => array(
1904
				'header' => array(
1905
					'value' => $txt['smileys_modify'],
1906
					'class' => 'centercol',
1907
				),
1908
				'data' => array(
1909
					'sprintf' => array(
1910
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=editicon;icon=%1$s">' . $txt['smileys_modify'] . '</a>',
1911
						'params' => array(
1912
							'id_icon' => false,
1913
						),
1914
					),
1915
					'class' => 'centercol',
1916
				),
1917
			),
1918
			'check' => array(
1919
				'header' => array(
1920
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check">',
1921
					'class' => 'centercol',
1922
				),
1923
				'data' => array(
1924
					'sprintf' => array(
1925
						'format' => '<input type="checkbox" name="checked_icons[]" value="%1$d" class="input_check">',
1926
						'params' => array(
1927
							'id_icon' => false,
1928
						),
1929
					),
1930
					'class' => 'centercol',
1931
				),
1932
			),
1933
		),
1934
		'form' => array(
1935
			'href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1936
		),
1937
		'additional_rows' => array(
1938
			array(
1939
				'position' => 'below_table_data',
1940
				'value' => '<input type="submit" name="delete" value="' . $txt['quickmod_delete_selected'] . '" class="button_submit"> <a class="button_link" href="' . $scripturl . '?action=admin;area=smileys;sa=editicon">' . $txt['icons_add_new'] . '</a>',
1941
			),
1942
		),
1943
	);
1944
1945
	require_once($sourcedir . '/Subs-List.php');
1946
	createList($listOptions);
1947
1948
	// If we're adding/editing an icon we'll need a list of boards
1949
	if ($context['sub_action'] == 'editicon' || isset($_POST['add']))
1950
	{
1951
		// Force the sub_template just in case.
1952
		$context['sub_template'] = 'editicon';
1953
1954
		$context['new_icon'] = !isset($_GET['icon']);
1955
1956
		// Get the properties of the current icon from the icon list.
1957
		if (!$context['new_icon'])
1958
			$context['icon'] = $context['icons'][$_GET['icon']];
1959
1960
		// Get a list of boards needed for assigning this icon to a specific board.
1961
		$boardListOptions = array(
1962
			'use_permissions' => true,
1963
			'selected_board' => isset($context['icon']['board_id']) ? $context['icon']['board_id'] : 0,
1964
		);
1965
		require_once($sourcedir . '/Subs-MessageIndex.php');
1966
		$context['categories'] = getBoardList($boardListOptions);
1967
	}
1968
}
1969
1970
/**
1971
 * Callback function for createList().
1972
 *
1973
 * @param int $start The item to start with (not used here)
1974
 * @param int $items_per_page The number of items to display per page (not used here)
1975
 * @param string $sort A string indicating how to sort the items (not used here)
1976
 * @return array An array of information about message icons
1977
 */
1978 View Code Duplication
function list_getMessageIcons($start, $items_per_page, $sort)
0 ignored issues
show
Unused Code introduced by
The parameter $start is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $items_per_page is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $sort is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This function 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...
1979
{
1980
	global $smcFunc;
1981
1982
	$request = $smcFunc['db_query']('', '
1983
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
1984
		FROM {db_prefix}message_icons AS m
1985
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1986
		WHERE ({query_see_board} OR b.id_board IS NULL)
1987
		ORDER BY m.icon_order',
1988
		array()
1989
	);
1990
1991
	$message_icons = array();
1992
	while ($row = $smcFunc['db_fetch_assoc']($request))
1993
		$message_icons[] = $row;
1994
	$smcFunc['db_free_result']($request);
1995
1996
	return $message_icons;
1997
}
1998
1999
?>