Passed
Push — release-2.1 ( 0c2197...207d2d )
by Jeremy
05:47
created

ManageSmileys.php ➔ InstallSmileySet()   F

Complexity

Conditions 42
Paths > 20000

Size

Total Lines 223

Duplication

Lines 16
Ratio 7.17 %

Importance

Changes 0
Metric Value
cc 42
nc 429496.7295
nop 0
dl 16
loc 223
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 2018 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
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']]) ? $modSettings['smiley_sets_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_exts = explode(',', $modSettings['smiley_sets_exts']);
207
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
208
			foreach ($_POST['smiley_set'] as $id => $val)
209
			{
210
				// If this is the set you've marked as default, or the only one remaining, you can't delete it
211
				if ($modSettings['smiley_sets_default'] != $set_paths[$id] && count($set_paths) != 1 && isset($set_paths[$id], $set_names[$id]))
212
					unset($set_paths[$id], $set_names[$id], $set_exts[$id]);
213
			}
214
215
			// Shortcut... array_merge() on a single array resets the numeric keys
216
			$set_paths = array_merge($set_paths);
217
			$set_exts = array_merge($set_exts);
218
			$set_names = array_merge($set_names);
219
220
			updateSettings(array(
221
				'smiley_sets_known' => implode(',', $set_paths),
222
				'smiley_sets_exts' => implode(',', $set_exts),
223
				'smiley_sets_names' => implode("\n", $set_names),
224
				'smiley_sets_default' => in_array($modSettings['smiley_sets_default'], $set_paths) ? $modSettings['smiley_sets_default'] : $set_paths[0],
225
			));
226
		}
227
		// Add a new smiley set.
228
		elseif (!empty($_POST['add']))
229
			$context['sub_action'] = 'modifyset';
230
		// Create or modify a smiley set.
231
		elseif (isset($_POST['set']))
232
		{
233
			$set_paths = explode(',', $modSettings['smiley_sets_known']);
234
			$set_exts = explode(',', $modSettings['smiley_sets_exts']);
235
			$set_names = explode("\n", $modSettings['smiley_sets_names']);
236
237
			// Create a new smiley set.
238
			if ($_POST['set'] == -1 && isset($_POST['smiley_sets_path']))
239
			{
240
				if (in_array($_POST['smiley_sets_path'], $set_paths))
241
					fatal_lang_error('smiley_set_already_exists');
242
243
				updateSettings(array(
244
					'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . $_POST['smiley_sets_path'],
245
					'smiley_sets_exts' => $modSettings['smiley_sets_exts'] . ',' . $_POST['smiley_sets_ext'],
246
					'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $_POST['smiley_sets_name'],
247
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path'],
248
				));
249
			}
250
			// Modify an existing smiley set.
251
			else
252
			{
253
				// Make sure the smiley set exists.
254
				if (!isset($set_paths[$_POST['set']]) || !isset($set_names[$_POST['set']]))
255
					fatal_lang_error('smiley_set_not_found');
256
257
				// Make sure the path is not yet used by another smileyset.
258
				if (in_array($_POST['smiley_sets_path'], $set_paths) && $_POST['smiley_sets_path'] != $set_paths[$_POST['set']])
259
					fatal_lang_error('smiley_set_path_already_used');
260
261
				$set_paths[$_POST['set']] = $_POST['smiley_sets_path'];
262
				$set_exts[$_POST['set']] = $_POST['smiley_sets_ext'];
263
				$set_names[$_POST['set']] = $_POST['smiley_sets_name'];
264
				updateSettings(array(
265
					'smiley_sets_known' => implode(',', $set_paths),
266
					'smiley_sets_exts' => implode(',', $set_exts),
267
					'smiley_sets_names' => implode("\n", $set_names),
268
					'smiley_sets_default' => empty($_POST['smiley_sets_default']) ? $modSettings['smiley_sets_default'] : $_POST['smiley_sets_path']
269
				));
270
			}
271
272
			// The user might have checked to also import smileys.
273
			if (!empty($_POST['smiley_sets_import']))
274
				ImportSmileys($_POST['smiley_sets_path']);
275
		}
276
		cache_put_data('parsing_smileys', null, 480);
277
		cache_put_data('posting_smileys', null, 480);
278
	}
279
280
	// Load all available smileysets...
281
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
282
	$set_exts = explode(",", $modSettings['smiley_sets_exts']);
283
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
284
	foreach ($context['smiley_sets'] as $i => $set)
285
		$context['smiley_sets'][$i] = array(
286
			'id' => $i,
287
			'path' => $smcFunc['htmlspecialchars']($set),
288
			'ext' => $smcFunc['htmlspecialchars']($set_exts[$i]),
289
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
290
			'selected' => $set == $modSettings['smiley_sets_default']
291
		);
292
293
	// Importing any smileys from an existing set?
294
	if ($context['sub_action'] == 'import')
295
	{
296
		checkSession('get');
297
		validateToken('admin-mss', 'request');
298
299
		$_GET['set'] = (int) $_GET['set'];
300
301
		// Sanity check - then import.
302
		if (isset($context['smiley_sets'][$_GET['set']]))
303
			ImportSmileys(un_htmlspecialchars($context['smiley_sets'][$_GET['set']]['path']));
304
305
		// Force the process to continue.
306
		$context['sub_action'] = 'modifyset';
307
		$context['sub_template'] = 'modifyset';
308
	}
309
	// If we're modifying or adding a smileyset, some context info needs to be set.
310
	if ($context['sub_action'] == 'modifyset')
311
	{
312
		$_GET['set'] = !isset($_GET['set']) ? -1 : (int) $_GET['set'];
313
		if ($_GET['set'] == -1 || !isset($context['smiley_sets'][$_GET['set']]))
314
			$context['current_set'] = array(
315
				'id' => '-1',
316
				'path' => '',
317
				'ext' => '',
318
				'name' => '',
319
				'selected' => false,
320
				'is_new' => true,
321
			);
322
		else
323
		{
324
			$context['current_set'] = &$context['smiley_sets'][$_GET['set']];
325
			$context['current_set']['is_new'] = false;
326
327
			// Calculate whether there are any smileys in the directory that can be imported.
328
			if (!empty($modSettings['smiley_enable']) && !empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']))
329
			{
330
				$smileys = array();
331
				$dir = dir($modSettings['smileys_dir'] . '/' . $context['current_set']['path']);
332
				while ($entry = $dir->read())
333
				{
334
					// strip extension before comparison
335
					$filename = pathinfo($entry, PATHINFO_FILENAME);
336
					if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png', '.svg')))
337
						$smileys[strtolower($filename)] = $filename;
338
				}
339
				$dir->close();
340
341
				if (empty($smileys))
342
					fatal_lang_error('smiley_set_dir_not_found', false, array($context['current_set']['name']));
343
344
				// Exclude the smileys that are already in the database.
345
				$request = $smcFunc['db_query']('', '
346
					SELECT filename
347
					FROM {db_prefix}smileys
348
					WHERE filename IN ({array_string:smiley_list})',
349
					array(
350
						'smiley_list' => $smileys,
351
					)
352
				);
353
				while ($row = $smcFunc['db_fetch_assoc']($request))
354
					if (isset($smileys[strtolower($row['filename'])]))
355
						unset($smileys[strtolower($row['filename'])]);
356
				$smcFunc['db_free_result']($request);
357
358
				$context['current_set']['can_import'] = count($smileys);
359
				$context['current_set']['import_url'] = $scripturl . '?action=admin;area=smileys;sa=import;set=' . $context['current_set']['id'] . ';' . $context['session_var'] . '=' . $context['session_id'];
360
			}
361
		}
362
363
		// Retrieve all potential smiley set directories.
364
		$context['smiley_set_dirs'] = array();
365
		if (!empty($modSettings['smileys_dir']) && is_dir($modSettings['smileys_dir']))
366
		{
367
			$dir = dir($modSettings['smileys_dir']);
368
			while ($entry = $dir->read())
369
			{
370
				if (!in_array($entry, array('.', '..')) && is_dir($modSettings['smileys_dir'] . '/' . $entry))
371
					$context['smiley_set_dirs'][] = array(
372
						'id' => $entry,
373
						'path' => $modSettings['smileys_dir'] . '/' . $entry,
374
						'selectable' => $entry == $context['current_set']['path'] || !in_array($entry, explode(',', $modSettings['smiley_sets_known'])),
375
						'current' => $entry == $context['current_set']['path'],
376
					);
377
			}
378
			$dir->close();
379
		}
380
	}
381
382
	// This is our save haven.
383
	createToken('admin-mss', 'request');
384
385
	// In case we need to import smileys, we need to add the token in now.
386
	if (isset($context['current_set']['import_url']))
387
		$context['current_set']['import_url'] .= ';' . $context['admin-mss_token_var'] . '=' . $context['admin-mss_token'];
388
389
	$listOptions = array(
390
		'id' => 'smiley_set_list',
391
		'title' => $txt['smiley_sets'],
392
		'no_items_label' => $txt['smiley_sets_none'],
393
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
394
		'default_sort_col' => 'default',
395
		'get_items' => array(
396
			'function' => 'list_getSmileySets',
397
		),
398
		'get_count' => array(
399
			'function' => 'list_getNumSmileySets',
400
		),
401
		'columns' => array(
402
			'default' => array(
403
				'header' => array(
404
					'value' => $txt['smiley_sets_default'],
405
					'class' => 'centercol',
406
				),
407
				'data' => array(
408
					'function' => function ($rowData)
409
					{
410
						return $rowData['selected'] ? '<span class="generic_icons valid"></span>' : '';
411
					},
412
					'class' => 'centercol',
413
				),
414
				'sort' => array(
415
					'default' => 'selected DESC',
416
				),
417
			),
418
			'name' => array(
419
				'header' => array(
420
					'value' => $txt['smiley_sets_name'],
421
				),
422
				'data' => array(
423
					'db_htmlsafe' => 'name',
424
				),
425
				'sort' => array(
426
					'default' => 'name',
427
					'reverse' => 'name DESC',
428
				),
429
			),
430
			'ext' => array(
431
				'header' => array(
432
					'value' => $txt['smiley_sets_ext'],
433
				),
434
				'data' => array(
435
					'db_htmlsafe' => 'ext',
436
				),
437
				'sort' => array(
438
					'default' => 'ext',
439
					'reverse' => 'ext DESC',
440
				),
441
			),
442
			'url' => array(
443
				'header' => array(
444
					'value' => $txt['smiley_sets_url'],
445
				),
446
				'data' => array(
447
					'sprintf' => array(
448
						'format' => $modSettings['smileys_url'] . '/<strong>%1$s</strong>/...',
449
						'params' => array(
450
							'path' => true,
451
						),
452
					),
453
				),
454
				'sort' => array(
455
					'default' => 'path',
456
					'reverse' => 'path DESC',
457
				),
458
			),
459
			'modify' => array(
460
				'header' => array(
461
					'value' => $txt['smiley_set_modify'],
462
					'class' => 'centercol',
463
				),
464
				'data' => array(
465
					'sprintf' => array(
466
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset;set=%1$d">' . $txt['smiley_set_modify'] . '</a>',
467
						'params' => array(
468
							'id' => true,
469
						),
470
					),
471
					'class' => 'centercol',
472
				),
473
			),
474
			'check' => array(
475
				'header' => array(
476
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
477
					'class' => 'centercol',
478
				),
479
				'data' => array(
480
					'function' => function ($rowData)
481
					{
482
						return $rowData['selected'] ? '' : sprintf('<input type="checkbox" name="smiley_set[%1$d]">', $rowData['id']);
483
					},
484
					'class' => 'centercol',
485
				),
486
			),
487
		),
488
		'form' => array(
489
			'href' => $scripturl . '?action=admin;area=smileys;sa=editsets',
490
			'token' => 'admin-mss',
491
		),
492
		'additional_rows' => array(
493
			array(
494
				'position' => 'above_table_headers',
495
				'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 you_sure"> <a class="button" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
496
			),
497
			array(
498
				'position' => 'below_table_data',
499
				'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 you_sure"> <a class="button" href="' . $scripturl . '?action=admin;area=smileys;sa=modifyset' . '">' . $txt['smiley_sets_add'] . '</a> ',
500
			),
501
		),
502
	);
503
504
	require_once($sourcedir . '/Subs-List.php');
505
	createList($listOptions);
506
}
507
508
/**
509
 * Callback function for createList().
510
 * @todo to be moved to Subs-Smileys?
511
 *
512
 * @param int $start The item to start with (not used here)
513
 * @param int $items_per_page The number of items to show per page (not used here)
514
 * @param string $sort A string indicating how to sort the results
515
 * @return array An array of info about the smiley sets
516
 */
517
function list_getSmileySets($start, $items_per_page, $sort)
518
{
519
	global $modSettings;
520
521
	$known_sets = explode(',', $modSettings['smiley_sets_known']);
522
	$set_exts = explode(',', $modSettings['smiley_sets_exts']);
523
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
524
	$cols = array(
525
		'id' => array(),
526
		'selected' => array(),
527
		'path' => array(),
528
		'name' => array(),
529
		'ext' => array(),
530
	);
531
	foreach ($known_sets as $i => $set)
532
	{
533
		$cols['id'][] = $i;
534
		$cols['selected'][] = $i;
535
		$cols['path'][] = $set;
536
		$cols['name'][] = $set_names[$i];
537
		$cols['ext'][] = $set_exts[$i];
538
	}
539
	$sort_flag = strpos($sort, 'DESC') === false ? SORT_ASC : SORT_DESC;
540
	if (substr($sort, 0, 4) === 'name')
541
		array_multisort($cols['name'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['selected'], $cols['id'], $cols['ext']);
542
	elseif (substr($sort, 0, 3) === 'ext')
543
		array_multisort($cols['ext'], $sort_flag, SORT_REGULAR, $cols['name'], $cols['selected'], $cols['id'], $cols['path']);
544
	elseif (substr($sort, 0, 4) === 'path')
545
		array_multisort($cols['path'], $sort_flag, SORT_REGULAR, $cols['name'], $cols['selected'], $cols['id'], $cols['ext']);
546
	else
547
		array_multisort($cols['selected'], $sort_flag, SORT_REGULAR, $cols['path'], $cols['name'], $cols['id'], $cols['ext']);
548
549
	$smiley_sets = array();
550
	foreach ($cols['id'] as $i => $id)
551
		$smiley_sets[] = array(
552
			'id' => $id,
553
			'path' => $cols['path'][$i],
554
			'name' => $cols['name'][$i],
555
			'ext' => $cols['ext'][$i],
556
			'selected' => $cols['path'][$i] == $modSettings['smiley_sets_default']
557
		);
558
559
	return $smiley_sets;
560
}
561
562
/**
563
 * Callback function for createList().
564
 * @todo to be moved to Subs-Smileys?
565
 * @return int The total number of known smiley sets
566
 */
567
function list_getNumSmileySets()
568
{
569
	global $modSettings;
570
571
	return count(explode(',', $modSettings['smiley_sets_known']));
572
}
573
574
/**
575
 * Add a smiley, that's right.
576
 */
577
function AddSmiley()
578
{
579
	global $modSettings, $context, $txt, $boarddir, $smcFunc;
580
581
	// Get a list of all known smiley sets.
582
	$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
583
	$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
584
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
585
	$set_exts = explode(',', $modSettings['smiley_sets_exts']);
586
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
587
	foreach ($context['smiley_sets'] as $i => $set)
588
		$context['smiley_sets'][$i] = array(
589
			'id' => $i,
590
			'path' => $smcFunc['htmlspecialchars']($set),
591
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
592
			'ext' => $smcFunc['htmlspecialchars']($set_exts[$i]),
593
			'selected' => $set == $modSettings['smiley_sets_default']
594
		);
595
596
	// Submitting a form?
597
	if (isset($_POST[$context['session_var']], $_POST['smiley_code']))
598
	{
599
		checkSession();
600
601
		// Some useful arrays... types we allow - and ports we don't!
602
		$allowedTypes = array('jpeg', 'jpg', 'gif', 'png', 'bmp');
603
		$disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php');
604
605
		$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
606
		$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
607
		$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
608
609
		// Make sure some code was entered.
610
		if (empty($_POST['smiley_code']))
611
			fatal_lang_error('smiley_has_no_code');
612
613
		// Check whether the new code has duplicates. It should be unique.
614
		$request = $smcFunc['db_query']('', '
615
			SELECT id_smiley
616
			FROM {db_prefix}smileys
617
			WHERE code = {raw:mysql_binary_statement} {string:smiley_code}',
618
			array(
619
				'mysql_binary_statement' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
620
				'smiley_code' => $_POST['smiley_code'],
621
			)
622
		);
623
		if ($smcFunc['db_num_rows']($request) > 0)
624
			fatal_lang_error('smiley_not_unique');
625
		$smcFunc['db_free_result']($request);
626
627
		// If we are uploading - check all the smiley sets are writable!
628
		if ($_POST['method'] != 'existing')
629
		{
630
			$writeErrors = array();
631
			foreach ($context['smiley_sets'] as $set)
632
			{
633
				if (!is_writable($context['smileys_dir'] . '/' . un_htmlspecialchars($set['path'])))
634
					$writeErrors[] = $set['path'];
635
			}
636
			if (!empty($writeErrors))
637
				fatal_lang_error('smileys_upload_error_notwritable', true, array(implode(', ', $writeErrors)));
638
		}
639
640
		// Uploading just one smiley for all of them?
641
		if (isset($_POST['sameall']) && isset($_FILES['uploadSmiley']['name']) && $_FILES['uploadSmiley']['name'] != '')
642
		{
643
			if (!is_uploaded_file($_FILES['uploadSmiley']['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['uploadSmiley']['tmp_name'])))
644
				fatal_lang_error('smileys_upload_error');
645
646
			// Sorry, no spaces, dots, or anything else but letters allowed.
647
			$_FILES['uploadSmiley']['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['uploadSmiley']['name']);
648
649
			// We only allow image files - it's THAT simple - no messing around here...
650
			if (!in_array(strtolower(substr(strrchr($_FILES['uploadSmiley']['name'], '.'), 1)), $allowedTypes))
651
				fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
652
653
			// We only need the filename...
654
			$destName = basename($_FILES['uploadSmiley']['name']);
655
656
			// Make sure they aren't trying to upload a nasty file - for their own good here!
657
			if (in_array(strtolower($destName), $disabledFiles))
658
				fatal_lang_error('smileys_upload_error_illegal');
659
660
			// Check if the file already exists... and if not move it to EVERY smiley set directory.
661
			$i = 0;
662
			// Keep going until we find a set the file doesn't exist in. (or maybe it exists in all of them?)
663
			while (isset($context['smiley_sets'][$i]) && file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName))
664
				$i++;
665
666
			// Okay, we're going to put the smiley right here, since it's not there yet!
667
			if (isset($context['smiley_sets'][$i]['path']))
668
			{
669
				$smileyLocation = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
670
				move_uploaded_file($_FILES['uploadSmiley']['tmp_name'], $smileyLocation);
671
				smf_chmod($smileyLocation, 0644);
672
673
				// Now, we want to move it from there to all the other sets.
674
				for ($n = count($context['smiley_sets']); $i < $n; $i++)
675
				{
676
					$currentPath = $context['smileys_dir'] . '/' . un_htmlspecialchars($context['smiley_sets'][$i]['path']) . '/' . $destName;
677
678
					// The file is already there!  Don't overwrite it!
679
					if (file_exists($currentPath))
680
						continue;
681
682
					// Okay, so copy the first one we made to here.
683
					copy($smileyLocation, $currentPath);
684
					smf_chmod($currentPath, 0644);
685
				}
686
			}
687
688
			// Finally make sure it's saved correctly!
689
			$_POST['smiley_filename'] = $destName;
690
		}
691
		// What about uploading several files?
692
		elseif ($_POST['method'] != 'existing')
693
		{
694
			$newName = '';
695
			foreach ($_FILES as $name => $data)
696
			{
697
				if ($_FILES[$name]['name'] == '')
698
					fatal_lang_error('smileys_upload_error_blank');
699
700
				if (empty($newName))
701
					$newName = basename($_FILES[$name]['name']);
702
				elseif (basename($_FILES[$name]['name']) != $newName)
703
					fatal_lang_error('smileys_upload_error_name');
704
			}
705
706
			foreach ($context['smiley_sets'] as $i => $set)
707
			{
708
				$set['name'] = un_htmlspecialchars($set['name']);
709
				$set['path'] = un_htmlspecialchars($set['path']);
710
711
				if (!isset($_FILES['individual_' . $set['name']]['name']) || $_FILES['individual_' . $set['name']]['name'] == '')
712
					continue;
713
714
				// Got one...
715
				if (!is_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['individual_' . $set['name']]['tmp_name'])))
716
					fatal_lang_error('smileys_upload_error');
717
718
				// Sorry, no spaces, dots, or anything else but letters allowed.
719
				$_FILES['individual_' . $set['name']]['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['individual_' . $set['name']]['name']);
720
721
				// We only allow image files - it's THAT simple - no messing around here...
722
				if (!in_array(strtolower(substr(strrchr($_FILES['individual_' . $set['name']]['name'], '.'), 1)), $allowedTypes))
723
					fatal_lang_error('smileys_upload_error_types', false, array(implode(', ', $allowedTypes)));
724
725
				// We only need the filename...
726
				$destName = basename($_FILES['individual_' . $set['name']]['name']);
727
728
				// Make sure they aren't trying to upload a nasty file - for their own good here!
729
				if (in_array(strtolower($destName), $disabledFiles))
730
					fatal_lang_error('smileys_upload_error_illegal');
731
732
				// If the file exists - ignore it.
733
				$smileyLocation = $context['smileys_dir'] . '/' . $set['path'] . '/' . $destName;
734
				if (file_exists($smileyLocation))
735
					continue;
736
737
				// Finally - move the image!
738
				move_uploaded_file($_FILES['individual_' . $set['name']]['tmp_name'], $smileyLocation);
739
				smf_chmod($smileyLocation, 0644);
740
741
				// Should always be saved correctly!
742
				$_POST['smiley_filename'] = $destName;
743
			}
744
		}
745
746
		// Also make sure a filename was given.
747
		if (empty($_POST['smiley_filename']))
748
			fatal_lang_error('smiley_has_no_filename');
749
750
		// Find the position on the right.
751
		$smiley_order = '0';
752
		if ($_POST['smiley_location'] != 1)
753
		{
754
			$request = $smcFunc['db_query']('', '
755
				SELECT MAX(smiley_order) + 1
756
				FROM {db_prefix}smileys
757
				WHERE hidden = {int:smiley_location}
758
					AND smiley_row = {int:first_row}',
759
				array(
760
					'smiley_location' => $_POST['smiley_location'],
761
					'first_row' => 0,
762
				)
763
			);
764
			list ($smiley_order) = $smcFunc['db_fetch_row']($request);
765
			$smcFunc['db_free_result']($request);
766
767
			if (empty($smiley_order))
768
				$smiley_order = '0';
769
		}
770
		$smcFunc['db_insert']('',
771
			'{db_prefix}smileys',
772
			array(
773
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'hidden' => 'int', 'smiley_order' => 'int',
774
			),
775
			array(
776
				$_POST['smiley_code'], $_POST['smiley_filename'], $_POST['smiley_description'], $_POST['smiley_location'], $smiley_order,
777
			),
778
			array('id_smiley')
779
		);
780
781
		cache_put_data('parsing_smileys', null, 480);
782
		cache_put_data('posting_smileys', null, 480);
783
784
		// No errors? Out of here!
785
		redirectexit('action=admin;area=smileys;sa=editsmileys');
786
	}
787
788
	$context['selected_set'] = $modSettings['smiley_sets_default'];
789
790
	// Get all possible filenames for the smileys.
791
	$context['filenames'] = array();
792
	if ($context['smileys_dir_found'])
793
	{
794
		foreach ($context['smiley_sets'] as $smiley_set)
795
		{
796
			if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
797
				continue;
798
799
			$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
800
			while ($entry = $dir->read())
801
			{
802
				// Strip extension
803
				$filename = pathinfo($entry, PATHINFO_FILENAME);
804
				if (!in_array($filename, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png', '.svg')))
805
					$context['filenames'][strtolower($filename)] = array(
806
						'id' => $smcFunc['htmlspecialchars']($filename),
807
						'selected' => false,
808
					);
809
			}
810
			$dir->close();
811
		}
812
		ksort($context['filenames']);
813
	}
814
815
	// Create a new smiley from scratch.
816
	$context['filenames'] = array_values($context['filenames']);
817
	$context['current_smiley'] = array(
818
		'id' => 0,
819
		'code' => '',
820
		'filename' => $context['filenames'][0]['id'],
821
		'description' => $txt['smileys_default_description'],
822
		'location' => 0,
823
		'is_new' => true,
824
	);
825
}
826
827
/**
828
 * Add, remove, edit smileys.
829
 */
830
function EditSmileys()
831
{
832
	global $modSettings, $context, $txt, $boarddir;
833
	global $smcFunc, $scripturl, $sourcedir;
834
835
	// Force the correct tab to be displayed.
836
	$context[$context['admin_menu_name']]['current_subsection'] = 'editsmileys';
837
838
	// Submitting a form?
839
	if (isset($_POST['smiley_save']) || isset($_POST['smiley_action']))
840
	{
841
		checkSession();
842
843
		// Changing the selected smileys?
844
		if (isset($_POST['smiley_action']) && !empty($_POST['checked_smileys']))
845
		{
846
			foreach ($_POST['checked_smileys'] as $id => $smiley_id)
847
				$_POST['checked_smileys'][$id] = (int) $smiley_id;
848
849
			if ($_POST['smiley_action'] == 'delete')
850
				$smcFunc['db_query']('', '
851
					DELETE FROM {db_prefix}smileys
852
					WHERE id_smiley IN ({array_int:checked_smileys})',
853
					array(
854
						'checked_smileys' => $_POST['checked_smileys'],
855
					)
856
				);
857
			// Changing the status of the smiley?
858
			else
859
			{
860
				// Check it's a valid type.
861
				$displayTypes = array(
862
					'post' => 0,
863
					'hidden' => 1,
864
					'popup' => 2
865
				);
866
				if (isset($displayTypes[$_POST['smiley_action']]))
867
					$smcFunc['db_query']('', '
868
						UPDATE {db_prefix}smileys
869
						SET hidden = {int:display_type}
870
						WHERE id_smiley IN ({array_int:checked_smileys})',
871
						array(
872
							'checked_smileys' => $_POST['checked_smileys'],
873
							'display_type' => $displayTypes[$_POST['smiley_action']],
874
						)
875
					);
876
			}
877
		}
878
		// Create/modify a smiley.
879
		elseif (isset($_POST['smiley']))
880
		{
881
			// Is it a delete?
882
			if (!empty($_POST['deletesmiley']))
883
			{
884
				$smcFunc['db_query']('', '
885
					DELETE FROM {db_prefix}smileys
886
					WHERE id_smiley = {int:current_smiley}',
887
					array(
888
						'current_smiley' => $_POST['smiley'],
889
					)
890
				);
891
			}
892
			// Otherwise an edit.
893
			else
894
			{
895
				$_POST['smiley'] = (int) $_POST['smiley'];
896
				$_POST['smiley_code'] = htmltrim__recursive($_POST['smiley_code']);
897
				$_POST['smiley_filename'] = htmltrim__recursive($_POST['smiley_filename']);
898
				$_POST['smiley_location'] = empty($_POST['smiley_location']) || $_POST['smiley_location'] > 2 || $_POST['smiley_location'] < 0 ? 0 : (int) $_POST['smiley_location'];
899
900
				// Make sure some code was entered.
901
				if (empty($_POST['smiley_code']))
902
					fatal_lang_error('smiley_has_no_code');
903
904
				// Also make sure a filename was given.
905
				if (empty($_POST['smiley_filename']))
906
					fatal_lang_error('smiley_has_no_filename');
907
908
				// Check whether the new code has duplicates. It should be unique.
909
				$request = $smcFunc['db_query']('', '
910
					SELECT id_smiley
911
					FROM {db_prefix}smileys
912
					WHERE code = {raw:mysql_binary_type} {string:smiley_code}' . (empty($_POST['smiley']) ? '' : '
913
						AND id_smiley != {int:current_smiley}'),
914
					array(
915
						'current_smiley' => $_POST['smiley'],
916
						'mysql_binary_type' => $smcFunc['db_title'] == 'MySQL' ? 'BINARY' : '',
917
						'smiley_code' => $_POST['smiley_code'],
918
					)
919
				);
920
				if ($smcFunc['db_num_rows']($request) > 0)
921
					fatal_lang_error('smiley_not_unique');
922
				$smcFunc['db_free_result']($request);
923
924
				$smcFunc['db_query']('', '
925
					UPDATE {db_prefix}smileys
926
					SET
927
						code = {string:smiley_code},
928
						filename = {string:smiley_filename},
929
						description = {string:smiley_description},
930
						hidden = {int:smiley_location}
931
					WHERE id_smiley = {int:current_smiley}',
932
					array(
933
						'smiley_location' => $_POST['smiley_location'],
934
						'current_smiley' => $_POST['smiley'],
935
						'smiley_code' => $_POST['smiley_code'],
936
						'smiley_filename' => $_POST['smiley_filename'],
937
						'smiley_description' => $_POST['smiley_description'],
938
					)
939
				);
940
			}
941
		}
942
943
		cache_put_data('parsing_smileys', null, 480);
944
		cache_put_data('posting_smileys', null, 480);
945
	}
946
947
	// Load all known smiley sets.
948
	$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
949
	$set_exts = explode(',', $modSettings['smiley_sets_exts']);
950
	$set_names = explode("\n", $modSettings['smiley_sets_names']);
951
	foreach ($context['smiley_sets'] as $i => $set)
952
		$context['smiley_sets'][$i] = array(
953
			'id' => $i,
954
			'path' => $smcFunc['htmlspecialchars']($set),
955
			'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
956
			'ext' => $smcFunc['htmlspecialchars']($set_exts[$i]),
957
			'selected' => $set == $modSettings['smiley_sets_default']
958
		);
959
960
	// Prepare overview of all (custom) smileys.
961
	if ($context['sub_action'] == 'editsmileys')
962
	{
963
		// Determine the language specific sort order of smiley locations.
964
		$smiley_locations = array(
965
			$txt['smileys_location_form'],
966
			$txt['smileys_location_hidden'],
967
			$txt['smileys_location_popup'],
968
		);
969
		asort($smiley_locations);
970
971
		// Create a list of options for selecting smiley sets.
972
		$smileyset_option_list = '
973
			<select name="set" onchange="changeSet(this.options[this.selectedIndex].value);">';
974
		foreach ($context['smiley_sets'] as $smiley_set)
975
			$smileyset_option_list .= '
976
				<option value="' . $smiley_set['path'] . '"' . ($modSettings['smiley_sets_default'] == $smiley_set['path'] ? ' selected' : '') . '>' . $smiley_set['name'] . '</option>';
977
		$smileyset_option_list .= '
978
			</select>';
979
980
		$listOptions = array(
981
			'id' => 'smiley_list',
982
			'title' => $txt['smileys_edit'],
983
			'items_per_page' => 40,
984
			'base_href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
985
			'default_sort_col' => 'filename',
986
			'get_items' => array(
987
				'function' => 'list_getSmileys',
988
			),
989
			'get_count' => array(
990
				'function' => 'list_getNumSmileys',
991
			),
992
			'no_items_label' => $txt['smileys_no_entries'],
993
			'columns' => array(
994
				'picture' => array(
995
					'data' => array(
996
						'sprintf' => array(
997
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d"><img src="' . $modSettings['smileys_url'] . '/' . $modSettings['smiley_sets_default'] . '/%2$s' . $context['user']['smiley_set_default_ext'] . '" alt="%3$s" style="padding: 2px;" id="smiley%1$d"><input type="hidden" name="smileys[%1$d][filename]" value="%2$s"></a>',
998
							'params' => array(
999
								'id_smiley' => false,
1000
								'filename' => true,
1001
								'description' => true,
1002
							),
1003
						),
1004
						'class' => 'centercol',
1005
					),
1006
				),
1007
				'code' => array(
1008
					'header' => array(
1009
						'value' => $txt['smileys_code'],
1010
					),
1011
					'data' => array(
1012
						'db_htmlsafe' => 'code',
1013
					),
1014
					'sort' => array(
1015
						'default' => 'code',
1016
						'reverse' => 'code DESC',
1017
					),
1018
				),
1019
				'filename' => array(
1020
					'header' => array(
1021
						'value' => $txt['smileys_filename'],
1022
					),
1023
					'data' => array(
1024
						'db_htmlsafe' => 'filename',
1025
					),
1026
					'sort' => array(
1027
						'default' => 'filename',
1028
						'reverse' => 'filename DESC',
1029
					),
1030
				),
1031
				'location' => array(
1032
					'header' => array(
1033
						'value' => $txt['smileys_location'],
1034
					),
1035
					'data' => array(
1036
						'function' => function ($rowData) use ($txt)
1037
						{
1038
							if (empty($rowData['hidden']))
1039
								return $txt['smileys_location_form'];
1040
							elseif ($rowData['hidden'] == 1)
1041
								return $txt['smileys_location_hidden'];
1042
							else
1043
								return $txt['smileys_location_popup'];
1044
						},
1045
					),
1046
					'sort' => array(
1047
						'default' => $smcFunc['db_custom_order']('hidden', array_keys($smiley_locations)) ,
1048
						'reverse' => $smcFunc['db_custom_order']('hidden', array_keys($smiley_locations), true),
1049
					),
1050
				),
1051
				'tooltip' => array(
1052
					'header' => array(
1053
						'value' => $txt['smileys_description'],
1054
					),
1055
					'data' => array(
1056
						'function' => function ($rowData) use ($context, $txt, $modSettings, $smcFunc)
1057
						{
1058
							if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir']))
1059
								return $smcFunc['htmlspecialchars']($rowData['description']);
1060
1061
							// Check if there are smileys missing in some sets.
1062
							$missing_sets = array();
1063
							foreach ($context['smiley_sets'] as $smiley_set)
1064
								if (!file_exists(sprintf('%1$s/%2$s/%3$s', $modSettings['smileys_dir'], $smiley_set['path'], $rowData['filename'])))
1065
									$missing_sets[] = $smiley_set['path'];
1066
1067
							$description = $smcFunc['htmlspecialchars']($rowData['description']);
1068
1069
							if (!empty($missing_sets))
1070
								$description .= sprintf('<br><span class="smalltext"><strong>%1$s:</strong> %2$s</span>', $txt['smileys_not_found_in_set'], implode(', ', $missing_sets));
1071
1072
							return $description;
1073
						},
1074
					),
1075
					'sort' => array(
1076
						'default' => 'description',
1077
						'reverse' => 'description DESC',
1078
					),
1079
				),
1080
				'modify' => array(
1081
					'header' => array(
1082
						'value' => $txt['smileys_modify'],
1083
						'class' => 'centercol',
1084
					),
1085
					'data' => array(
1086
						'sprintf' => array(
1087
							'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=modifysmiley;smiley=%1$d">' . $txt['smileys_modify'] . '</a>',
1088
							'params' => array(
1089
								'id_smiley' => false,
1090
							),
1091
						),
1092
						'class' => 'centercol',
1093
					),
1094
				),
1095
				'check' => array(
1096
					'header' => array(
1097
						'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
1098
						'class' => 'centercol',
1099
					),
1100
					'data' => array(
1101
						'sprintf' => array(
1102
							'format' => '<input type="checkbox" name="checked_smileys[]" value="%1$d">',
1103
							'params' => array(
1104
								'id_smiley' => false,
1105
							),
1106
						),
1107
						'class' => 'centercol',
1108
					),
1109
				),
1110
			),
1111
			'form' => array(
1112
				'href' => $scripturl . '?action=admin;area=smileys;sa=editsmileys',
1113
				'name' => 'smileyForm',
1114
			),
1115
			'additional_rows' => array(
1116
				array(
1117
					'position' => 'above_column_headers',
1118
					'value' => $smileyset_option_list,
1119
					'class' => 'righttext',
1120
				),
1121
				array(
1122
					'position' => 'below_table_data',
1123
					'value' => '
1124
						<select name="smiley_action" onchange="makeChanges(this.value);">
1125
							<option value="-1">' . $txt['smileys_with_selected'] . ':</option>
1126
							<option value="-1" disabled>--------------</option>
1127
							<option value="hidden">' . $txt['smileys_make_hidden'] . '</option>
1128
							<option value="post">' . $txt['smileys_show_on_post'] . '</option>
1129
							<option value="popup">' . $txt['smileys_show_on_popup'] . '</option>
1130
							<option value="delete">' . $txt['smileys_remove'] . '</option>
1131
						</select>
1132
						<noscript>
1133
							<input type="submit" name="perform_action" value="' . $txt['go'] . '" class="button">
1134
						</noscript>',
1135
					'class' => 'righttext',
1136
				),
1137
			),
1138
			'javascript' => '
1139
				function makeChanges(action)
1140
				{
1141
					if (action == \'-1\')
1142
						return false;
1143
					else if (action == \'delete\')
1144
					{
1145
						if (confirm(\'' . $txt['smileys_confirm'] . '\'))
1146
							document.forms.smileyForm.submit();
1147
					}
1148
					else
1149
						document.forms.smileyForm.submit();
1150
					return true;
1151
				}
1152
				function changeSet(newSet)
1153
				{
1154
					var currentImage, i, knownSmileys = [];
1155
					let extsarr = smf_smiley_sets_exts.split(",");
1156
					let index = document.getElementsByName("set")[0].selectedIndex;
1157
1158
					if (knownSmileys.length == 0)
1159
					{
1160
						for (var i = 0, n = document.images.length; i < n; i++)
1161
							if (document.images[i].id.substr(0, 6) == \'smiley\')
1162
								knownSmileys[knownSmileys.length] = document.images[i].id.substr(6);
1163
					}
1164
1165
					for (i = 0; i < knownSmileys.length; i++)
1166
					{
1167
						currentImage = document.getElementById("smiley" + knownSmileys[i]);
1168
						currentImage.src = "' . $modSettings['smileys_url'] . '/" + newSet + "/" + document.forms.smileyForm["smileys[" + knownSmileys[i] + "][filename]"].value + extsarr[index];
1169
					}
1170
				}',
1171
		);
1172
1173
		require_once($sourcedir . '/Subs-List.php');
1174
		createList($listOptions);
1175
1176
		// The list is the only thing to show, so make it the main template.
1177
		$context['default_list'] = 'smiley_list';
1178
		$context['sub_template'] = 'show_list';
1179
	}
1180
	// Modifying smileys.
1181
	elseif ($context['sub_action'] == 'modifysmiley')
1182
	{
1183
		// Get a list of all known smiley sets.
1184
		$context['smileys_dir'] = empty($modSettings['smileys_dir']) ? $boarddir . '/Smileys' : $modSettings['smileys_dir'];
1185
		$context['smileys_dir_found'] = is_dir($context['smileys_dir']);
1186
		$context['smiley_sets'] = explode(',', $modSettings['smiley_sets_known']);
1187
		$set_exts = explode(',', $modSettings['smiley_sets_exts']);
1188
		$set_names = explode("\n", $modSettings['smiley_sets_names']);
1189
		foreach ($context['smiley_sets'] as $i => $set)
1190
			$context['smiley_sets'][$i] = array(
1191
				'id' => $i,
1192
				'path' => $smcFunc['htmlspecialchars']($set),
1193
				'name' => $smcFunc['htmlspecialchars']($set_names[$i]),
1194
				'ext' => $smcFunc['htmlspecialchars']($set_exts[$i]),
1195
				'selected' => $set == $modSettings['smiley_sets_default']
1196
			);
1197
1198
		$context['selected_set'] = $modSettings['smiley_sets_default'];
1199
1200
		// Get all possible filenames for the smileys.
1201
		$context['filenames'] = array();
1202
		if ($context['smileys_dir_found'])
1203
		{
1204
			foreach ($context['smiley_sets'] as $smiley_set)
1205
			{
1206
				if (!file_exists($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path'])))
1207
					continue;
1208
1209
				$dir = dir($context['smileys_dir'] . '/' . un_htmlspecialchars($smiley_set['path']));
1210
				while ($entry = $dir->read())
1211
				{
1212
					// Strip extension
1213
					$filename = pathinfo($entry, PATHINFO_FILENAME);
1214
					if (!in_array($filename, $context['filenames']) && in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png', '.svg')))
1215
						$context['filenames'][strtolower($filename)] = array(
1216
							'id' => $smcFunc['htmlspecialchars']($filename),
1217
							'selected' => false,
1218
						);
1219
				}
1220
				$dir->close();
1221
			}
1222
			ksort($context['filenames']);
1223
		}
1224
1225
		$request = $smcFunc['db_query']('', '
1226
			SELECT id_smiley AS id, code, filename, description, hidden AS location, 0 AS is_new
1227
			FROM {db_prefix}smileys
1228
			WHERE id_smiley = {int:current_smiley}',
1229
			array(
1230
				'current_smiley' => (int) $_REQUEST['smiley'],
1231
			)
1232
		);
1233
		if ($smcFunc['db_num_rows']($request) != 1)
1234
			fatal_lang_error('smiley_not_found');
1235
		$context['current_smiley'] = $smcFunc['db_fetch_assoc']($request);
1236
		$smcFunc['db_free_result']($request);
1237
1238
		$context['current_smiley']['code'] = $smcFunc['htmlspecialchars']($context['current_smiley']['code']);
1239
		$context['current_smiley']['filename'] = $smcFunc['htmlspecialchars']($context['current_smiley']['filename']);
1240
		$context['current_smiley']['description'] = $smcFunc['htmlspecialchars']($context['current_smiley']['description']);
1241
1242
		if (isset($context['filenames'][strtolower($context['current_smiley']['filename'])]))
1243
			$context['filenames'][strtolower($context['current_smiley']['filename'])]['selected'] = true;
1244
	}
1245
}
1246
1247
/**
1248
 * Callback function for createList().
1249
 *
1250
 * @param int $start The item to start with (not used here)
1251
 * @param int $items_per_page The number of items to show per page (not used here)
1252
 * @param string $sort A string indicating how to sort the results
1253
 * @return array An array of info about the smileys
1254
 */
1255
function list_getSmileys($start, $items_per_page, $sort)
1256
{
1257
	global $smcFunc;
1258
1259
	$request = $smcFunc['db_query']('', '
1260
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1261
		FROM {db_prefix}smileys
1262
		ORDER BY {raw:sort}',
1263
		array(
1264
			'sort' => $sort,
1265
		)
1266
	);
1267
	$smileys = array();
1268
	while ($row = $smcFunc['db_fetch_assoc']($request))
1269
		$smileys[] = $row;
1270
	$smcFunc['db_free_result']($request);
1271
1272
	return $smileys;
1273
}
1274
1275
/**
1276
 * Callback function for createList().
1277
 * @return int The number of smileys
1278
 */
1279
function list_getNumSmileys()
1280
{
1281
	global $smcFunc;
1282
1283
	$request = $smcFunc['db_query']('', '
1284
		SELECT COUNT(*)
1285
		FROM {db_prefix}smileys',
1286
		array()
1287
	);
1288
	list($numSmileys) = $smcFunc['db_fetch_row'];
1289
	$smcFunc['db_free_result']($request);
1290
1291
	return $numSmileys;
1292
}
1293
1294
/**
1295
 * Allows to edit smileys order.
1296
 */
1297
function EditSmileyOrder()
1298
{
1299
	global $context, $txt, $smcFunc;
1300
1301
	// Move smileys to another position.
1302
	if (isset($_REQUEST['reorder']))
1303
	{
1304
		checkSession('get');
1305
1306
		$_GET['location'] = empty($_GET['location']) || $_GET['location'] != 'popup' ? 0 : 2;
1307
		$_GET['source'] = empty($_GET['source']) ? 0 : (int) $_GET['source'];
1308
1309
		if (empty($_GET['source']))
1310
			fatal_lang_error('smiley_not_found');
1311
1312
		if (!empty($_GET['after']))
1313
		{
1314
			$_GET['after'] = (int) $_GET['after'];
1315
1316
			$request = $smcFunc['db_query']('', '
1317
				SELECT smiley_row, smiley_order, hidden
1318
				FROM {db_prefix}smileys
1319
				WHERE hidden = {int:location}
1320
					AND id_smiley = {int:after_smiley}',
1321
				array(
1322
					'location' => $_GET['location'],
1323
					'after_smiley' => $_GET['after'],
1324
				)
1325
			);
1326
			if ($smcFunc['db_num_rows']($request) != 1)
1327
				fatal_lang_error('smiley_not_found');
1328
			list ($smiley_row, $smiley_order, $smileyLocation) = $smcFunc['db_fetch_row']($request);
1329
			$smcFunc['db_free_result']($request);
1330
		}
1331
		else
1332
		{
1333
			$smiley_row = (int) $_GET['row'];
1334
			$smiley_order = -1;
1335
			$smileyLocation = (int) $_GET['location'];
1336
		}
1337
1338
		$smcFunc['db_query']('', '
1339
			UPDATE {db_prefix}smileys
1340
			SET smiley_order = smiley_order + 1
1341
			WHERE hidden = {int:new_location}
1342
				AND smiley_row = {int:smiley_row}
1343
				AND smiley_order > {int:smiley_order}',
1344
			array(
1345
				'new_location' => $_GET['location'],
1346
				'smiley_row' => $smiley_row,
1347
				'smiley_order' => $smiley_order,
1348
			)
1349
		);
1350
1351
		$smcFunc['db_query']('', '
1352
			UPDATE {db_prefix}smileys
1353
			SET
1354
				smiley_order = {int:smiley_order} + 1,
1355
				smiley_row = {int:smiley_row},
1356
				hidden = {int:new_location}
1357
			WHERE id_smiley = {int:current_smiley}',
1358
			array(
1359
				'smiley_order' => $smiley_order,
1360
				'smiley_row' => $smiley_row,
1361
				'new_location' => $smileyLocation,
1362
				'current_smiley' => $_GET['source'],
1363
			)
1364
		);
1365
1366
		cache_put_data('parsing_smileys', null, 480);
1367
		cache_put_data('posting_smileys', null, 480);
1368
	}
1369
1370
	$request = $smcFunc['db_query']('', '
1371
		SELECT id_smiley, code, filename, description, smiley_row, smiley_order, hidden
1372
		FROM {db_prefix}smileys
1373
		WHERE hidden != {int:popup}
1374
		ORDER BY smiley_order, smiley_row',
1375
		array(
1376
			'popup' => 1,
1377
		)
1378
	);
1379
	$context['smileys'] = array(
1380
		'postform' => array(
1381
			'rows' => array(),
1382
		),
1383
		'popup' => array(
1384
			'rows' => array(),
1385
		),
1386
	);
1387
	while ($row = $smcFunc['db_fetch_assoc']($request))
1388
	{
1389
		$location = empty($row['hidden']) ? 'postform' : 'popup';
1390
		$context['smileys'][$location]['rows'][$row['smiley_row']][] = array(
1391
			'id' => $row['id_smiley'],
1392
			'code' => $smcFunc['htmlspecialchars']($row['code']),
1393
			'filename' => $smcFunc['htmlspecialchars']($row['filename'] . $context['user']['smiley_set_default_ext']),
1394
			'description' => $smcFunc['htmlspecialchars']($row['description']),
1395
			'row' => $row['smiley_row'],
1396
			'order' => $row['smiley_order'],
1397
			'selected' => !empty($_REQUEST['move']) && $_REQUEST['move'] == $row['id_smiley'],
1398
		);
1399
	}
1400
	$smcFunc['db_free_result']($request);
1401
1402
	$context['move_smiley'] = empty($_REQUEST['move']) ? 0 : (int) $_REQUEST['move'];
1403
1404
	// Make sure all rows are sequential.
1405
	foreach (array_keys($context['smileys']) as $location)
1406
		$context['smileys'][$location] = array(
1407
			'id' => $location,
1408
			'title' => $location == 'postform' ? $txt['smileys_location_form'] : $txt['smileys_location_popup'],
1409
			'description' => $location == 'postform' ? $txt['smileys_location_form_description'] : $txt['smileys_location_popup_description'],
1410
			'last_row' => count($context['smileys'][$location]['rows']),
1411
			'rows' => array_values($context['smileys'][$location]['rows']),
1412
		);
1413
1414
	// Check & fix smileys that are not ordered properly in the database.
1415
	foreach (array_keys($context['smileys']) as $location)
1416
	{
1417
		foreach ($context['smileys'][$location]['rows'] as $id => $smiley_row)
1418
		{
1419
			// Fix empty rows if any.
1420
			if ($id != $smiley_row[0]['row'])
1421
			{
1422
				$smcFunc['db_query']('', '
1423
					UPDATE {db_prefix}smileys
1424
					SET smiley_row = {int:new_row}
1425
					WHERE smiley_row = {int:current_row}
1426
						AND hidden = {int:location}',
1427
					array(
1428
						'new_row' => $id,
1429
						'current_row' => $smiley_row[0]['row'],
1430
						'location' => $location == 'postform' ? '0' : '2',
1431
					)
1432
				);
1433
				// Only change the first row value of the first smiley (we don't need the others :P).
1434
				$context['smileys'][$location]['rows'][$id][0]['row'] = $id;
1435
			}
1436
			// Make sure the smiley order is always sequential.
1437
			foreach ($smiley_row as $order_id => $smiley)
1438
				if ($order_id != $smiley['order'])
1439
					$smcFunc['db_query']('', '
1440
						UPDATE {db_prefix}smileys
1441
						SET smiley_order = {int:new_order}
1442
						WHERE id_smiley = {int:current_smiley}',
1443
						array(
1444
							'new_order' => $order_id,
1445
							'current_smiley' => $smiley['id'],
1446
						)
1447
					);
1448
		}
1449
	}
1450
1451
	cache_put_data('parsing_smileys', null, 480);
1452
	cache_put_data('posting_smileys', null, 480);
1453
}
1454
1455
/**
1456
 * Install a smiley set.
1457
 */
1458
function InstallSmileySet()
1459
{
1460
	global $sourcedir, $boarddir, $packagesdir, $modSettings, $smcFunc, $scripturl, $context, $txt, $user_info;
1461
1462
	isAllowedTo('manage_smileys');
1463
	checkSession('request');
1464
	// One of these two may be necessary
1465
	loadLanguage('Errors');
1466
	loadLanguage('Packages');
1467
1468
	require_once($sourcedir . '/Subs-Package.php');
1469
1470
	// Installing unless proven otherwise
1471
	$testing = false;
1472
1473
	if (isset($_REQUEST['set_gz']))
1474
	{
1475
		$base_name = strtr(basename($_REQUEST['set_gz']), ':/', '-_');
1476
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['set_gz']), '.'));
1477
		$context['filename'] = $base_name;
1478
1479
		// Check that the smiley is from simplemachines.org, for now... maybe add mirroring later.
1480
		// @ TODO: Our current xml files serve http links.  Allowing both for now until we serve https.
1481
		if (preg_match('~^https?://[\w_\-]+\.simplemachines\.org/~', $_REQUEST['set_gz']) == 0 || strpos($_REQUEST['set_gz'], 'dlattach') !== false)
1482
			fatal_lang_error('not_on_simplemachines');
1483
1484
		$destination = $packagesdir . '/' . $base_name;
1485
1486
		if (file_exists($destination))
1487
			fatal_lang_error('package_upload_error_exists');
1488
1489
		// Let's copy it to the Packages directory
1490
		file_put_contents($destination, fetch_web_data($_REQUEST['set_gz']));
1491
		$testing = true;
1492
	}
1493
	elseif (isset($_REQUEST['package']))
1494
	{
1495
		$base_name = basename($_REQUEST['package']);
1496
		$name = $smcFunc['htmlspecialchars'](strtok(basename($_REQUEST['package']), '.'));
1497
		$context['filename'] = $base_name;
1498
1499
		$destination = $packagesdir . '/' . basename($_REQUEST['package']);
1500
	}
1501
1502
	if (empty($destination) || !file_exists($destination))
1503
		fatal_lang_error('package_no_file', false);
1504
1505
	// Make sure temp directory exists and is empty.
1506
	if (file_exists($packagesdir . '/temp'))
1507
		deltree($packagesdir . '/temp', false);
1508
1509
	if (!mktree($packagesdir . '/temp', 0755))
1510
	{
1511
		deltree($packagesdir . '/temp', false);
1512
		if (!mktree($packagesdir . '/temp', 0777))
1513
		{
1514
			deltree($packagesdir . '/temp', false);
1515
			// @todo not sure about url in destination_url
1516
			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));
1517
1518
			deltree($packagesdir . '/temp', false);
1519
			if (!mktree($packagesdir . '/temp', 0777))
1520
				fatal_lang_error('package_cant_download', false);
1521
		}
1522
	}
1523
1524
	$extracted = read_tgz_file($destination, $packagesdir . '/temp');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $destination does not seem to be defined for all execution paths leading up to this point.
Loading history...
1525
	if (!$extracted)
1526
		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
Comprehensibility Best Practice introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.
Loading history...
1527
	if ($extracted && !file_exists($packagesdir . '/temp/package-info.xml'))
1528
		foreach ($extracted as $file)
1529
			if (basename($file['filename']) == 'package-info.xml')
1530
			{
1531
				$base_path = dirname($file['filename']) . '/';
1532
				break;
1533
			}
1534
1535
	if (!isset($base_path))
1536
		$base_path = '';
1537
1538
	if (!file_exists($packagesdir . '/temp/' . $base_path . 'package-info.xml'))
1539
		fatal_lang_error('package_get_error_missing_xml', false);
1540
1541
	$smileyInfo = getPackageInfo($context['filename']);
1542
	if (!is_array($smileyInfo))
1543
		fatal_lang_error($smileyInfo);
1544
1545
	// See if it is installed?
1546
	$request = $smcFunc['db_query']('', '
1547
		SELECT version, themes_installed, db_changes
1548
		FROM {db_prefix}log_packages
1549
		WHERE package_id = {string:current_package}
1550
			AND install_state != {int:not_installed}
1551
		ORDER BY time_installed DESC
1552
		LIMIT 1',
1553
		array(
1554
			'not_installed'	=> 0,
1555
			'current_package' => $smileyInfo['id'],
1556
		)
1557
	);
1558
1559
	if ($smcFunc['db_num_rows']($request) > 0)
1560
		fatal_lang_error('package_installed_warning1');
1561
1562
	// Everything is fine, now it's time to do something
1563
	$actions = parsePackageInfo($smileyInfo['xml'], true, 'install');
1564
1565
	$context['post_url'] = $scripturl . '?action=admin;area=smileys;sa=install;package=' . $base_name;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $base_name does not seem to be defined for all execution paths leading up to this point.
Loading history...
1566
	$context['has_failure'] = false;
1567
	$context['actions'] = array();
1568
	$context['ftp_needed'] = false;
1569
1570
	foreach ($actions as $action)
1571
	{
1572
		if ($action['type'] == 'readme' || $action['type'] == 'license')
1573
		{
1574
			$type = 'package_' . $action['type'];
1575
			if (file_exists($packagesdir . '/temp/' . $base_path . $action['filename']))
1576
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($packagesdir . '/temp/' . $base_path . $action['filename']), "\n\r"));
1577
			elseif (file_exists($action['filename']))
1578
				$context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($action['filename']), "\n\r"));
1579
1580
			if (!empty($action['parse_bbc']))
1581
			{
1582
				require_once($sourcedir . '/Subs-Post.php');
1583
				preparsecode($context[$type]);
1584
				$context[$type] = parse_bbc($context[$type]);
1585
			}
1586
			else
1587
				$context[$type] = nl2br($context[$type]);
1588
1589
			continue;
1590
		}
1591
		elseif ($action['type'] == 'require-dir')
1592
		{
1593
			// Do this one...
1594
			$thisAction = array(
1595
				'type' => $txt['package_extract'] . ' ' . ($action['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']),
1596
				'action' => $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.')))
1597
			);
1598
1599
			$file =  $packagesdir . '/temp/' . $base_path . $action['filename'];
1600
			if (isset($action['filename']) && (!file_exists($file) || !is_writable(dirname($action['destination']))))
1601
			{
1602
				$context['has_failure'] = true;
1603
1604
				$thisAction += array(
1605
					'description' => $txt['package_action_error'],
1606
					'failed' => true,
1607
				);
1608
			}
1609
			// @todo None given?
1610
			if (empty($thisAction['description']))
1611
				$thisAction['description'] = isset($action['description']) ? $action['description'] : '';
1612
1613
			$context['actions'][] = $thisAction;
1614
		}
1615
		elseif ($action['type'] == 'credits')
1616
		{
1617
			// Time to build the billboard
1618
			$credits_tag = array(
1619
				'url' => $action['url'],
1620
				'license' => $action['license'],
1621
				'copyright' => $action['copyright'],
1622
				'title' => $action['title'],
1623
			);
1624
		}
1625
	}
1626
1627
	if ($testing)
1628
	{
1629
		$context['sub_template'] = 'view_package';
1630
		$context['uninstalling'] = false;
1631
		$context['is_installed'] = false;
1632
		$context['package_name'] = $smileyInfo['name'];
1633
		loadTemplate('Packages');
1634
	}
1635
	// Do the actual install
1636
	else
1637
	{
1638
		// @TODO Does this call have side effects? ($actions is not used)
1639
		$actions = parsePackageInfo($smileyInfo['xml'], false, 'install');
0 ignored issues
show
Unused Code introduced by
The assignment to $actions is dead and can be removed.
Loading history...
1640
		foreach ($context['actions'] as $action)
1641
		{
1642
			updateSettings(array(
1643
				'smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . basename($action['action']),
1644
				'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $smileyInfo['name'] . (count($context['actions']) > 1 ? ' ' .  (!empty($action['description']) ? $smcFunc['htmlspecialchars']($action['description']) : basename($action['action'])) : ''),
1645
			));
1646
		}
1647
1648
		package_flush_cache();
1649
1650
		// Credits tag?
1651
		$credits_tag = (empty($credits_tag)) ? '' : $smcFunc['json_encode']($credits_tag);
1652
		$smcFunc['db_insert']('',
1653
			'{db_prefix}log_packages',
1654
			array(
1655
				'filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string',
1656
				'id_member_installed' => 'int', 'member_installed' => 'string','time_installed' => 'int',
1657
				'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string',
1658
				'member_removed' => 'int', 'db_changes' => 'string', 'credits' => 'string',
1659
			),
1660
			array(
1661
				$smileyInfo['filename'], $smileyInfo['name'], $smileyInfo['id'], $smileyInfo['version'],
1662
				$user_info['id'], $user_info['name'], time(),
1663
				1, '', '',
1664
				0, '', $credits_tag,
1665
			),
1666
			array('id_install')
1667
		);
1668
1669
		logAction('install_package', array('package' => $smcFunc['htmlspecialchars']($smileyInfo['name']), 'version' => $smcFunc['htmlspecialchars']($smileyInfo['version'])), 'admin');
1670
1671
		cache_put_data('parsing_smileys', null, 480);
1672
		cache_put_data('posting_smileys', null, 480);
1673
	}
1674
1675
	if (file_exists($packagesdir . '/temp'))
1676
		deltree($packagesdir . '/temp');
1677
1678
	if (!$testing)
1679
		redirectexit('action=admin;area=smileys');
1680
}
1681
1682
/**
1683
 * A function to import new smileys from an existing directory into the database.
1684
 *
1685
 * @param string $smileyPath The path to the directory to import smileys from
1686
 */
1687
function ImportSmileys($smileyPath)
1688
{
1689
	global $modSettings, $smcFunc;
1690
1691
	if (empty($modSettings['smileys_dir']) || !is_dir($modSettings['smileys_dir'] . '/' . $smileyPath))
1692
		fatal_lang_error('smiley_set_unable_to_import');
1693
1694
	$smileys = array();
1695
	$dir = dir($modSettings['smileys_dir'] . '/' . $smileyPath);
1696
	while ($entry = $dir->read())
1697
	{
1698
		$filename = pathinfo($entry, PATHINFO_FILENAME);
1699
		if (in_array(strrchr($entry, '.'), array('.jpg', '.gif', '.jpeg', '.png', '.svg')))
1700
			$smileys[strtolower($filename)] = $filename;
1701
	}
1702
	$dir->close();
1703
1704
	// Exclude the smileys that are already in the database.
1705
	$request = $smcFunc['db_query']('', '
1706
		SELECT filename
1707
		FROM {db_prefix}smileys
1708
		WHERE filename IN ({array_string:smiley_list})',
1709
		array(
1710
			'smiley_list' => $smileys,
1711
		)
1712
	);
1713
	while ($row = $smcFunc['db_fetch_assoc']($request))
1714
		if (isset($smileys[strtolower($row['filename'])]))
1715
			unset($smileys[strtolower($row['filename'])]);
1716
	$smcFunc['db_free_result']($request);
1717
1718
	$request = $smcFunc['db_query']('', '
1719
		SELECT MAX(smiley_order)
1720
		FROM {db_prefix}smileys
1721
		WHERE hidden = {int:postform}
1722
			AND smiley_row = {int:first_row}',
1723
		array(
1724
			'postform' => 0,
1725
			'first_row' => 0,
1726
		)
1727
	);
1728
	list ($smiley_order) = $smcFunc['db_fetch_row']($request);
1729
	$smcFunc['db_free_result']($request);
1730
1731
	$new_smileys = array();
1732
	foreach ($smileys as $smiley)
1733
		if (strlen($smiley) <= 48)
1734
			$new_smileys[] = array(':' . strtok($smiley, '.') . ':', $smiley, strtok($smiley, '.'), 0, ++$smiley_order);
1735
1736
	if (!empty($new_smileys))
1737
	{
1738
		$smcFunc['db_insert']('',
1739
			'{db_prefix}smileys',
1740
			array(
1741
				'code' => 'string-30', 'filename' => 'string-48', 'description' => 'string-80', 'smiley_row' => 'int', 'smiley_order' => 'int',
1742
			),
1743
			$new_smileys,
1744
			array('id_smiley')
1745
		);
1746
1747
		cache_put_data('parsing_smileys', null, 480);
1748
		cache_put_data('posting_smileys', null, 480);
1749
	}
1750
}
1751
1752
/**
1753
 * Handles editing message icons
1754
 */
1755
function EditMessageIcons()
1756
{
1757
	global $context, $settings, $txt;
1758
	global $smcFunc, $scripturl, $sourcedir;
1759
1760
	// Get a list of icons.
1761
	$context['icons'] = array();
1762
	$request = $smcFunc['db_query']('', '
1763
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
1764
		FROM {db_prefix}message_icons AS m
1765
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
1766
		WHERE ({query_see_board} OR b.id_board IS NULL)
1767
		ORDER BY m.icon_order',
1768
		array(
1769
		)
1770
	);
1771
	$last_icon = 0;
1772
	$trueOrder = 0;
1773
	while ($row = $smcFunc['db_fetch_assoc']($request))
1774
	{
1775
		$context['icons'][$row['id_icon']] = array(
1776
			'id' => $row['id_icon'],
1777
			'title' => $row['title'],
1778
			'filename' => $row['filename'],
1779
			'image_url' => $settings[file_exists($settings['theme_dir'] . '/images/post/' . $row['filename'] . '.png') ? 'actual_images_url' : 'default_images_url'] . '/post/' . $row['filename'] . '.png',
1780
			'board_id' => $row['id_board'],
1781
			'board' => empty($row['board_name']) ? $txt['icons_edit_icons_all_boards'] : $row['board_name'],
1782
			'order' => $row['icon_order'],
1783
			'true_order' => $trueOrder++,
1784
			'after' => $last_icon,
1785
		);
1786
		$last_icon = $row['id_icon'];
1787
	}
1788
	$smcFunc['db_free_result']($request);
1789
1790
	// Submitting a form?
1791
	if (isset($_POST['icons_save']) || isset($_POST['delete']))
1792
	{
1793
		checkSession();
1794
1795
		// Deleting icons?
1796
		if (isset($_POST['delete']) && !empty($_POST['checked_icons']))
1797
		{
1798
			$deleteIcons = array();
1799
			foreach ($_POST['checked_icons'] as $icon)
1800
				$deleteIcons[] = (int) $icon;
1801
1802
			// Do the actual delete!
1803
			$smcFunc['db_query']('', '
1804
				DELETE FROM {db_prefix}message_icons
1805
				WHERE id_icon IN ({array_int:icon_list})',
1806
				array(
1807
					'icon_list' => $deleteIcons,
1808
				)
1809
			);
1810
		}
1811
		// Editing/Adding an icon?
1812
		elseif ($context['sub_action'] == 'editicon' && isset($_GET['icon']))
1813
		{
1814
			$_GET['icon'] = (int) $_GET['icon'];
1815
1816
			// Do some preperation with the data... like check the icon exists *somewhere*
1817
			if (strpos($_POST['icon_filename'], '.png') !== false)
1818
				$_POST['icon_filename'] = substr($_POST['icon_filename'], 0, -4);
1819
			if (!file_exists($settings['default_theme_dir'] . '/images/post/' . $_POST['icon_filename'] . '.png'))
1820
				fatal_lang_error('icon_not_found');
1821
			// There is a 16 character limit on message icons...
1822
			elseif (strlen($_POST['icon_filename']) > 16)
1823
				fatal_lang_error('icon_name_too_long');
1824
			elseif ($_POST['icon_location'] == $_GET['icon'] && !empty($_GET['icon']))
1825
				fatal_lang_error('icon_after_itself');
1826
1827
			// First do the sorting... if this is an edit reduce the order of everything after it by one ;)
1828
			if ($_GET['icon'] != 0)
1829
			{
1830
				$oldOrder = $context['icons'][$_GET['icon']]['true_order'];
1831
				foreach ($context['icons'] as $id => $data)
1832
					if ($data['true_order'] > $oldOrder)
1833
						$context['icons'][$id]['true_order']--;
1834
			}
1835
1836
			// If there are no existing icons and this is a new one, set the id to 1 (mainly for non-mysql)
1837
			if (empty($_GET['icon']) && empty($context['icons']))
1838
				$_GET['icon'] = 1;
1839
1840
			// Get the new order.
1841
			$newOrder = $_POST['icon_location'] == 0 ? 0 : $context['icons'][$_POST['icon_location']]['true_order'] + 1;
1842
			// Do the same, but with the one that used to be after this icon, done to avoid conflict.
1843
			foreach ($context['icons'] as $id => $data)
1844
				if ($data['true_order'] >= $newOrder)
1845
					$context['icons'][$id]['true_order']++;
1846
1847
			// Finally set the current icon's position!
1848
			$context['icons'][$_GET['icon']]['true_order'] = $newOrder;
1849
1850
			// Simply replace the existing data for the other bits.
1851
			$context['icons'][$_GET['icon']]['title'] = $_POST['icon_description'];
1852
			$context['icons'][$_GET['icon']]['filename'] = $_POST['icon_filename'];
1853
			$context['icons'][$_GET['icon']]['board_id'] = (int) $_POST['icon_board'];
1854
1855
			// Do a huge replace ;)
1856
			$iconInsert = array();
1857
			$iconInsert_new = array();
1858
			foreach ($context['icons'] as $id => $icon)
1859
			{
1860
				if ($id != 0)
1861
				{
1862
					$iconInsert[] = array($id, $icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1863
				}
1864
				else
1865
				{
1866
					$iconInsert_new[] = array($icon['board_id'], $icon['title'], $icon['filename'], $icon['true_order']);
1867
				}
1868
			}
1869
1870
			$smcFunc['db_insert']('replace',
1871
				'{db_prefix}message_icons',
1872
				array('id_icon' => 'int', 'id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1873
				$iconInsert,
1874
				array('id_icon')
1875
			);
1876
1877
			if (!empty($iconInsert_new))
1878
			{
1879
				$smcFunc['db_insert']('insert',
1880
					'{db_prefix}message_icons',
1881
					array('id_board' => 'int', 'title' => 'string-80', 'filename' => 'string-80', 'icon_order' => 'int'),
1882
					$iconInsert_new,
1883
					array('id_icon')
1884
				);
1885
			}
1886
		}
1887
1888
		// Unless we're adding a new thing, we'll escape
1889
		if (!isset($_POST['add']))
1890
			redirectexit('action=admin;area=smileys;sa=editicons');
1891
	}
1892
1893
	$context[$context['admin_menu_name']]['current_subsection'] = 'editicons';
1894
1895
	$listOptions = array(
1896
		'id' => 'message_icon_list',
1897
		'title' => $txt['icons_edit_message_icons'],
1898
		'base_href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1899
		'get_items' => array(
1900
			'function' => 'list_getMessageIcons',
1901
		),
1902
		'no_items_label' => $txt['icons_no_entries'],
1903
		'columns' => array(
1904
			'icon' => array(
1905
				'data' => array(
1906
					'function' => function ($rowData) use ($settings, $smcFunc)
1907
					{
1908
						$images_url = $settings[file_exists(sprintf('%1$s/images/post/%2$s.png', $settings['theme_dir'], $rowData['filename'])) ? 'actual_images_url' : 'default_images_url'];
1909
						return sprintf('<img src="%1$s/post/%2$s.png" alt="%3$s">', $images_url, $rowData['filename'], $smcFunc['htmlspecialchars']($rowData['title']));
1910
					},
1911
					'class' => 'centercol',
1912
				),
1913
			),
1914
			'filename' => array(
1915
				'header' => array(
1916
					'value' => $txt['smileys_filename'],
1917
				),
1918
				'data' => array(
1919
					'sprintf' => array(
1920
						'format' => '%1$s.png',
1921
						'params' => array(
1922
							'filename' => true,
1923
						),
1924
					),
1925
				),
1926
			),
1927
			'tooltip' => array(
1928
				'header' => array(
1929
					'value' => $txt['smileys_description'],
1930
				),
1931
				'data' => array(
1932
					'db_htmlsafe' => 'title',
1933
				),
1934
			),
1935
			'board' => array(
1936
				'header' => array(
1937
					'value' => $txt['icons_board'],
1938
				),
1939
				'data' => array(
1940
					'function' => function ($rowData) use ($txt)
1941
					{
1942
						return empty($rowData['board_name']) ? $txt['icons_edit_icons_all_boards'] : $rowData['board_name'];
1943
					},
1944
				),
1945
			),
1946
			'modify' => array(
1947
				'header' => array(
1948
					'value' => $txt['smileys_modify'],
1949
					'class' => 'centercol',
1950
				),
1951
				'data' => array(
1952
					'sprintf' => array(
1953
						'format' => '<a href="' . $scripturl . '?action=admin;area=smileys;sa=editicon;icon=%1$s">' . $txt['smileys_modify'] . '</a>',
1954
						'params' => array(
1955
							'id_icon' => false,
1956
						),
1957
					),
1958
					'class' => 'centercol',
1959
				),
1960
			),
1961
			'check' => array(
1962
				'header' => array(
1963
					'value' => '<input type="checkbox" onclick="invertAll(this, this.form);">',
1964
					'class' => 'centercol',
1965
				),
1966
				'data' => array(
1967
					'sprintf' => array(
1968
						'format' => '<input type="checkbox" name="checked_icons[]" value="%1$d">',
1969
						'params' => array(
1970
							'id_icon' => false,
1971
						),
1972
					),
1973
					'class' => 'centercol',
1974
				),
1975
			),
1976
		),
1977
		'form' => array(
1978
			'href' => $scripturl . '?action=admin;area=smileys;sa=editicons',
1979
		),
1980
		'additional_rows' => array(
1981
			array(
1982
				'position' => 'below_table_data',
1983
				'value' => '<input type="submit" name="delete" value="' . $txt['quickmod_delete_selected'] . '" class="button"> <a class="button" href="' . $scripturl . '?action=admin;area=smileys;sa=editicon">' . $txt['icons_add_new'] . '</a>',
1984
			),
1985
		),
1986
	);
1987
1988
	require_once($sourcedir . '/Subs-List.php');
1989
	createList($listOptions);
1990
1991
	// If we're adding/editing an icon we'll need a list of boards
1992
	if ($context['sub_action'] == 'editicon' || isset($_POST['add']))
1993
	{
1994
		// Force the sub_template just in case.
1995
		$context['sub_template'] = 'editicon';
1996
1997
		$context['new_icon'] = !isset($_GET['icon']);
1998
1999
		// Get the properties of the current icon from the icon list.
2000
		if (!$context['new_icon'])
2001
			$context['icon'] = $context['icons'][$_GET['icon']];
2002
2003
		// Get a list of boards needed for assigning this icon to a specific board.
2004
		$boardListOptions = array(
2005
			'use_permissions' => true,
2006
			'selected_board' => isset($context['icon']['board_id']) ? $context['icon']['board_id'] : 0,
2007
		);
2008
		require_once($sourcedir . '/Subs-MessageIndex.php');
2009
		$context['categories'] = getBoardList($boardListOptions);
2010
	}
2011
}
2012
2013
/**
2014
 * Callback function for createList().
2015
 *
2016
 * @param int $start The item to start with (not used here)
2017
 * @param int $items_per_page The number of items to display per page (not used here)
2018
 * @param string $sort A string indicating how to sort the items (not used here)
2019
 * @return array An array of information about message icons
2020
 */
2021
function list_getMessageIcons($start, $items_per_page, $sort)
2022
{
2023
	global $smcFunc;
2024
2025
	$request = $smcFunc['db_query']('', '
2026
		SELECT m.id_icon, m.title, m.filename, m.icon_order, m.id_board, b.name AS board_name
2027
		FROM {db_prefix}message_icons AS m
2028
			LEFT JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board)
2029
		WHERE ({query_see_board} OR b.id_board IS NULL)
2030
		ORDER BY m.icon_order',
2031
		array()
2032
	);
2033
2034
	$message_icons = array();
2035
	while ($row = $smcFunc['db_fetch_assoc']($request))
2036
		$message_icons[] = $row;
2037
	$smcFunc['db_free_result']($request);
2038
2039
	return $message_icons;
2040
}
2041
2042
?>