Project

General

Profile

Download (19.1 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
	pfSense_MODULE: pkgs
57
*/
58

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

    
66
require_once("guiconfig.inc");
67
require_once("pkg-utils.inc");
68

    
69
function gentitle_pkg($pgname) {
70
	global $config;
71
	return $config['system']['hostname'] . "." . $config['system']['domain'] . " - " . $pgname;
72
}
73

    
74
function domTT_title($title_msg) {
75
	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');\"";
76
}
77

    
78
$xml = $_REQUEST['xml'];
79

    
80
if ($xml == "") {
81
	include("head.inc");
82
	print_info_box_np(gettext("ERROR: No valid package defined."));
83
	include("foot.inc");
84
	exit;
85
} else {
86
	$pkg_xml_prefix = "/usr/local/pkg/";
87
	$pkg_full_path = "{$pkg_xml_prefix}/{$xml}";
88
	if (substr_compare(realpath($pkg_full_path), $pkg_xml_prefix, 0, strlen($pkg_xml_prefix))) {
89
		print_info_box_np(gettext("ERROR: Invalid path specified."));
90
		die;
91
	}
92
	if (file_exists($pkg_full_path)) {
93
		$pkg = parse_xml_config_pkg($pkg_full_path, "packagegui");
94
	} else {
95
		include("head.inc");
96
		print_info_box_np(gettext("File not found ") . htmlspecialchars($xml));
97
		include("foot.inc");
98
		exit;
99
	}
100
}
101

    
102
if ($pkg['donotsave'] != "") {
103
	header("Location: pkg_edit.php?xml=" . $xml);
104
	exit;
105
}
106

    
107
if ($pkg['include_file'] != "") {
108
	require_once($pkg['include_file']);
109
}
110

    
111
if ($_REQUEST['startdisplayingat']) {
112
	$startdisplayingat = $_REQUEST['startdisplayingat'];
113
}
114

    
115
if ($_REQUEST['display_maximum_rows']) {
116
	if ($_REQUEST['display_maximum_rows']) {
117
		$display_maximum_rows = $_REQUEST['display_maximum_rows'];
118
	}
119
}
120

    
121
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
122

    
123
if ($_GET['act'] == "update") {
124

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

    
158
	$a_pkg = &$config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
159

    
160
	if ($a_pkg[$_GET['id']]) {
161
		unset($a_pkg[$_GET['id']]);
162
		write_config();
163
		if ($pkg['custom_delete_php_command'] != "") {
164
			if ($pkg['custom_php_command_before_form'] != "") {
165
				eval($pkg['custom_php_command_before_form']);
166
			}
167
			eval($pkg['custom_delete_php_command']);
168
		}
169
		header("Location:  pkg.php?xml=" . $xml);
170
		exit;
171
	}
172
}
173

    
174
ob_start();
175

    
176
$iflist = get_configured_interface_with_descr(false, true);
177
$evaledvar = $config['installedpackages'][xml_safe_fieldname($pkg['name'])]['config'];
178

    
179
if ($pkg['custom_php_global_functions'] != "") {
180
	eval($pkg['custom_php_global_functions']);
181
}
182

    
183
if ($pkg['custom_php_command_before_form'] != "") {
184
	eval($pkg['custom_php_command_before_form']);
185
}
186

    
187
$pgtitle = array($pkg['title']);
188
include("head.inc");
189

    
190
?>
191

    
192
<script type="text/javascript">
193
//<![CDATA[
194
events.push(function(){
195
	function setFilter(filtertext) {
196
		jQuery('#pkg_filter').val(filtertext);
197
		document.pkgform.submit();
198
	}
199

    
200
	<?php
201
		if ($pkg['adddeleteeditpagefields']['movable']) {
202
	?>
203
			jQuery(document).ready(function() {
204
				jQuery('#mainarea table tbody').sortable({
205
					items: 'tr.sortable',
206
					cursor: 'move',
207
					distance: 10,
208
					opacity: 0.8,
209
					helper: function(e, ui) {
210
						ui.children().each(function() {
211
							jQuery(this).width(jQuery(this).width());
212
						});
213
					return ui;
214
					},
215
				});
216
			});
217
			function save_changes_to_xml(xml) {
218
				var ids=jQuery('#mainarea table tbody').sortable('serialize', {key:"ids[]"});
219
				var strloading="<?=gettext('Saving changes...')?>";
220
				if (confirm("<?=gettext("Do you really want to save changes?")?>")) {
221
					jQuery.ajax({
222
						type: 'get',
223
						cache: false,
224
						url: "<?=$_SERVER['SCRIPT_NAME']?>",
225
						data: {xml:'<?=$xml?>', act:'update', ids: ids},
226
						beforeSend: function() {
227
							jQuery('#savemsg').empty().html(strloading);
228
						},
229
						error: function(data) {
230
							jQuery('#savemsg').empty().html('Error:' + data);
231
						},
232
						success: function(data) {
233
							jQuery('#savemsg').empty().html(data);
234
						}
235
					});
236
				}
237
			}
238
	<?php
239
		}
240
	?>
241
});
242
//]]>
243
</script>
244

    
245
<?php
246
if ($_GET['savemsg'] != "")
247
	$savemsg = htmlspecialchars($_GET['savemsg']);
248

    
249
if ($savemsg)
250
	print_info_box($savemsg, 'success');
251
?>
252

    
253
<form action="pkg.php" name="pkgform" method="get">
254
	<input type='hidden' name='xml' value='<?=$_REQUEST['xml']?>' />
255
<?php
256
	if ($pkg['tabs'] != "") {
257
		$tab_array = array();
258
		foreach ($pkg['tabs']['tab'] as $tab) {
259
			if ($tab['tab_level']) {
260
				$tab_level = $tab['tab_level'];
261
			} else {
262
				$tab_level = 1;
263
			}
264
			if (isset($tab['active'])) {
265
				$active = true;
266
			} else {
267
				$active = false;
268
			}
269
			if (isset($tab['no_drop_down'])) {
270
				$no_drop_down = true;
271
			}
272
			$urltmp = "";
273
			if ($tab['url'] != "") {
274
				$urltmp = $tab['url'];
275
			}
276
			if ($tab['xml'] != "") {
277
				$urltmp = "pkg_edit.php?xml=" . $tab['xml'];
278
			}
279

    
280
			$addresswithport = getenv("HTTP_HOST");
281
			$colonpos = strpos($addresswithport, ":");
282
			if ($colonpos !== False) {
283
				//my url is actually just the IP address of the pfsense box
284
				$myurl = substr($addresswithport, 0, $colonpos);
285
			} else {
286
				$myurl = $addresswithport;
287
			}
288
			// eval url so that above $myurl item can be processed if need be.
289
			$url = str_replace('$myurl', $myurl, $urltmp);
290

    
291
			$tab_array[$tab_level][] = array(
292
				$tab['text'],
293
				$active,
294
				$url
295
			);
296
		}
297

    
298
		ksort($tab_array);
299
		foreach ($tab_array as $tab) {
300
			display_top_tabs($tab, $no_drop_down);
301
		}
302
	}
303
?>
304

    
305
			<table class="table table-striped table-hover table-condensed">
306
<?php
307
	/* Handle filtering bar A-Z */
308
	$include_filtering_inputbox = false;
309
	$colspan = 0;
310
	if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
311
		foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
312
			$colspan++;
313
		}
314
	}
315
	if ($pkg['fields']['field']) {
316
		// First find the sorting type field if it exists
317
		foreach ($pkg['fields']['field'] as $field) {
318
			if ($field['type'] == "sorting") {
319
				if (isset($field['include_filtering_inputbox'])) {
320
					$include_filtering_inputbox = true;
321
				}
322
				if ($display_maximum_rows < 1) {
323
					if ($field['display_maximum_rows']) {
324
						$display_maximum_rows = $field['display_maximum_rows'];
325
					}
326
				}
327
				echo "<tr><td colspan='$colspan' align='center'>";
328
				echo "Filter by: ";
329
				$isfirst = true;
330
				for ($char = 65; $char < 91; $char++) {
331
					if (!$isfirst) {
332
						echo " | ";
333
					}
334
					echo "<a href=\"#\" onclick=\"setFilter('" . chr($char) . "');\">" . chr($char) . "</a>";
335
					$isfirst = false;
336
				}
337
				echo "</td></tr>";
338
				echo "<tr><td colspan='$colspan' align='center'>";
339
				if ($field['sortablefields']) {
340
					echo "Filter field: <select name='pkg_filter_type'>";
341
					foreach ($field['sortablefields']['item'] as $si) {
342
						if ($si['name'] == $_REQUEST['pkg_filter_type']) {
343
							$SELECTED = "selected";
344
						} else {
345
							$SELECTED = "";
346
						}
347
						echo "<option value='{$si['name']}' {$SELECTED}>{$si['name']}</option>";
348
					}
349
					echo "</select>";
350
				}
351
				if ($include_filtering_inputbox) {
352
					echo "&nbsp;&nbsp;Filter text: <input id='pkg_filter' name='pkg_filter' value='" . $_REQUEST['pkg_filter'] . "' /><input type='submit' value='Filter' />";
353
				}
354
				echo "</td></tr><tr><td><font size='-3'>&nbsp;</font></td></tr>";
355
			}
356
		}
357
	}
358
?>
359
				<tr>
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><td colspan='" . count($pkg['adddeleteeditpagefields']['columnitem']) . "'>";
380
		echo "<table width='100%' summary=''>";
381
		echo "<tr>";
382
		echo "<td align='left'>Displaying page $page of $totalpages</b></td>";
383
		echo "<td align='right'>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 "</td></tr>";
396
	}
397
	$cols = 0;
398
	if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
399
		foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
400
			echo "<td class=\"listhdrr\">" . $column['fielddescr'] . "</td>";
401
			$cols++;
402
		}
403
	}
404
?>
405
				</tr>
406
<?php
407
	$i = 0;
408
	$pagination_counter = 0;
409
	if ($evaledvar) {
410
		foreach ($evaledvar as $ip) {
411
			if ($startdisplayingat) {
412
				if ($i < $startdisplayingat) {
413
					$i++;
414
					continue;
415
				}
416
			}
417
			if ($_REQUEST['pkg_filter']) {
418
				// Handle filtered items
419
				if ($pkg['fields']['field'] && !$filter_regex) {
420
					// First find the sorting type field if it exists
421
					foreach ($pkg['fields']['field'] as $field) {
422
						if ($field['type'] == "sorting") {
423
							if ($field['sortablefields']['item']) {
424
								foreach ($field['sortablefields']['item'] as $sf) {
425
									if ($sf['name'] == $_REQUEST['pkg_filter_type']) {
426
										$filter_fieldname = $sf['fieldname'];
427
										#Use a default regex on sortable fields when none is declared
428
										if ($sf['regex']) {
429
											$filter_regex = str_replace("%FILTERTEXT%", $_REQUEST['pkg_filter'], trim($sf['regex']));
430
										} else {
431
											$filter_regex = "/{$_REQUEST['pkg_filter']}/i";
432
										}
433
									}
434
								}
435
							}
436
						}
437
					}
438
				}
439
				// Do we have something to filter on?
440
				unset($filter_matches);
441
				if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
442
					foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
443
						$fieldname = $ip[xml_safe_fieldname($column['fieldname'])];
444
						if ($column['fieldname'] == $filter_fieldname) {
445
							if ($filter_regex) {
446
								//echo "$filter_regex - $fieldname<p/>";
447
								preg_match($filter_regex, $fieldname, $filter_matches);
448
								break;
449
							}
450
						}
451
					}
452
				}
453
				if (!$filter_matches) {
454
					$i++;
455
					continue;
456
				}
457
			}
458
			if ($pkg['adddeleteeditpagefields']['movable']) {
459
				echo "<tr valign=\"top\" class=\"sortable\" id=\"id_{$i}\">\n";
460
			} else {
461
				echo "<tr valign=\"top\">\n";
462
			}
463
			if ($pkg['adddeleteeditpagefields']['columnitem'] != "") {
464
				foreach ($pkg['adddeleteeditpagefields']['columnitem'] as $column) {
465
					if ($column['fieldname'] == "description") {
466
						$class = "listbg";
467
					} else {
468
						$class = "listlr";
469
					}
470
?>
471
					<td class="<?=$class?>" ondblclick="document.location='pkg_edit.php?xml=<?=$xml?>&amp;act=edit&amp;id=<?=$i?>';">
472
<?php
473
					$fieldname = $ip[xml_safe_fieldname($column['fieldname'])];
474
					#Check if columnitem has a type field declared
475
					if ($column['type'] == "checkbox") {
476
						if ($fieldname == "") {
477
							echo gettext("No");
478
						} else {
479
							echo gettext("Yes");
480
						}
481
					} else if ($column['type'] == "interface") {
482
						echo $column['prefix'] . $iflist[$fieldname] . $column['suffix'];
483
					} else {
484
						#Check if columnitem has an encoding field declared
485
						if ($column['encoding'] == "base64") {
486
							echo $column['prefix'] . base64_decode($fieldname) . $column['suffix'];
487
						#Check if there is a custom info to show when $fieldname is not empty
488
						} else if ($column['listmodeon'] && $fieldname != "") {
489
							echo $column['prefix'] . gettext($column['listmodeon']). $column['suffix'];
490
						#Check if there is a custom info to show when $fieldname is empty
491
						} else if ($column['listmodeoff'] && $fieldname == "") {
492
							echo $column['prefix'] .gettext($column['listmodeoff']). $column['suffix'];
493
						} else {
494
							echo $column['prefix'] . $fieldname ." ". $column['suffix'];
495
						}
496
					}
497
?>
498
					</td>
499
<?php
500
				} // foreach columnitem
501
			} // if columnitem
502
?>
503
					<td valign="middle" class="list nowrap">
504
						<table border="0" cellspacing="0" cellpadding="1" summary="icons">
505
							<tr>
506
<?php
507
			#Show custom description to edit button if defined
508
			$edit_msg=($pkg['adddeleteeditpagefields']['edittext']?$pkg['adddeleteeditpagefields']['edittext']:"Edit this item");
509
?>
510
								<td><a class="btn btn-xs btn-info" href="pkg_edit.php?xml=<?=$xml?>&amp;act=edit&amp;id=<?=$i?>"><?=$edit_msg?></a></td>
511
<?php
512
			#Show custom description to delete button if defined
513
			$delete_msg=($pkg['adddeleteeditpagefields']['deletetext']?$pkg['adddeleteeditpagefields']['deletetext']:"Delete this item");
514
?>
515
								<td><a class="btn btn-xs btn-danger" href="pkg.php?xml=<?=$xml?>&amp;act=del&amp;id=<?=$i?>"><?=gettext("Delete")?></a></td>
516
							</tr>
517
						</table>
518
					</td>
519
<?php
520
			echo "</tr>\n"; // Pairs with an echo tr some way above
521
			// Handle pagination and display_maximum_rows
522
			if ($display_maximum_rows) {
523
				if ($pagination_counter == ($display_maximum_rows-1) or
524
					$i == (count($evaledvar)-1)) {
525
					$colcount = count($pkg['adddeleteeditpagefields']['columnitem']);
526
					$final_footer = "";
527
					$final_footer .= "<tr><td colspan='$colcount'>";
528
					$final_footer .= "<table width='100%' summary=''><tr>";
529
					$final_footer .= "<td align='left'>";
530
					$startingat = $startdisplayingat - $display_maximum_rows;
531
					if ($startingat > -1) {
532
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat={$startingat}&amp;display_maximum_rows={$display_maximum_rows}'>";
533
					} else if ($startdisplayingat > 1) {
534
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat=0&amp;display_maximum_rows={$display_maximum_rows}'>";
535
					}
536
					$final_footer .= "<font size='2'><< Previous page</font></a>";
537
					if ($tmppp + $display_maximum_rows > count($evaledvar)) {
538
						$endingrecord = count($evaledvar);
539
					} else {
540
						$endingrecord = $tmppp + $display_maximum_rows;
541
					}
542
					$final_footer .= "</td><td align='center'>";
543
					$tmppp++;
544
					$final_footer .= "<font size='2'>Displaying {$tmppp} - {$endingrecord} / " . count($evaledvar) . " records";
545
					$final_footer .= "</font></td><td align='right'>&nbsp;";
546
					if (($i+1) < count($evaledvar)) {
547
						$final_footer .= "<a href='pkg.php?xml=" . $_REQUEST['xml'] . "&amp;startdisplayingat=" . ($startdisplayingat + $display_maximum_rows) . "&amp;display_maximum_rows={$display_maximum_rows}'>";
548
					}
549
					$final_footer .= "<font size='2'>Next page >></font></a>";
550
					$final_footer .= "</td></tr></table></td></tr>";
551
					$i = count($evaledvar);
552
					break;
553
				}
554
			}
555
			$i++;
556
			$pagination_counter++;
557
		} // foreach evaledvar
558
	} // if evaledvar
559
?>
560
				<tr>
561
					<td colspan="<?=$cols?>"></td>
562
					<td>
563
						<table border="0" cellspacing="0" cellpadding="1" summary="icons">
564
							<tr>
565
<?php
566
	#Show custom description to add button if defined
567
	$add_msg=($pkg['adddeleteeditpagefields']['addtext']?$pkg['adddeleteeditpagefields']['addtext']:"Add a new item");
568
?>
569
								<td><a href="pkg_edit.php?xml=<?=$xml?>&amp;id=<?=$i?>" class="btn btn-xs btn-success"><?=gettext('Add')?></a></td>
570
<?php
571
	#Show description button and info if defined
572
	if ($pkg['adddeleteeditpagefields']['description']) {
573
?>
574
								<td>
575
									<i class="fa fa-info-circle"><?=$pkg['adddeleteeditpagefields']['description']?></i>
576
								</td>
577
<?php
578
	}
579
?>
580
							</tr>
581
						</table>
582
					</td>
583
				</tr>
584
				<?=$final_footer?>
585
<?php
586
	#Show save button only when movable is defined
587
	if ($pkg['adddeleteeditpagefields']['movable']) {
588
?>
589
				<tr>
590
					<td><input class="btn btn-primary" type="button" value="Save" name="Submit" onclick="save_changes_to_xml('<?=$xml?>')" /></td>
591
				</tr>
592
<?php
593
	}
594
?>
595
			</table>
596

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

    
602
include("foot.inc"); ?>
(100-100/228)