Subversion Repositories php-qbpwcf

Rev

Rev 3 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3 Rev 226
Line 1... Line 1...
1
#!/usr/bin/php
1
#!/usr/bin/php
2
<?php
2
<?php
3
 
3
 
4
/*
4
/*
5
	QBPWCF, Quick Build PHP website Component base on Fedora Linux.
5
	QBPWCF, Quick Build PHP website Component base on Fedora Linux.
6
    Copyright (C) 2015~2024 Min-Jhin,Chen
6
    Copyright (C) 2014~2025 MIN ZHI, CHEN
7
 
7
 
8
    This file is part of QBPWCF.
8
    This file is part of QBPWCF.
9
 
9
 
10
    QBPWCF is free software: you can redistribute it and/or modify
10
    QBPWCF is free software: you can redistribute it and/or modify
11
    it under the terms of the GNU General Public License as published by
11
    it under the terms of the GNU General Public License as published by
Line 17... Line 17...
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
18
    GNU General Public License for more details.
19
 
19
 
20
    You should have received a copy of the GNU General Public License
20
    You should have received a copy of the GNU General Public License
21
    along with QBPWCF.  If not, see <http://www.gnu.org/licenses/>.
21
    along with QBPWCF.  If not, see <http://www.gnu.org/licenses/>.
22
    
22
 
23
*/
23
*/
24
 
24
 
25
#使用命名空間qbpwcf
25
#使用命名空間qbpwcf
26
namespace qbpwcf;
26
namespace qbpwcf;
27
 
27
 
Line 55... Line 55...
55
	#結束執行,回傳shell 1.
55
	#結束執行,回傳shell 1.
56
	exit(1);
56
	exit(1);
57
 
57
 
58
	}#if end
58
	}#if end
59
 
59
 
60
#設置 include path 
60
#設置 include path
61
set_include_path($output[0].PATH_SEPARATOR.get_include_path());
61
set_include_path($output[0].PATH_SEPARATOR.get_include_path());
62
 
62
 
63
#匯入外部套件
63
#匯入外部套件
64
include("allInOne.php");
64
include("allInOne.php");
65
 
65
 
Line 83... Line 83...
83
#$result["statusCode"],執行結束後的代碼.
83
#$result["statusCode"],執行結束後的代碼.
84
#必填的參數
84
#必填的參數
85
#$conf["command"],字串,要執行的指令與.
85
#$conf["command"],字串,要執行的指令與.
86
$conf["command"]="journalctl";
86
$conf["command"]="journalctl";
87
#$conf["fileArgu"],字串,變數__FILE__的內容.
87
#$conf["fileArgu"],字串,變數__FILE__的內容.
88
$conf["fileArgu"]=__FILE__;		
88
$conf["fileArgu"]=__FILE__;
89
#可省略參數:
89
#可省略參數:
90
#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
90
#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
91
$conf["argu"]=array("-a","|","grep","ssh","|","grep","failed");
91
$conf["argu"]=array("-a","|","grep","ssh","|","grep","failed");
92
#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
92
#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
93
#$conf["arguIsAddr"]=array();	
93
#$conf["arguIsAddr"]=array();
94
#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
94
#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.
95
#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
95
#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.
96
#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
96
#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.
97
#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
97
#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
98
#$conf["enablePrintDescription"]="true";
98
#$conf["enablePrintDescription"]="true";
Line 124... Line 124...
124
#如果執行失敗
124
#如果執行失敗
125
if($callShell["status"]==="false"){
125
if($callShell["status"]==="false"){
126
 
126
 
127
	#印出結果
127
	#印出結果
128
	var_dump($callShell);
128
	var_dump($callShell);
129
	
129
 
130
	#結束執行
130
	#結束執行
131
	exit;
131
	exit;
132
 
132
 
133
	}#if end
133
	}#if end
134
 
134
 
Line 152... Line 152...
152
	#$result["error"],錯誤訊息陣列.
152
	#$result["error"],錯誤訊息陣列.
153
	#$result["warning"],警告訊息鎮列.
153
	#$result["warning"],警告訊息鎮列.
154
	#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
154
	#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
155
	#$result["function"],當前執行的函數名稱.
155
	#$result["function"],當前執行的函數名稱.
156
	#$result["oriStr"],要處理的原始字串內容.
156
	#$result["oriStr"],要處理的原始字串內容.
157
	#$result["content"],處理好的的字串內容.	
157
	#$result["content"],處理好的的字串內容.
158
	#必填的參數:
158
	#必填的參數:
159
	#$conf["stringIn"],字串,要處理的字串.
159
	#$conf["stringIn"],字串,要處理的字串.
160
	$conf["stringIn"]=$line;
160
	$conf["stringIn"]=$line;
161
	#$conf["keyWord"],字串,特定字串.
161
	#$conf["keyWord"],字串,特定字串.
162
	$conf["keyWord"]=$keyWord1;
162
	$conf["keyWord"]=$keyWord1;
163
	$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf);
163
	$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf);
164
	unset($conf);
164
	unset($conf);
165
	
165
 
166
	#如果執行失敗
166
	#如果執行失敗
167
	if($delStrBeforeKeyWord["status"]==="false"){
167
	if($delStrBeforeKeyWord["status"]==="false"){
168
 
168
 
169
		#印出結果
169
		#印出結果
170
		var_dump($delStrBeforeKeyWord);
170
		var_dump($delStrBeforeKeyWord);
171
		
171
 
172
		#結束執行
172
		#結束執行
173
		exit;
173
		exit;
174
 
174
 
175
		}#if end
175
		}#if end
176
		
176
 
177
	#如果執行失敗
177
	#如果執行失敗
178
	if($delStrBeforeKeyWord["founded"]==="false"){
178
	if($delStrBeforeKeyWord["founded"]==="false"){
179
 
179
 
180
		#印出結果
180
		#印出結果
181
		var_dump($delStrBeforeKeyWord);
181
		var_dump($delStrBeforeKeyWord);
182
		
182
 
183
		#跳過該行,繼續執行
183
		#跳過該行,繼續執行
184
		continue;
184
		continue;
185
 
185
 
186
		}#if end
186
		}#if end
187
		
187
 
188
	#取得處理一半的字串
188
	#取得處理一半的字串
189
	$line=$delStrBeforeKeyWord["content"];
189
	$line=$delStrBeforeKeyWord["content"];
190
 
190
 
191
	#用空格分割內容
191
	#用空格分割內容
192
	#涵式說明:
192
	#涵式說明:
Line 214... Line 214...
214
	#如果執行失敗
214
	#如果執行失敗
215
	if($spiltString["status"]==="false"){
215
	if($spiltString["status"]==="false"){
216
 
216
 
217
		#印出結果
217
		#印出結果
218
		var_dump($delStrBeforeKeyWord);
218
		var_dump($delStrBeforeKeyWord);
219
		
219
 
220
		#結束執行
220
		#結束執行
221
		exit;
221
		exit;
222
 
222
 
223
		}#if end
223
		}#if end
224
		
224
 
225
	#如果執行失敗
225
	#如果執行失敗
226
	if($spiltString["found"]==="false"){
226
	if($spiltString["found"]==="false"){
227
 
227
 
228
		#印出結果
228
		#印出結果
229
		var_dump($delStrBeforeKeyWord);
229
		var_dump($delStrBeforeKeyWord);
230
		
230
 
231
		#跳過該行,繼續執行
231
		#跳過該行,繼續執行
232
		continue;
232
		continue;
233
 
233
 
234
		}#if end
234
		}#if end
235
		
235
 
236
	#第一段為有問題的ip
236
	#第一段為有問題的ip
237
	$ip=$spiltString["dataArray"][0];
237
	$ip=$spiltString["dataArray"][0];
238
	
238
 
239
	#如果是第一次發現的ip
239
	#如果是第一次發現的ip
240
	if(!isset($ipsInfo[$ip])){
240
	if(!isset($ipsInfo[$ip])){
241
	
241
 
242
		#計數該ip出現一次
242
		#計數該ip出現一次
243
		$ipsInfo[$ip]=1;
243
		$ipsInfo[$ip]=1;
244
	
244
 
245
		}#if end
245
		}#if end
246
		
246
 
247
	#反之有出現過
247
	#反之有出現過
248
	else{
248
	else{
249
	
249
 
250
		#計數該ip出現一次
250
		#計數該ip出現一次
251
		$ipsInfo[$ip]++;
251
		$ipsInfo[$ip]++;
252
	
252
 
253
		}#else end
253
		}#else end
254
	
254
 
255
	}#foreach end
255
	}#foreach end
256
 
256
 
257
#當還有ip未處理
257
#當還有ip未處理
258
while(count($ipsInfo)>0){
258
while(count($ipsInfo)>0){
259
 
259
 
260
	#max count ip
260
	#max count ip
261
	$maxCountIp=array();
261
	$maxCountIp=array();
262
	
262
 
263
	#排序有問題的ip,次數最多的優先.
263
	#排序有問題的ip,次數最多的優先.
264
	foreach($ipsInfo as $ip => $count){
264
	foreach($ipsInfo as $ip => $count){
265
 
265
 
266
		#如果沒有既有的最多次數ip
266
		#如果沒有既有的最多次數ip
267
		if($maxCountIp===array()){
267
		if($maxCountIp===array()){
268
		
268
 
269
			#將該ip視為最多次數
269
			#將該ip視為最多次數
270
			$maxCountIp["ip"]=$ip;
270
			$maxCountIp["ip"]=$ip;
271
			$maxCountIp["count"]=$count;
271
			$maxCountIp["count"]=$count;
272
		
272
 
273
			}#if end
273
			}#if end
274
 
274
 
275
		#反之
275
		#反之
276
		else{
276
		else{
277
			#如果當前ip的次數更多
277
			#如果當前ip的次數更多
278
			if($maxCountIp["count"]<$count){
278
			if($maxCountIp["count"]<$count){
279
			
279
 
280
				#將該ip視為最多次數
280
				#將該ip視為最多次數
281
				$maxCountIp["ip"]=$ip;
281
				$maxCountIp["ip"]=$ip;
282
				$maxCountIp["count"]=$count;
282
				$maxCountIp["count"]=$count;
283
			
283
 
284
				}#if end
284
				}#if end
285
		
285
 
286
			}#else end
286
			}#else end
287
 
287
 
288
		}#foreach end
288
		}#foreach end
289
 
289
 
290
	#儲存目前次數最多的ip
290
	#儲存目前次數最多的ip
291
	$ip=$maxCountIp["ip"];
291
	$ip=$maxCountIp["ip"];
292
	
292
 
293
	#確認該IP是否已經封鎖
293
	#確認該IP是否已經封鎖
294
	#取得防火牆的IP block清單
294
	#取得防火牆的IP block清單
295
	#cmd:firewall-cmd --list-rich-rule
295
	#cmd:firewall-cmd --list-rich-rule
296
	
296
 
297
	#函式說明:
297
	#函式說明:
298
	#檢查指令的輸出是否含有關鍵字
298
	#檢查指令的輸出是否含有關鍵字
299
	#回傳結果:
299
	#回傳結果:
300
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
300
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
301
	#$result["error"],錯誤訊息.
301
	#$result["error"],錯誤訊息.
Line 316... Line 316...
316
	#$conf["binPath"]="";
316
	#$conf["binPath"]="";
317
	#$conf["argu"],陣列字串,指令搭配的參數,預設不使用.
317
	#$conf["argu"],陣列字串,指令搭配的參數,預設不使用.
318
	$conf["cmd::searchOutPut"]["argu"]=array("--list-rich-rule");
318
	$conf["cmd::searchOutPut"]["argu"]=array("--list-rich-rule");
319
	#$conf["excludeGrep"],字串,"true"代表排除含有 " | grep ".$conf["keyWord"] 字樣的輸出;預設為"false",不排除.
319
	#$conf["excludeGrep"],字串,"true"代表排除含有 " | grep ".$conf["keyWord"] 字樣的輸出;預設為"false",不排除.
320
	#$conf["excludeGrep"]="false";
320
	#$conf["excludeGrep"]="false";
321
	
321
 
322
	#如果有設置 username
322
	#如果有設置 username
323
	if(isset($conf["username"])){
323
	if(isset($conf["username"])){
324
	
324
 
325
		#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
325
		#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
326
		$conf["cmd::searchOutPut"]["username"]=$conf["username"];
326
		$conf["cmd::searchOutPut"]["username"]=$conf["username"];
327
	
327
 
328
		}#if end
328
		}#if end
329
	
329
 
330
	#如果有設置 password
330
	#如果有設置 password
331
	if(isset($conf["password"])){
331
	if(isset($conf["password"])){
332
	
332
 
333
		#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
333
		#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
334
		$conf["cmd::searchOutPut"]["password"]=$conf["password"];
334
		$conf["cmd::searchOutPut"]["password"]=$conf["password"];
335
	
335
 
336
		}#if end
336
		}#if end
337
		
337
 
338
	$searchOutPut=cmd::searchOutPut($conf["cmd::searchOutPut"]);
338
	$searchOutPut=cmd::searchOutPut($conf["cmd::searchOutPut"]);
339
	unset($conf["cmd::searchOutPut"]);
339
	unset($conf["cmd::searchOutPut"]);
340
	
340
 
341
	#如果執行失敗
341
	#如果執行失敗
342
	if($searchOutPut["status"]==="false"){
342
	if($searchOutPut["status"]==="false"){
343
	
343
 
344
		#設置執行失敗
344
		#設置執行失敗
345
		$result["status"]="false";
345
		$result["status"]="false";
346
 
346
 
347
		#設置錯誤訊息
347
		#設置錯誤訊息
348
		$result["error"]=$searchOutPut;
348
		$result["error"]=$searchOutPut;
349
 
349
 
350
		#回傳結果
350
		#回傳結果
351
		return $result;
351
		return $result;
352
	
352
 
353
		}#if end
353
		}#if end
354
	
354
 
355
	#如果有找到關鍵字 " reject"
355
	#如果有找到關鍵字 " reject"
356
	if($searchOutPut["founded"]==="true"){
356
	if($searchOutPut["founded"]==="true"){
357
	
357
 
358
		#移除該ip
358
		#移除該ip
359
		unset($ipsInfo[$ip]);
359
		unset($ipsInfo[$ip]);
360
	
360
 
361
		#跳過該ip
361
		#跳過該ip
362
		continue;
362
		continue;
363
	
363
 
364
		}#if end
364
		}#if end
365
	
365
 
366
	#儲存目前次數最多的ip次數
366
	#儲存目前次數最多的ip次數
367
	$count=$maxCountIp["count"];
367
	$count=$maxCountIp["count"];
368
 
368
 
369
	#提示有問題的 ip
369
	#提示有問題的 ip
370
	echo "IP:".$ip." 拜訪了 ".$count." 次都失敗".PHP_EOL;
370
	echo "IP:".$ip." 拜訪了 ".$count." 次都失敗".PHP_EOL;
371
	echo "是否要 block it?".PHP_EOL;
371
	echo "是否要 block it?".PHP_EOL;
372
	
372
 
373
	#涵式說明:
373
	#涵式說明:
374
	#讀取標準I/O的一行輸入.並提供提示說明.
374
	#讀取標準I/O的一行輸入.並提供提示說明.
375
	#回傳的結果:
375
	#回傳的結果:
376
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
376
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
377
	#$result["error"],錯誤訊息.
377
	#$result["error"],錯誤訊息.
Line 383... Line 383...
383
	#可省略的參數:
383
	#可省略的參數:
384
	#$conf["newLineBreak"],字串,是否$conf["commentsArray"]的每個元素後面都要斷行,"false"代表不要,預設為"true"要斷行.
384
	#$conf["newLineBreak"],字串,是否$conf["commentsArray"]的每個元素後面都要斷行,"false"代表不要,預設為"true"要斷行.
385
	#$conf["newLineBreak"]="false";
385
	#$conf["newLineBreak"]="false";
386
	$readLine=cmd::readLine($conf);
386
	$readLine=cmd::readLine($conf);
387
	unset($conf);
387
	unset($conf);
388
	
388
 
389
	#如果讀取失敗
389
	#如果讀取失敗
390
	if($readLine["status"]==="false"){
390
	if($readLine["status"]==="false"){
391
	
391
 
392
		#印出結果
392
		#印出結果
393
		var_dump($readLine);
393
		var_dump($readLine);
394
		
394
 
395
		#結束執行
395
		#結束執行
396
		exit;
396
		exit;
397
		
397
 
398
		}#if end
398
		}#if end
399
	
399
 
400
	#取得輸入的內容
400
	#取得輸入的內容
401
	$input=$readLine["content"];
401
	$input=$readLine["content"];
402
	
402
 
403
	#判斷輸入
403
	#判斷輸入
404
	switch($input){
404
	switch($input){
405
		
405
 
406
		#如果輸入 "y"
406
		#如果輸入 "y"
407
		case "y":
407
		case "y":
408
		
408
 
409
			#封鎖該ip
409
			#封鎖該ip
410
			#涵式說明:
410
			#涵式說明:
411
			#呼叫shell依序執行系統命令,並取得回傳的內容.
411
			#呼叫shell依序執行系統命令,並取得回傳的內容.
412
			#回傳的結果:
412
			#回傳的結果:
413
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
413
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
Line 417... Line 417...
417
			#$result["output"],爲執行完每個指令後的輸出陣列.
417
			#$result["output"],爲執行完每個指令後的輸出陣列.
418
			#必填的參數
418
			#必填的參數
419
			#$conf["command"],字串陣列,要執行的指令.
419
			#$conf["command"],字串陣列,要執行的指令.
420
			$conf["external::callShellMulti"]["command"]=array("echo");
420
			$conf["external::callShellMulti"]["command"]=array("echo");
421
			#$conf["fileArgu"],字串,變數__FILE__的內容,預設為當前檔案的路徑與名稱.
421
			#$conf["fileArgu"],字串,變數__FILE__的內容,預設為當前檔案的路徑與名稱.
422
			$conf["external::callShellMulti"]["fileArgu"]=__FILE__;		
422
			$conf["external::callShellMulti"]["fileArgu"]=__FILE__;
423
			#可省略參數:
423
			#可省略參數:
424
			#$conf["argu"],陣字串列,執行各個$conf["command"]時指令搭配的參數,預設為空陣列.
424
			#$conf["argu"],陣字串列,執行各個$conf["command"]時指令搭配的參數,預設為空陣列.
425
			$conf["external::callShellMulti"]["argu"]=array(array($ip,"|","block_ip.sh"));
425
			$conf["external::callShellMulti"]["argu"]=array(array($ip,"|","block_ip.sh"));
426
			#$conf["enablePrintDescription"],字串陣列,執行各個$conf["command"]時是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,其數量須與$conf["command"]的元素數量相同,若只有一個元素,則代表是每個$conf["command"]執行時都用此參數.
426
			#$conf["enablePrintDescription"],字串陣列,執行各個$conf["command"]時是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,其數量須與$conf["command"]的元素數量相同,若只有一個元素,則代表是每個$conf["command"]執行時都用此參數.
427
			#$conf["enablePrintDescription"]=array("false");
427
			#$conf["enablePrintDescription"]=array("false");
Line 438... Line 438...
438
			#備註:
438
			#備註:
439
			#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行.
439
			#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行.
440
			#參考資料:
440
			#參考資料:
441
			#exec=>http://php.net/manual/en/function.exec.php
441
			#exec=>http://php.net/manual/en/function.exec.php
442
			#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
442
			#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
443
			#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php	
443
			#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
444
			$callShellMulti=external::callShellMulti($conf["external::callShellMulti"]);
444
			$callShellMulti=external::callShellMulti($conf["external::callShellMulti"]);
445
			unset($conf["external::callShellMulti"]);
445
			unset($conf["external::callShellMulti"]);
446
		
446
 
447
			#如果執行失敗
447
			#如果執行失敗
448
			if($callShellMulti["status"]==="false"){
448
			if($callShellMulti["status"]==="false"){
449
			
449
 
450
				#設置執行失敗
450
				#設置執行失敗
451
				$result["status"]="false";
451
				$result["status"]="false";
452
 
452
 
453
				#設置錯誤訊息
453
				#設置錯誤訊息
454
				$result["error"]=$callShellMulti;
454
				$result["error"]=$callShellMulti;
455
 
455
 
456
				#回傳結果
456
				#回傳結果
457
				return $result;
457
				return $result;
458
			
458
 
459
				}#if end
459
				}#if end
460
				
460
 
461
			#移除該ip
461
			#移除該ip
462
			unset($ipsInfo[$ip]);
462
			unset($ipsInfo[$ip]);
463
						
463
 
464
			#結束執行
464
			#結束執行
465
			break;
465
			break;
466
		
466
 
467
		#如果輸入 "n"
467
		#如果輸入 "n"
468
		case "n":
468
		case "n":
469
		
469
 
470
			#移除該ip
470
			#移除該ip
471
			unset($ipsInfo[$ip]);
471
			unset($ipsInfo[$ip]);
472
		
472
 
473
			#換下一個ip
473
			#換下一個ip
474
			continue 2;
474
			continue 2;
475
		
475
 
476
			#結束執行
476
			#結束執行
477
			break;
477
			break;
478
			
478
 
479
		#其他輸入內容
479
		#其他輸入內容
480
		default:
480
		default:
481
		
481
 
482
			#重複詢問
482
			#重複詢問
483
			continue 2;
483
			continue 2;
484
		
484
 
485
		}#switch end
485
		}#switch end
486
 
486
 
487
	}#while end
487
	}#while end
488
 
488
 
489
?>
489
?>