Project

General

Profile

Download (19.2 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * pkg.php
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2018 Rubicon Communications, LLC (Netgate)
7
 * All rights reserved.
8
 *
9
 * Licensed under the Apache License, Version 2.0 (the "License");
10
 * you may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 * http://www.apache.org/licenses/LICENSE-2.0
14
 *
15
 * Unless required by applicable law or agreed to in writing, software
16
 * distributed under the License is distributed on an "AS IS" BASIS,
17
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
 * See the License for the specific language governing permissions and
19
 * limitations under the License.
20
 */
21

    
22
##|+PRIV
23
##|*IDENT=page-package-settings
24
##|*NAME=Package: Settings
25
##|*DESCR=Allow access to the 'Package: Settings' page.
26
##|*MATCH=pkg.php*
27
##|-PRIV
28

    
29
require_once("guiconfig.inc");
30
require_once("pkg-utils.inc");
31

    
32
function domTT_title($title_msg) {
33
	print "onmouseout=\"this.style.color = ''; domTT_mouseout(this, event);\" onmouseover=\"domTT_activate(this, event, 'content', '".gettext($title_msg)."', 'trail', true, 'delay', 0, 'fade', 'both', 'fadeMax', 93, 'styleClass', 'niceTitle');\"";
34
}
35

    
36
$xml = $_REQUEST['xml'];
37

    
38
if ($xml == "") {
39
	$pgtitle = array(gettext("Package"), gettext("Editor"));
40
	$pglinks = array("", "@self");
41
	include("head.inc");
42
	print_info_box(gettext("No valid package defined."), 'danger', false);
43
	include("foot.inc");
44
	exit;
45
} else {
46
	$pkg_xml_prefix = "/usr/local/pkg/";
47
	$pkg_full_path = "{$pkg_xml_prefix}/{$xml}";
48
	$pkg_realpath = realpath($pkg_full_path);
49
	if (empty($pkg_realpath)) {
50
		$path_error = sprintf(gettext("Package path %s not found."), htmlspecialchars($pkg_full_path));
51
	} else if (substr_compare($pkg_realpath, $pkg_xml_prefix, 0, strlen($pkg_xml_prefix))) {
52
		$path_error = sprintf(gettext("Invalid path %s specified."), htmlspecialchars($pkg_full_path));
53
	}
54

    
55
	if (!empty($path_error)) {
56
		include("head.inc");
57
		print_info_box($path_error . "<br />" . gettext("Try reinstalling the package."), 'danger', false);
58
		include("foot.inc");
59
		die;
60
	}
61

    
62
	if (file_exists($pkg_full_path)) {
63
		$pkg = parse_xml_config_pkg($pkg_full_path, "packagegui");
64
	} else {
65
		include("head.inc");
66
		print_info_box(sprintf(gettext("File not found %s."), htmlspecialchars($xml)), 'danger', false);
67
		include("foot.inc");
68
		exit;
69
	}
70
}
71

    
72
if ($pkg['donotsave'] != "") {
73
	header("Location: pkg_edit.php?xml=" . $xml);
74
	exit;
75
}
76

    
77
if ($pkg['include_file'] != "") {
78
	require_once($pkg['include_file']);
79
}
80

    
81
if ($_REQUEST['startdisplayingat']) {
82
	$startdisplayingat = $_REQUEST['startdisplayingat'];
83
}
84

    
85
if ($_REQUEST['display_maximum_rows']) {
86
	if ($_REQUEST['display_maximum_rows']) {
87
		$display_maximum_rows = $_REQUEST['display_maximum_rows'];
88
	}
89
}
90

    
91
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
92

    
93
if ($_REQUEST['act'] == "update") {
94

    
95
	if (is_array($config['installedpackages'][$pkg['name']]) && $pkg['name'] != "" && $_REQUEST['ids'] !="") {
96
		// get current values
97
		$current_values=$config['installedpackages'][$pkg['name']]['config'];
98
		// get updated ids
99
		parse_str($_REQUEST['ids'], $update_list);
100
		// sort ids to know what to change
101
		// useful to do not lose data when using sorting and paging
102
		$sort_list=$update_list['ids'];
103
		sort($sort_list);
104
		// apply updates
105
		foreach ($update_list['ids'] as $key=> $value) {
106
			$config['installedpackages'][$pkg['name']]['config'][$sort_list[$key]]=$current_values[$update_list['ids'][$key]];
107
		}
108
		// save current config
109
		write_config(gettext("Package configuration changes saved from package settings page."));
110
		// sync package
111
		eval ("{$pkg['custom_php_resync_config_command']}");
112
	}
113
	// function called via jquery, no need to continue after save changes.
114
	exit;
115
}
116
if ($_REQUEST['act'] == "del") {
117
	// loop through our fieldnames and automatically setup the fieldnames
118
	// in the environment.	ie: a fieldname of username with a value of
119
	// testuser would automatically eval $username = "testuser";
120
	foreach ($evaledvar as $ip) {
121
		if ($pkg['adddeleteeditpagefields']['columnitem']) {
122
			foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
123
				${xml_safe_fieldname($column['fielddescr'])} = $ip[xml_safe_fieldname($column['fieldname'])];
124
			}
125
		}
126
	}
127

    
128
	init_config_arr(array('installedpackages', xml_safe_fieldname($pkg['name']), 'config'));
129
	$a_pkg = &$config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
130

    
131
	if ($a_pkg[$_REQUEST['id']]) {
132
		unset($a_pkg[$_REQUEST['id']]);
133
		write_config(gettext("Package configuration item deleted from package settings page."));
134
		if ($pkg['custom_delete_php_command'] != "") {
135
			if ($pkg['custom_php_command_before_form'] != "") {
136
				eval($pkg['custom_php_command_before_form']);
137
			}
138
			eval($pkg['custom_delete_php_command']);
139
		}
140
		header("Location:  pkg.php?xml=" . $xml);
141
		exit;
142
	}
143
}
144

    
145
ob_start();
146

    
147
$iflist = get_configured_interface_with_descr(true);
148
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
149

    
150
if ($pkg['custom_php_global_functions'] != "") {
151
	eval($pkg['custom_php_global_functions']);
152
}
153

    
154
if ($pkg['custom_php_command_before_form'] != "") {
155
	eval($pkg['custom_php_command_before_form']);
156
}
157

    
158
// Breadcrumb
159
if ($pkg['title'] != "") {
160
	/*if (!$only_edit) {						// Is any package still making use of this?? Is this something that is still wanted, considering the breadcrumb policy https://redmine.pfsense.org/issues/5527
161
 		$pkg['title'] = $pkg['title'] . '/Edit';		// If this needs to live on, then it has to be moved to run AFTER "foreach ($pkg['tabs']['tab'] as $tab)"-loop. This due to $pgtitle[] = $tab['text'];
162
	}*/
163
	if (strpos($pkg['title'], '/')) {
164
		$title = explode('/', $pkg['title']);
165

    
166
		foreach ($title as $subtitle) {
167
			$pgtitle[] = gettext($subtitle);
168
			$pglinks[] = "@self";
169
		}
170
	} else {
171
		$pgtitle = array(gettext("Package"), gettext($pkg['title']));
172
		$pglinks = array("", "@self");
173
	}
174
} else {
175
	$pgtitle = array(gettext("Package"), gettext("Editor"));
176
	$pglinks = array("", "@self");
177
}
178

    
179
if ($pkg['tabs'] != "") {
180
	$tab_array = array();
181
	foreach ($pkg['tabs']['tab'] as $tab) {
182
		if ($tab['tab_level']) {
183
			$tab_level = $tab['tab_level'];
184
		} else {
185
			$tab_level = 1;
186
		}
187
		if (isset($tab['active'])) {
188
			$active = true;
189
			$pgtitle[] = $tab['text'];
190
			$pglinks[] = "@self";
191
		} else {
192
			$active = false;
193
		}
194
		$urltmp = "";
195
		if ($tab['url'] != "") {
196
			$urltmp = $tab['url'];
197
		}
198
		if ($tab['xml'] != "") {
199
			$urltmp = "pkg_edit.php?xml=" . $tab['xml'];
200
		}
201

    
202
		$addresswithport = getenv("HTTP_HOST");
203
		$colonpos = strpos($addresswithport, ":");
204
		if ($colonpos !== False) {
205
			//my url is actually just the IP address of the pfsense box
206
			$myurl = substr($addresswithport, 0, $colonpos);
207
		} else {
208
			$myurl = $addresswithport;
209
		}
210
		// eval url so that above $myurl item can be processed if need be.
211
		$url = str_replace('$myurl', $myurl, $urltmp);
212

    
213
		$tab_array[$tab_level][] = array(
214
			$tab['text'],
215
			$active,
216
			$url
217
		);
218
	}
219

    
220
	ksort($tab_array);
221
}
222

    
223
include("head.inc");
224
if (isset($tab_array)) {
225
	foreach ($tab_array as $tabid => $tab) {
226
		display_top_tabs($tab);
227
	}
228
}
229

    
230
?>
231

    
232
<script type="text/javascript">
233
//<![CDATA[
234
events.push(function() {
235

    
236
	function setFilter(filtertext) {
237
		$('#pkg_filter').val(filtertext);
238
		document.pkgform.submit();
239
	}
240

    
241
<?php
242
	if ($pkg['adddeleteeditpagefields']['movable']) {
243
?>
244
		$('#mainarea table tbody').sortable({
245
		items: 'tr.sortable',
246
			cursor: 'move',
247
			distance: 10,
248
			opacity: 0.8,
249
			helper: function(e, ui) {
250
				ui.children().each(function() {
251
					$(this).width($(this).width());
252
				});
253
			return ui;
254
			},
255
		});
256
<?php
257
	}
258
?>
259
});
260

    
261
function save_changes_to_xml(xml) {
262
	var ids = $('#mainarea table tbody').sortable('serialize', {key:"ids[]"});
263
	var strloading="<?=gettext('Saving changes...')?>";
264
	if (confirm("<?=gettext("Confirmation Required to save changes.")?>")) {
265
		$.ajax({
266
			type: 'get',
267
			cache: false,
268
			url: "<?=$_SERVER['SCRIPT_NAME']?>",
269
			data: {xml:'<?=$xml?>', act:'update', ids: ids},
270
			beforeSend: function() {
271
				$('#savemsg').empty().html(strloading);
272
			},
273
			error: function(data) {
274
				$('#savemsg').empty().html('Error:' + data);
275
			},
276
			success: function(data) {
277
				$('#savemsg').empty().html(data);
278
			}
279
		});
280
	}
281
}
282

    
283
//]]>
284
</script>
285

    
286
<?php
287
if ($_REQUEST['savemsg'] != "") {
288
	$savemsg = htmlspecialchars($_REQUEST['savemsg']);
289
}
290

    
291
if ($savemsg) {
292
	print_info_box($savemsg, 'success');
293
}
294
?>
295

    
296
<form action="pkg.php" name="pkgform" method="get">
297
	<input type='hidden' name='xml' value='<?=$_REQUEST['xml']?>' />
298
		<div id="mainarea" class="panel panel-default">
299
			<table id="mainarea" class="table table-striped table-hover table-condensed">
300
				<thead>
301
<?php
302
	/* Handle filtering bar A-Z */
303
	$include_filtering_inputbox = false;
304
	$colspan = 0;
305
	if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
306
		foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
307
			$colspan++;
308
		}
309
	}
310
	if ($pkg['fields']['field']) {
311
		// First find the sorting type field if it exists
312
		foreach ($pkg['fields']['field'] as $field) {
313
			if ($field['type'] == "sorting") {
314
				if (isset($field['include_filtering_inputbox'])) {
315
					$include_filtering_inputbox = true;
316
				}
317
				if ($display_maximum_rows < 1) {
318
					if ($field['display_maximum_rows']) {
319
						$display_maximum_rows = $field['display_maximum_rows'];
320
					}
321
				}
322
				echo "<tr><td colspan='$colspan' class='text-center'>";
323
				echo gettext("Filter by: ");
324
				$isfirst = true;
325
				for ($char = 65; $char < 91; $char++) {
326
					if (!$isfirst) {
327
						echo " | ";
328
					}
329
					echo "<a href=\"#\" onclick=\"setFilter('" . chr($char) . "');\">" . chr($char) . "</a>";
330
					$isfirst = false;
331
				}
332
				echo "</td></tr>";
333
				echo "<tr><td colspan='$colspan' class='text-center'>";
334
				if ($field['sortablefields']) {
335
					echo gettext("Filter field: ") . "<select name='pkg_filter_type'>";
336
					foreach ($field['sortablefields']['item'] as $si) {
337
						if ($si['name'] == $_REQUEST['pkg_filter_type']) {
338
							$SELECTED = "selected";
339
						} else {
340
							$SELECTED = "";
341
						}
342
						echo "<option value='{$si['name']}' {$SELECTED}>{$si['name']}</option>";
343
					}
344
					echo "</select>";
345
				}
346
				if ($include_filtering_inputbox) {
347
					echo '&nbsp;&nbsp;' . gettext("Filter text: ") . '<input id="pkg_filter" name="pkg_filter" value="' . htmlspecialchars($_REQUEST['pkg_filter']) . '" />';
348
					echo '&nbsp;<button type="submit" value="Filter" class="btn btn-primary btn-xs">';
349
					echo '<i class="fa fa-filter icon-embed-btn"></i>';
350
					echo gettext("Filter");
351
					echo "</button>";
352
				}
353
				echo "</td></tr><tr><td><font size='-3'>&nbsp;</font></td></tr>";
354
			}
355
		}
356
	}
357
?>
358
				<tr>
359

    
360
<?php
361
	if ($display_maximum_rows) {
362
		$totalpages = ceil(round((count($evaledvar) / $display_maximum_rows), 9));
363
		$page = 1;
364
		$tmpcount = 0;
365
		$tmppp = 0;
366
		if (is_array($evaledvar)) {
367
			foreach ($evaledvar as $ipa) {
368
				if ($tmpcount == $display_maximum_rows) {
369
					$page++;
370
					$tmpcount = 0;
371
				}
372
				if ($tmppp == $startdisplayingat) {
373
					break;
374
				}
375
				$tmpcount++;
376
				$tmppp++;
377
			}
378
		}
379
		echo "<tr><th colspan='" . count($pkg['adddeleteeditpagefields']['columnitem']) . "'>";
380
		echo "<table width='100%' summary=''>";
381
		echo "<tr>";
382
		echo "<td class='text-left'>" . sprintf(gettext('Displaying page %1$s of %2$s'), $page, $totalpages) . "</b></td>";
383
		echo "<td class='text-right'>" . gettext("Rows per page: ") . "<select onchange='document.pkgform.submit();' name='display_maximum_rows'>";
384
		for ($x = 0; $x < 250; $x++) {
385
			if ($x == $display_maximum_rows) {
386
				$SELECTED = "selected";
387
			} else {
388
				$SELECTED = "";
389
			}
390
			echo "<option value='$x' $SELECTED>$x</option>\n";
391
			$x = $x + 4;
392
		}
393
		echo "</select></td></tr>";
394
		echo "</table>";
395
		echo "</th></tr>";
396
	}
397

    
398
	$cols = 0;
399
	if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
400
		foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
401
			echo "<th class=\"listhdrr\">" . $column['fielddescr'] . "</th>";
402
			$cols++;
403
		}
404
	}
405
?>
406
				</tr>
407
				</thead>
408
				<tbody>
409
<?php
410
	$i = 0;
411
	$pagination_counter = 0;
412
	if ($evaledvar && is_array($evaledvar)) {
413
		foreach ($evaledvar as $ip) {
414
			if ($startdisplayingat) {
415
				if ($i < $startdisplayingat) {
416
					$i++;
417
					continue;
418
				}
419
			}
420
			if ($_REQUEST['pkg_filter']) {
421
				// Handle filtered items
422
				if ($pkg['fields']['field'] && !$filter_regex) {
423
					// First find the sorting type field if it exists
424
					foreach ($pkg['fields']['field'] as $field) {
425
						if ($field['type'] == "sorting") {
426
							if ($field['sortablefields']['item']) {
427
								foreach ($field['sortablefields']['item'] as $sf) {
428
									if ($sf['name'] == $_REQUEST['pkg_filter_type']) {
429
										$filter_fieldname = $sf['fieldname'];
430
										#Use a default regex on sortable fields when none is declared
431
										if ($sf['regex']) {
432
											$filter_regex = str_replace("%FILTERTEXT%", $_REQUEST['pkg_filter'], trim($sf['regex']));
433
										} else {
434
											$filter_regex = "/{$_REQUEST['pkg_filter']}/i";
435
										}
436
									}
437
								}
438
							}
439
						}
440
					}
441
				}
442
				// Do we have something to filter on?
443
				unset($filter_matches);
444
				if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
445
					foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
446
						$fieldname = $ip[xml_safe_fieldname($column['fieldname'])];
447
						if ($column['fieldname'] == $filter_fieldname) {
448
							if ($filter_regex) {
449
								//echo "$filter_regex - $fieldname<p/>";
450
								preg_match($filter_regex, $fieldname, $filter_matches);
451
								break;
452
							}
453
						}
454
					}
455
				}
456
				if (!$filter_matches) {
457
					$i++;
458
					continue;
459
				}
460
			}
461
			if ($pkg['adddeleteeditpagefields']['movable']) {
462
				echo "<tr style=\"vertical-align: top\" class=\"sortable\" id=\"id_{$i}\">\n";
463
			} else {
464
				echo "<tr style=\"vertical-align: top\">\n";
465
			}
466
			if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
467
				foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
468
					if ($column['fieldname'] == "description") {
469
						$class = "listbg";
470
					} else {
471
						$class = "listlr";
472
					}
473
?>
474
					<td class="<?=$class?>" ondblclick="document.location='pkg_edit.php?xml=<?=$xml?>&amp;act=edit&amp;id=<?=$i?>';">
475
<?php
476
					$fieldname = $ip[xml_safe_fieldname($column['fieldname'])];
477
					#Check if columnitem has a type field declared
478
					if ($column['type'] == "checkbox") {
479
						if ($fieldname == "") {
480
							echo gettext("No");
481
						} else {
482
							echo gettext("Yes");
483
						}
484
					} else if ($column['type'] == "interface") {
485
						echo $column['prefix'] . $iflist[$fieldname] . $column['suffix'];
486
					} else {
487
						$display_text = "";
488
						#Check if columnitem has an encoding field declared
489
						if ($column['encoding'] == "base64") {
490
							$display_text = $column['prefix'] . base64_decode($fieldname) . $column['suffix'];
491
						#Check if there is a custom info to show when $fieldname is not empty
492
						} else if ($column['listmodeon'] && $fieldname != "") {
493
							$display_text = $column['prefix'] . gettext($column['listmodeon']). $column['suffix'];
494
						#Check if there is a custom info to show when $fieldname is empty
495
						} else if ($column['listmodeoff'] && $fieldname == "") {
496
							$display_text = $column['prefix'] .gettext($column['listmodeoff']). $column['suffix'];
497
						} else {
498
							$display_text = $column['prefix'] . $fieldname ." ". $column['suffix'];
499
						}
500
						if (!isset($column['allow_html'])) {
501
							$display_text = htmlspecialchars($display_text);
502
						}
503
						echo $display_text;
504
					}
505
?>
506
					</td>
507
<?php
508
				} // foreach columnitem
509
			} // if columnitem
510
?>
511
					<td style="vertical-align: middle" class="list text-nowrap">
512
						<table border="0" cellspacing="0" cellpadding="1" summary="icons">
513
							<tr>
514
<?php
515
			#Show custom description to edit button if defined
516
			$edit_msg=($pkg['adddeleteeditpagefields']['edittext']?$pkg['adddeleteeditpagefields']['edittext']:gettext("Edit this item"));
517
?>
518
								<td><a class="fa fa-pencil" href="pkg_edit.php?xml=<?=$xml?>&amp;act=edit&amp;id=<?=$i?>" title="<?=$edit_msg?>"></a></td>
519
<?php
520
			#Show custom description to delete button if defined
521
			$delete_msg=($pkg['adddeleteeditpagefields']['deletetext']?$pkg['adddeleteeditpagefields']['deletetext']:gettext("Delete this item"));
522
?>
523
								<td>&nbsp;<a class="fa fa-trash" href="pkg.php?xml=<?=$xml?>&amp;act=del&amp;id=<?=$i?>" title="<?=$delete_msg?>"></a></td>
524
							</tr>
525
						</tbody>
526
					</table>
527
				</td>
528
<?php
529
			echo "</tr>\n"; // Pairs with an echo tr some way above
530
			// Handle pagination and display_maximum_rows
531
			if ($display_maximum_rows) {
532
				if ($pagination_counter == ($display_maximum_rows-1) or
533
					$i == (count($evaledvar)-1)) {
534
					$colcount = count($pkg['adddeleteeditpagefields']['columnitem']);
535
					$final_footer = "";
536
					$final_footer .= "<tr><td colspan='$colcount'>";
537
					$final_footer .= "<table width='100%' summary=''><tr>";
538
					$final_footer .= "<td class='text-left'>";
539
					$startingat = $startdisplayingat - $display_maximum_rows;
540
					if ($startingat > -1) {
541
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat={$startingat}&amp;display_maximum_rows={$display_maximum_rows}'>";
542
					} else if ($startdisplayingat > 1) {
543
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat=0&amp;display_maximum_rows={$display_maximum_rows}'>";
544
					}
545
					$final_footer .= "<font size='2'><< " . gettext("Previous page") . "</font></a>";
546
					if ($tmppp + $display_maximum_rows > count($evaledvar)) {
547
						$endingrecord = count($evaledvar);
548
					} else {
549
						$endingrecord = $tmppp + $display_maximum_rows;
550
					}
551
					$final_footer .= "</td><td class='text-center'>";
552
					$tmppp++;
553
					$final_footer .= "<font size='2'>Displaying {$tmppp} - {$endingrecord} / " . count($evaledvar) . " records";
554
					$final_footer .= "</font></td><td class='text-right'>&nbsp;";
555
					if (($i+1) < count($evaledvar)) {
556
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat=" . ($startdisplayingat + $display_maximum_rows) . "&amp;display_maximum_rows={$display_maximum_rows}'>";
557
					}
558
					$final_footer .= "<font size='2'>" . gettext("Next page") . " >></font></a>";
559
					$final_footer .= "</td></tr></table></td></tr>";
560
					$i = count($evaledvar);
561
					break;
562
				}
563
			}
564
			$i++;
565
			$pagination_counter++;
566
		} // foreach evaledvar
567
	} // if evaledvar
568
?>
569
				<tr>
570
					<td colspan="<?=$cols?>"></td>
571
					<td>
572
						<table border="0" cellspacing="0" cellpadding="1" summary="icons">
573
							<tr>
574
<?php
575
	#Show custom description to add button if defined
576
	$add_msg=($pkg['adddeleteeditpagefields']['addtext']?$pkg['adddeleteeditpagefields']['addtext']:gettext("Add a new item"));
577
?>
578
								<td><a href="pkg_edit.php?xml=<?=$xml?>&amp;id=<?=$i?>" class="btn btn-sm btn-success" title="<?=$add_msg?>"><i class="fa fa-plus icon-embed-btn"></i><?=gettext('Add')?></a></td>
579
<?php
580
	#Show description button and info if defined
581
	if ($pkg['adddeleteeditpagefields']['description']) {
582
?>
583
								<td>
584
									<i class="fa fa-info-circle"><?=$pkg['adddeleteeditpagefields']['description']?></i>
585
								</td>
586
<?php
587
	}
588
?>
589
							</tr>
590
						</table>
591
					</td>
592
				</tr>
593
				<?=$final_footer?>
594
			</table>
595
			</div>
596
		<button class="btn btn-primary" type="button" value="Save" name="Submit" onclick="save_changes_to_xml('<?=$xml?>')"><i class="fa fa-save icon-embed-btn"></i><?=gettext("Save")?></button>
597

    
598
</form>
599
<?php
600
echo "<!-- filter_fieldname: {$filter_fieldname} -->";
601
echo "<!-- filter_regex: {$filter_regex} -->";
602

    
603
include("foot.inc"); ?>
(101-101/234)