Project

General

Profile

Download (19.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	pkg.php
4
/*
5
/* ====================================================================
6
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
7
 *
8
 *	Redistribution and use in source and binary forms, with or without modification,
9
 *	are permitted provided that the following conditions are met:
10
 *
11
 *	1. Redistributions of source code must retain the above copyright notice,
12
 *		this list of conditions and the following disclaimer.
13
 *
14
 *	2. Redistributions in binary form must reproduce the above copyright
15
 *		notice, this list of conditions and the following disclaimer in
16
 *		the documentation and/or other materials provided with the
17
 *		distribution.
18
 *
19
 *	3. All advertising materials mentioning features or use of this software
20
 *		must display the following acknowledgment:
21
 *		"This product includes software developed by the pfSense Project
22
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
23
 *
24
 *	4. The names "pfSense" and "pfSense Project" must not be used to
25
 *		 endorse or promote products derived from this software without
26
 *		 prior written permission. For written permission, please contact
27
 *		 coreteam@pfsense.org.
28
 *
29
 *	5. Products derived from this software may not be called "pfSense"
30
 *		nor may "pfSense" appear in their names without prior written
31
 *		permission of the Electric Sheep Fencing, LLC.
32
 *
33
 *	6. Redistributions of any form whatsoever must retain the following
34
 *		acknowledgment:
35
 *
36
 *	"This product includes software developed by the pfSense Project
37
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
38
 *
39
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
40
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
43
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
51
 *
52
 *	====================================================================
53
 *
54
 */
55

    
56
##|+PRIV
57
##|*IDENT=page-package-settings
58
##|*NAME=Package: Settings
59
##|*DESCR=Allow access to the 'Package: Settings' page.
60
##|*MATCH=pkg.php*
61
##|-PRIV
62

    
63
require_once("guiconfig.inc");
64
require_once("pkg-utils.inc");
65

    
66
function domTT_title($title_msg) {
67
	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');\"";
68
}
69

    
70
$xml = $_REQUEST['xml'];
71

    
72
if ($xml == "") {
73
	include("head.inc");
74
	print_info_box_np(gettext("ERROR: No valid package defined."));
75
	include("foot.inc");
76
	exit;
77
} else {
78
	$pkg_xml_prefix = "/usr/local/pkg/";
79
	$pkg_full_path = "{$pkg_xml_prefix}/{$xml}";
80
	if (substr_compare(realpath($pkg_full_path), $pkg_xml_prefix, 0, strlen($pkg_xml_prefix))) {
81
		print_info_box_np(gettext("ERROR: Invalid path specified."));
82
		die;
83
	}
84
	if (file_exists($pkg_full_path)) {
85
		$pkg = parse_xml_config_pkg($pkg_full_path, "packagegui");
86
	} else {
87
		include("head.inc");
88
		print_info_box_np(gettext("File not found ") . htmlspecialchars($xml));
89
		include("foot.inc");
90
		exit;
91
	}
92
}
93

    
94
if ($pkg['donotsave'] != "") {
95
	header("Location: pkg_edit.php?xml=" . $xml);
96
	exit;
97
}
98

    
99
if ($pkg['include_file'] != "") {
100
	require_once($pkg['include_file']);
101
}
102

    
103
if ($_REQUEST['startdisplayingat']) {
104
	$startdisplayingat = $_REQUEST['startdisplayingat'];
105
}
106

    
107
if ($_REQUEST['display_maximum_rows']) {
108
	if ($_REQUEST['display_maximum_rows']) {
109
		$display_maximum_rows = $_REQUEST['display_maximum_rows'];
110
	}
111
}
112

    
113
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
114

    
115
if ($_GET['act'] == "update") {
116

    
117
	if (is_array($config['installedpackages'][$pkg['name']]) && $pkg['name'] != "" && $_REQUEST['ids'] !="") {
118
		#get current values
119
		$current_values=$config['installedpackages'][$pkg['name']]['config'];
120
		#get updated ids
121
		parse_str($_REQUEST['ids'], $update_list);
122
		#sort ids to know what to change
123
		#useful to do not lose data when using sorting and paging
124
		$sort_list=$update_list['ids'];
125
		sort($sort_list);
126
		#apply updates
127
		foreach ($update_list['ids'] as $key=> $value) {
128
			$config['installedpackages'][$pkg['name']]['config'][$sort_list[$key]]=$current_values[$update_list['ids'][$key]];
129
		}
130
		#save current config
131
		write_config();
132
		#sync package
133
		eval ("{$pkg['custom_php_resync_config_command']}");
134
	}
135
	#function called via jquery, no need to continue after save changes.
136
	exit;
137
}
138
if ($_GET['act'] == "del") {
139
	// loop through our fieldnames and automatically setup the fieldnames
140
	// in the environment.	ie: a fieldname of username with a value of
141
	// testuser would automatically eval $username = "testuser";
142
	foreach ($evaledvar as $ip) {
143
		if ($pkg['adddeleteeditpagefields']['columnitem']) {
144
			foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
145
				${xml_safe_fieldname($column['fielddescr'])} = $ip[xml_safe_fieldname($column['fieldname'])];
146
			}
147
		}
148
	}
149

    
150
	$a_pkg = &$config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
151

    
152
	if ($a_pkg[$_GET['id']]) {
153
		unset($a_pkg[$_GET['id']]);
154
		write_config();
155
		if ($pkg['custom_delete_php_command'] != "") {
156
			if ($pkg['custom_php_command_before_form'] != "") {
157
				eval($pkg['custom_php_command_before_form']);
158
			}
159
			eval($pkg['custom_delete_php_command']);
160
		}
161
		header("Location:  pkg.php?xml=" . $xml);
162
		exit;
163
	}
164
}
165

    
166
ob_start();
167

    
168
$iflist = get_configured_interface_with_descr(false, true);
169
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
170

    
171
if ($pkg['custom_php_global_functions'] != "") {
172
	eval($pkg['custom_php_global_functions']);
173
}
174

    
175
if ($pkg['custom_php_command_before_form'] != "") {
176
	eval($pkg['custom_php_command_before_form']);
177
}
178

    
179
// Breadcrumb
180
if ($pkg['title'] != "") {
181
	/*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
182
 		$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']; 
183
	}*/
184
	if (strpos($pkg['title'], '/')) {
185
		$title = explode('/', $pkg['title']);
186

    
187
		foreach ($title as $subtitle) {
188
			$pgtitle[] = gettext($subtitle);
189
		}
190
	} else {
191
		$pgtitle = array(gettext("Package"), gettext($pkg['title']));
192
	}
193
} else {
194
	$pgtitle = array(gettext("Package"), gettext("Editor"));
195
}
196

    
197
if ($pkg['tabs'] != "") {
198
	$tab_array = array();
199
	foreach ($pkg['tabs']['tab'] as $tab) {
200
		if ($tab['tab_level']) {
201
			$tab_level = $tab['tab_level'];
202
		} else {
203
			$tab_level = 1;
204
		}
205
		if (isset($tab['active'])) {
206
			$active = true;
207
			$pgtitle[] = $tab['text'];
208
		} else {
209
			$active = false;
210
		}
211
		if (isset($tab['no_drop_down'])) {
212
			$no_drop_down = true;
213
		}
214
		$urltmp = "";
215
		if ($tab['url'] != "") {
216
			$urltmp = $tab['url'];
217
		}
218
		if ($tab['xml'] != "") {
219
			$urltmp = "pkg_edit.php?xml=" . $tab['xml'];
220
		}
221

    
222
		$addresswithport = getenv("HTTP_HOST");
223
		$colonpos = strpos($addresswithport, ":");
224
		if ($colonpos !== False) {
225
			//my url is actually just the IP address of the pfsense box
226
			$myurl = substr($addresswithport, 0, $colonpos);
227
		} else {
228
			$myurl = $addresswithport;
229
		}
230
		// eval url so that above $myurl item can be processed if need be.
231
		$url = str_replace('$myurl', $myurl, $urltmp);
232

    
233
		$tab_array[$tab_level][] = array(
234
			$tab['text'],
235
			$active,
236
			$url
237
		);
238
	}
239

    
240
	ksort($tab_array);
241
}
242

    
243
include("head.inc");
244
if (isset($tab_array)) {
245
	foreach ($tab_array as $tabid => $tab) {
246
		display_top_tabs($tab); //, $no_drop_down, $tabid);
247
	}
248
}
249

    
250
?>
251

    
252
<script type="text/javascript">
253
//<![CDATA[
254
events.push(function() {
255

    
256
	function setFilter(filtertext) {
257
		jQuery('#pkg_filter').val(filtertext);
258
		document.pkgform.submit();
259
	}
260

    
261
<?php
262
	if ($pkg['adddeleteeditpagefields']['movable']) {
263
?>
264
		$('#mainarea table tbody').sortable({
265
		items: 'tr.sortable',
266
			cursor: 'move',
267
			distance: 10,
268
			opacity: 0.8,
269
			helper: function(e, ui) {
270
				ui.children().each(function() {
271
					jQuery(this).width(jQuery(this).width());
272
				});
273
			return ui;
274
			},
275
		});
276
<?php
277
	}
278
?>
279
});
280

    
281
function save_changes_to_xml(xml) {
282
	var ids = $('#mainarea table tbody').sortable('serialize', {key:"ids[]"});
283
	var strloading="<?=gettext('Saving changes...')?>";
284
	if (confirm("<?=gettext("Do you really want to save changes?")?>")) {
285
		$.ajax({
286
			type: 'get',
287
			cache: false,
288
			url: "<?=$_SERVER['SCRIPT_NAME']?>",
289
			data: {xml:'<?=$xml?>', act:'update', ids: ids},
290
			beforeSend: function() {
291
				$('#savemsg').empty().html(strloading);
292
			},
293
			error: function(data) {
294
				$('#savemsg').empty().html('Error:' + data);
295
			},
296
			success: function(data) {
297
				$('#savemsg').empty().html(data);
298
			}
299
		});
300
	}
301
}
302

    
303
//]]>
304
</script>
305

    
306
<?php
307
if ($_GET['savemsg'] != "") {
308
	$savemsg = htmlspecialchars($_GET['savemsg']);
309
}
310

    
311
if ($savemsg) {
312
	print_info_box($savemsg, 'success');
313
}
314
?>
315

    
316
<form action="pkg.php" name="pkgform" method="get">
317
	<input type='hidden' name='xml' value='<?=$_REQUEST['xml']?>' />
318
		<div id="mainarea" class="panel panel-default">
319
			<table id="mainarea" class="table table-striped table-hover table-condensed">
320
				<thead>
321
<?php
322
	/* Handle filtering bar A-Z */
323
	$include_filtering_inputbox = false;
324
	$colspan = 0;
325
	if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
326
		foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
327
			$colspan++;
328
		}
329
	}
330
	if ($pkg['fields']['field']) {
331
		// First find the sorting type field if it exists
332
		foreach ($pkg['fields']['field'] as $field) {
333
			if ($field['type'] == "sorting") {
334
				if (isset($field['include_filtering_inputbox'])) {
335
					$include_filtering_inputbox = true;
336
				}
337
				if ($display_maximum_rows < 1) {
338
					if ($field['display_maximum_rows']) {
339
						$display_maximum_rows = $field['display_maximum_rows'];
340
					}
341
				}
342
				echo "<tr><td colspan='$colspan' align='center'>";
343
				echo "Filter by: ";
344
				$isfirst = true;
345
				for ($char = 65; $char < 91; $char++) {
346
					if (!$isfirst) {
347
						echo " | ";
348
					}
349
					echo "<a href=\"#\" onclick=\"setFilter('" . chr($char) . "');\">" . chr($char) . "</a>";
350
					$isfirst = false;
351
				}
352
				echo "</td></tr>";
353
				echo "<tr><td colspan='$colspan' align='center'>";
354
				if ($field['sortablefields']) {
355
					echo "Filter field: <select name='pkg_filter_type'>";
356
					foreach ($field['sortablefields']['item'] as $si) {
357
						if ($si['name'] == $_REQUEST['pkg_filter_type']) {
358
							$SELECTED = "selected";
359
						} else {
360
							$SELECTED = "";
361
						}
362
						echo "<option value='{$si['name']}' {$SELECTED}>{$si['name']}</option>";
363
					}
364
					echo "</select>";
365
				}
366
				if ($include_filtering_inputbox) {
367
					echo "&nbsp;&nbsp;Filter text: <input id='pkg_filter' name='pkg_filter' value='" . $_REQUEST['pkg_filter'] . "' /><input type='submit' value='Filter' />";
368
				}
369
				echo "</td></tr><tr><td><font size='-3'>&nbsp;</font></td></tr>";
370
			}
371
		}
372
	}
373
?>
374
				<tr>
375

    
376
<?php
377
	if ($display_maximum_rows) {
378
		$totalpages = ceil(round((count($evaledvar) / $display_maximum_rows), 9));
379
		$page = 1;
380
		$tmpcount = 0;
381
		$tmppp = 0;
382
		if (is_array($evaledvar)) {
383
			foreach ($evaledvar as $ipa) {
384
				if ($tmpcount == $display_maximum_rows) {
385
					$page++;
386
					$tmpcount = 0;
387
				}
388
				if ($tmppp == $startdisplayingat) {
389
					break;
390
				}
391
				$tmpcount++;
392
				$tmppp++;
393
			}
394
		}
395
		echo "<tr><th colspan='" . count($pkg['adddeleteeditpagefields']['columnitem']) . "'>";
396
		echo "<table width='100%' summary=''>";
397
		echo "<tr>";
398
		echo "<td align='left'>Displaying page $page of $totalpages</b></td>";
399
		echo "<td align='right'>Rows per page: <select onchange='document.pkgform.submit();' name='display_maximum_rows'>";
400
		for ($x = 0; $x < 250; $x++) {
401
			if ($x == $display_maximum_rows) {
402
				$SELECTED = "selected";
403
			} else {
404
				$SELECTED = "";
405
			}
406
			echo "<option value='$x' $SELECTED>$x</option>\n";
407
			$x = $x + 4;
408
		}
409
		echo "</select></td></tr>";
410
		echo "</table>";
411
		echo "</th></tr>";
412
	}
413

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

    
610

    
611

    
612
<?php
613
	}
614
?>
615
			</table>
616
			</div>
617
		<input class="btn btn-primary" type="button" value="Save" name="Submit" onclick="save_changes_to_xml('<?=$xml?>')" />
618

    
619
</form>
620
<?php
621
echo "<!-- filter_fieldname: {$filter_fieldname} -->";
622
echo "<!-- filter_regex: {$filter_regex} -->";
623

    
624
include("foot.inc"); ?>
(100-100/229)