Subversion Repositories php-qbpwcf

Rev

Rev 68 | Rev 226 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 liveuser 1
<?php
2
 
3
/*
4
 
5
	QBPWCF, Quick Build PHP website Component base on Fedora Linux.
6
    Copyright (C) 2015~2025 Min-Jhin,Chen
7
 
8
    This file is part of QBPWCF.
9
 
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
12
    the Free Software Foundation, either version 3 of the License, or
13
    (at your option) any later version.
14
 
15
    QBPWCF is distributed in the hope that it will be useful,
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
    GNU General Public License for more details.
19
 
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/>.
22
 
23
*/
24
 
25
namespace qbpwcf;
26
 
27
#import all lib by composer(include ratchet)
28
require 'composer/vendor/autoload.php';
29
 
30
#使用 Ratchet\MessageComponentInterface 界面
31
use Ratchet\MessageComponentInterface;
32
 
33
#使用 Ratchet\ConnectionInterface 界面
34
use Ratchet\ConnectionInterface;
35
 
36
#用 Chat 類別來實作 MessageComponentInterface 界面
37
class Chat implements MessageComponentInterface{
38
 
39
	#初始化儲存使用者資訊的陣列
40
	private $connInfo=array();	
41
 
42
	#初始化儲存未傳送出去的留言訊息
43
	#"fromId",訊息來源的id
44
	#"toId",訊息目的的id
45
	#"fromUserId",訊息來源的userId
46
	#"toUserId",訊息目標的userId
47
	#"msg",傳送的訊息
48
	private $unSendMsg=array();
49
 
50
	#初始化一開始尚未能夠連線到資料庫
51
	private static $dbTouchable=false;
52
 
53
	#初始化db的位置
54
	public static $dbAddress="localhost";	
55
 
56
	#初始化連線db用的帳戶
57
	public static $dbAccount="root";
58
 
59
	#初始化連線的db名稱
60
	public static $dbName="test";
61
 
62
	#初始化連線db時用的密碼
63
	public static $dbPassword="";
64
 
65
	#初始化連線db的哪個資料表
66
	public static $memberTableName="member";
67
 
68
	#初始化登入時用來驗證帳號的資料表欄位名稱
69
	public static $accountCol="account";
70
 
71
	#初始化登入時用來驗證密碼的資料表欄位名稱,設為""代表不用密碼來認證
72
	public static $passwordCol="password";
73
 
74
	#建構子
75
	public function __construct(){
76
 
77
		#如果尚未可以上資料庫
78
		if(!(self::$dbTouchable)){
79
 
80
			#嘗試連線到目標資料庫.資料表
81
			#涵式說明:
82
			#一次取得資料庫、表的資料
83
			#回傳的結果
84
			#$result["status"],執行結果"true"為成功;"false"為執行失敗。
85
			#$result["error"],錯誤訊息陣列。
86
			#$result["function"],當前執行的漢書名稱.
87
			#$result["dataColumnName"],抓取的資料欄位名稱陣列.
88
				#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
89
			#$result["dataContent"],爲資料的內容。
90
			#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
91
				#$dataSetNum 爲第$dataSetNum+1筆資料
92
				#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
93
			#$result["dataCount"],爲取得的資料筆數。
94
			#$result["sql"],執行的sql字串.
95
			#必填的參數:
96
			$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
97
			$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
98
			$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
99
			$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
100
			$conf["db::fastGetDbData"]["columnYouWant"]=array("id",self::$accountCol);#你想要的欄位!,若設為「array("*")」則代表全部欄位.
101
 
102
			#如果 $passwordCol 不為空
103
			if(self::$passwordCol!=""){
104
 
105
				#加上密碼欄位
106
				$conf["db::fastGetDbData"]["columnYouWant"][]=self::$passwordCol;
107
 
108
				}#if end
109
 
110
			#可省略的參數:
111
			$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
112
			#$conf["db::fastGetDbData"]["WhereColumnName"]=array("account","password");#用於判斷語句的欄位項目陣列。
113
			#$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac,$pw);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
114
			#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
115
			#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
116
			#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
117
			#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
118
			#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
119
			#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
120
			$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
121
			#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
122
			#備註:
123
			#建議在查詢資料前,能夠檢查是否每個欄位都存在.
124
			$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
125
			unset($conf["db::fastGetDbData"]);
126
 
127
			#如果取得資料失敗
128
			if($fastGetDbData["status"]==="false"){
129
 
130
				#設置執行失敗
131
				$result["status"]="false";
132
 
133
				#設置執行錯誤訊息
134
				$result["error"]=$fastGetDbData;
135
 
136
				#印出debug訊息
137
				var_dump($result);
138
 
139
				#結束程式
140
				exit;
141
 
142
				}#if end
143
 
144
			#連線成功,將self::dbTouchable設為true
145
			self::$dbTouchable=true;
146
 
147
			}#if end
148
 
149
        	$this->clients = new \SplObjectStorage;
150
 
151
		}#funciton __construct end
152
 
153
	#當用戶與伺服器建立連線時
154
    	public function onOpen(ConnectionInterface $conn){
155
 
156
		// Store the new connection to send messages to later
157
        	$this->clients->attach($conn);
158
 
159
		#提示server有clent連上web socket.
160
        	echo "New connection! ({$conn->resourceId})\n";
161
 
162
		#用client的id為index來儲存額外的資訊
163
        	#元素 "conn" 代表已經建立連線的ConnectionInterface物件
164
 		#元素 "talkTo" 代表要跟誰講話
165
		#元素 "userId" 代表辨識使用者的id
166
		#元素 "loigin=array("ac","pw")" 代表client輸入的帳號與密碼
167
     	  	 #$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""),"type"=>"");
168
        	$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""));
169
 
170
		#提示登入		
171
		$conn->send(json_encode("Please input your account! ex:account:ws1"));
172
 
173
		}#function onOpen end
174
 
175
	#當伺服器收到訊息時
176
   	public function onMessage(ConnectionInterface $from, $msg){
177
 
178
		#如果該連線沒有使用者id
179
		if($this->connInfo[$from->resourceId]["userId"]===""){
180
 
181
			#如果尚未輸入帳戶
182
			if($this->connInfo[$from->resourceId]["login"]["ac"]===""){
183
 
184
				#如果 $msg 長度大於 "account:"
185
				if(strlen($msg) > strlen("account:")){
186
 
187
					#檢查有無前置字元 "account:"
188
					#函式說明:
189
					#將字串特定關鍵字與其前面的內容剔除
190
					#回傳結果:
191
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
192
					#$result["error"],錯誤訊息陣列.
193
					#$result["warning"],警告訊息鎮列.
194
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
195
					#$result["function"],當前執行的函數名稱.
196
					#$result["oriStr"],要處理的原始字串內容.
197
					#$result["content"],處理好的的字串內容.
198
					#必填的參數:
199
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
200
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="account:";#特定字串.
201
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
202
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
203
 
204
					#如果移除前置字元失敗
205
					if($delStrBeforeKeyWord["status"]==="false"){
206
 
207
						#設置執行失敗
208
						$result["status"]="false";
209
 
210
						#設置執行錯誤訊息
211
						$result["error"]=$delStrBeforeKeyWord;
212
 
213
						#回傳結果
214
						return $result;
215
 
216
						}#if end
217
 
218
					#如果有符合條件的前置字元
219
					if($delStrBeforeKeyWord["founded"]==="true"){
220
 
221
						#儲存帳戶
222
						$this->connInfo[$from->resourceId]["login"]["ac"]=$delStrBeforeKeyWord["content"];
223
 
224
						}#if end
225
 
226
					#反之代表格式錯誤	
227
					else{
228
 
229
						#提示輸入帳戶
230
						$from->send(json_encode("Please input your account! ex:account:ws1"));
231
 
232
						#結束程式
233
						return true;
234
 
235
						}#else end
236
 
237
					}#if end
238
 
239
				#反之代表輸入錯誤格式的account
240
				else{
241
 
242
					#提示輸入帳號	
243
					$from->send(json_encode("Please input your account! ex:account:ws1"));
244
 
245
					#結束程式
246
					return true;
247
 
248
					}#else end
249
 
250
				}#if end
251
 
252
			#如果有設置密碼欄位
253
			if(self::$passwordCol!==""){
254
 
255
				#如果尚未輸入密碼
256
				if($this->connInfo[$from->resourceId]["login"]["pw"]===""){
257
 
258
					#$msg 長度大於 "password:"
259
					if(strlen($msg) > strlen("password:")){
260
 
261
						#檢查有無前置字元 "password:"
262
						#函式說明:
263
						#將字串特定關鍵字與其前面的內容剔除
264
						#回傳結果:
265
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
266
						#$result["error"],錯誤訊息陣列.
267
						#$result["warning"],警告訊息鎮列.
268
						#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
269
						#$result["function"],當前執行的函數名稱.
270
						#$result["oriStr"],要處理的原始字串內容.
271
						#$result["content"],處理好的的字串內容.
272
						#必填的參數:
273
						$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
274
						$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="password:";#特定字串.
275
						$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
276
						unset($conf["stringProcess::delStrBeforeKeyWord"]);
277
 
278
						#如果移除前置字元失敗
279
						if($delStrBeforeKeyWord["status"]==="false"){
280
 
281
							#設置執行失敗
282
							$result["status"]="false";
283
 
284
							#設置執行錯誤訊息
285
							$result["error"]=$delStrBeforeKeyWord;
286
 
287
							#回傳結果
288
							return $result;
289
 
290
							}#if end
291
 
292
						#如果有符合條件的前置字元
293
						if($delStrBeforeKeyWord["founded"]==="true"){
294
 
295
							#儲存密碼
296
							$this->connInfo[$from->resourceId]["login"]["pw"]=$delStrBeforeKeyWord["content"];
297
 
298
							}#if end
299
 
300
						#反之代表格式錯誤
301
						else{
302
 
303
							#提示輸入密碼
304
							$from->send(json_encode("Please input your password! ex:password:ws1"));
305
 
306
							#結束程式
307
							return true;
308
 
309
							}#else end
310
 
311
						}#if end
312
 
313
					#反之代表格式錯誤
314
					else{
315
 
316
						#提示輸入密碼		
317
						$from->send(json_encode("Please input your password! ex:password:ws1"));
318
 
319
						#結束程式
320
						return true;
321
 
322
						}#else end
323
 
324
					}#if end
325
 
326
				}#if end
327
 
328
			#如果已經輸入帳號了
329
			if($this->connInfo[$from->resourceId]["login"]["ac"]!=""){
330
 
331
				#設置可以進行驗證
332
				$startAuth=true;
333
 
334
				#另存帳號
335
				$ac=$this->connInfo[$from->resourceId]["login"]["ac"];
336
 
337
				#初始化密碼
338
				$pw="";
339
 
340
				#如果有設置密碼欄位
341
				if(self::$passwordCol!==""){
342
 
343
					#如果client已經輸入密碼了
344
					if($this->connInfo[$from->resourceId]["login"]["pw"]!=""){
345
 
346
						#另存密碼
347
						$pw=md5($this->connInfo[$from->resourceId]["login"]["pw"]);
348
 
349
						}#if end
350
 
351
					#反之
352
					else{
353
 
354
						#設置尚不能進行認證
355
						$startAuth=false;
356
 
357
						}#else end
358
 
359
					}#if end
360
 
361
				#如果尚不能進行驗證
362
				if(!$startAuth){
363
 
364
					#結束程式
365
					return true;
366
 
367
					}#if end
368
 
369
				#檢查有無符合的帳戶密碼
370
				#涵式說明:
371
				#一次取得資料庫、表的資料
372
				#回傳的結果
373
				#$result["status"],執行結果"true"為成功;"false"為執行失敗。
374
				#$result["error"],錯誤訊息陣列。
375
				#$result["function"],當前執行的漢書名稱.
376
				#$result["dataColumnName"],抓取的資料欄位名稱陣列.
377
					#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
378
				#$result["dataContent"],爲資料的內容。
379
				#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
380
					#$dataSetNum 爲第$dataSetNum+1筆資料
381
					#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
382
				#$result["dataCount"],爲取得的資料筆數。
383
				#$result["sql"],執行的sql字串.
384
				#必填的參數:
385
				$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
386
				$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
387
				$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
388
				$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
389
				$conf["db::fastGetDbData"]["columnYouWant"]=array("id");#你想要的欄位!,若設為「array("*")」則代表全部欄位.
390
				#可省略的參數:
391
				$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
392
				$conf["db::fastGetDbData"]["WhereColumnName"]=array(self::$accountCol);#用於判斷語句的欄位項目陣列。
393
				$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
394
 
395
				#如果有輸入密碼
396
				if($pw!==""){
397
 
398
					#新增要判斷 self::$password 欄位,是否有於 $pw
399
					$conf["db::fastGetDbData"]["WhereColumnName"][]=self::$passwordCol;
400
					$conf["db::fastGetDbData"]["WhereColumnValue"][]=$pw;
401
 
402
					}#if end
403
 
404
				#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
405
				#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
406
				#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
407
				#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
408
				#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
409
				#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
410
				$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
411
				#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
412
				#備註:
413
				#建議在查詢資料前,能夠檢查是否每個欄位都存在.
414
				$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
415
				unset($conf["db::fastGetDbData"]);
416
 
417
				#如果取得資料失敗
418
				if($fastGetDbData["status"]==="false"){
419
 
420
					#設置執行失敗
421
					$result["status"]="false";
422
 
423
					#設置執行錯誤訊息
424
					$result["error"]=$fastGetDbData;
425
 
426
					#印出結果
427
					#var_dump($result);
428
 
429
					#提示server有資料庫錯誤
430
					echo "dbError!";
431
 
432
					#結束程式
433
					exit;
434
 
435
					}#if end
436
 
437
				#如果沒有一筆資料
438
				if($fastGetDbData["dataCount"]!==1){
439
 
440
					#代表登入失敗
441
 
442
					#清空登入用的帳戶
443
					$this->connInfo[$from->resourceId]["login"]["ac"]="";
444
 
445
					#清空登入用的密碼
446
					$this->connInfo[$from->resourceId]["login"]["pw"]="";
447
 
448
					#提示登入失敗					
449
					$from->send(json_encode("Login failed, please input account. ex:account:ws1"));
450
 
451
					#執行到這即可
452
					return true;
453
 
454
					}#if end
455
 
456
				#反之代表帳戶資訊正確
457
				else{
458
 
459
					#設置 $myUserId
460
					$myUserId=$this->connInfo[$from->resourceId]["userId"]=$fastGetDbData["dataContent"]["id"][0];
461
 
462
					#設置 $myId
463
					$myId=$from->resourceId;
464
 
465
					#提示登入成功
466
					$from->send(json_encode("Login successfully!"));
467
 
468
					#檢查是否有訊息是要給自己的
469
					foreach($this->unSendMsg as $index => $historyMsg){
470
 
471
						#如果有要給自己的訊息
472
						if($myUserId===$historyMsg["toUserId"]){
473
 
474
							#接收別人給的留言
475
							$from->send(json_encode($historyMsg["msg"]));
476
 
477
							#有幾個人在線上就執行幾次
478
							foreach($this->connInfo as $toId => $cInfo){
479
 
480
								#如果是自己
481
								if($myId===$toId ){
482
 
483
									#跳過
484
									continue;
485
 
486
									}#if end
487
 
488
								#如果留言的對象有在線上
489
								if($historyMsg["fromUserId"]===$cInfo["userId"]){
490
 
491
									#檢查對方是否已經在自己的通話清單裡面了
492
 
493
									#初始化要將對方加到自己的對話清單裡面
494
									$add=false;
495
 
496
									#根據自己的每個通話對象
497
									foreach($this->connInfo[$myId]["talkTo"] as $myToIndex=>$myToCinfo ){
498
 
499
										#如果對對方已經存在於自己的對話清單裡面了
500
										if($myToCinfo["userId"]===$historyMsg["fromUserId"] && $myId===$historyMsg["fromId"]){
501
 
502
											#設置不要將對方加到自己的對話清單裡面
503
											$add=false;
504
 
505
											#跳出foreach
506
											break;
507
 
508
											}#if end
509
 
510
										}#foreach end
511
 
512
									#如果要將對方加到自己的對話清單裡面
513
									if($add){
514
 
515
										#將對方加到自己的talkTo清單裡面
516
										$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$historyMsg["fromUserId"]);
517
 
518
										}#if end
519
 
520
									#檢查自己有沒有在對方talkTo清單裡面
521
 
522
									#假設對方需要加自己到對話清單裡面
523
									$add=true;
524
 
525
									#檢查通話對象能否跟自己對話
526
 
527
									#依據對方每個通話的對象
528
									foreach($this->connInfo[$toId]["talkTo"] as $talkToIndex=>$talkToCinfo){
529
 
530
										#如果自己的userId已經在對方的對話清單裡面了
531
										if($myUserId===$talkToCinfo["userId"]){
532
 
533
											#如果對方對話userId對應的id不在線上
534
											if(!isset($this->connInfo[$toId])){
535
 
536
												#檢查對方對話清單是否已經含有自己的id與userId了
537
 
538
												#假設對方對話清單沒有自己的id與userId
539
												$update=true;
540
 
541
												#依據對方每個通話的對象
542
												foreach($this->connInfo[$toId]["talkTo"] as $ceToIndex=>$ceToCinfo){
543
 
544
													#如果對方對話清單已經含有自己的id與userId了												
545
													if($ceToCinfo["id"]===$myId && $ceToCinfo["userId"]===$myUserId){
546
 
547
														#設置不需要更新
548
														$update=false;
549
 
550
														#設置對方不需要加自己到對話清單裡面
551
														$add=false;
552
 
553
														}#if end
554
 
555
													}#foreach end
556
 
557
												#如果對方對話清單沒有自己的id與userId
558
												if($update){
559
 
560
													#將自己在對方對話清單裡面的id改成現在的id
561
													$this->connInfo[$toId]["talkTo"][$talkToIndex]["id"]=$myId;
562
 
563
													}#if end
564
 
565
												#反之對方對話清單已經有自己的id與userId
566
												else{
567
 
568
													#移除對方該已經斷線的對話id
569
													unset($this->connInfo[$toId]["talkTo"][$talkToIndex]);
570
 
571
													}#else end
572
 
573
												}#if end
574
 
575
											}#if end
576
 
577
										}#foreach end
578
 
579
									#如果對方需要加自己到對話清單裡面
580
									if($add){
581
 
582
										#讓通話對象也可以傳送訊息回來
583
										$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId);
584
 
585
										}#if end
586
 
587
									}#if end
588
 
589
								}#foreach end
590
 
591
							#移除留言紀錄
592
							unset($this->unSendMsg[$index]);
593
 
594
							}#if end
595
 
596
						}#foreach end
597
 
598
					#檢查線上是否有人想跟我對話
599
 
600
					#有幾個人在線上就執行幾次
601
					foreach($this->connInfo as $toId => $cInfo){
602
 
603
						#如果是自己
604
						if($myId===$toId){
605
 
606
							#跳過
607
							continue;
608
 
609
							}#if end
610
 
611
						#該cliet目前再跟幾個人通話,就執行幾次
612
						foreach($cInfo["talkTo"] as $tIndex=>$tInfo){
613
 
614
							#如果自己的userId在對方的對話清單裡面
615
							if($myUserId===$tInfo["userId"]){
616
 
617
								#假設自己需要被對方加到對話清單裡面
618
								$add=true;
619
 
620
								#檢查自己是否已經在對方的對話清單裡面
621
 
622
								#對方有幾個通話對象就執行幾次
623
								foreach($this->connInfo[$toId]["talkTo"] as $toIndex=>$toCinfo){
624
 
625
									#如果自己已經在對方的對話清單裡面
626
									if($myUserId===$toCinfo["userId"] && $myId===$toCinfo["id"]){
627
 
628
										#設置自己不需要被對方加到對話清單裡面
629
										$add=false;
630
 
631
										#跳出迴圈
632
										break;
633
 
634
										}#if end
635
 
636
									}#foreach end
637
 
638
								#另存針對自己userId的連線id
639
								$oneIdOfMyUserid=$this->connInfo[$toId]["talkTo"][$tIndex]["id"];
640
 
641
								#如果對方對話清單裡面的用戶id不在線
642
								if(!isset($this->connInfo[$oneIdOfMyUserid])){
643
 
644
									#假設要將自己在對方對話清單裡面的id改成現在的id
645
									$update=true;
646
 
647
									#自己不需要被對方加到對話清單裡面
648
									$add=false;
649
 
650
									#檢查自己的id是否已經在對方的對話id裡面
651
									foreach($this->connInfo[$toId]["talkTo"] as $ceIndex=>$ceInfo){
652
 
653
										#如果自己的id已經在對方的對話清單裡面
654
										if($myId===$ceInfo["id"]){
655
 
656
											#設置不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
657
											$update=false;
658
 
659
											#跳出迴圈
660
											break;
661
 
662
											}#if end
663
 
664
										}#foreach end
665
 
666
									#如果要將自己在對方對話清單裡面的id改成現在的id
667
									if($update){
668
 
669
										#將自己在對方對話清單裡面的id改成現在的id
670
										$this->connInfo[$toId]["talkTo"][$tIndex]["id"]=$myId;
671
 
672
										}#if end
673
 
674
									#反之不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
675
									else{
676
 
677
										#移除該對話id
678
										unset($this->connInfo[$toId]["talkTo"][$tIndex]);
679
 
680
										}#else end
681
 
682
									}#if end	
683
 
684
								#如果要將自己加到對方的的通話清單裡面
685
								if($add){
686
 
687
									#將自己加到對方的的通話清單裡面
688
									$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId);			
689
 
690
									}#if end								
691
 
692
								#檢查對方是否已經在自己的對話清單裡面
693
 
694
								#設置要新增對方到自己的對話清單裡面.
695
								$add=true;
696
 
697
								#自己有幾個對話對象就執行幾次
698
								foreach($this->connInfo[$myId]["talkTo"] as $mtIndex=>$mtInfo){
699
 
700
									#對方的userId與id若在自己的對話清單裡面
701
									if($mtInfo["userId"]===$cInfo["userId"] && $mtInfo["id"]===$toId){
702
 
703
										#設置不需要新增對方到自己的對話清單裡面
704
										$add=false;
705
 
706
										#跳出 foreach
707
										break;
708
 
709
										}#if end
710
 
711
									}#foreache end
712
 
713
								#如果要新增對方到自己的對話清單裡面.
714
								if($add){
715
 
716
									#將對方加到自己的對話清單裡面
717
									$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$cInfo["userId"]);
718
 
719
									}#if end
720
 
721
								}#if end
722
 
723
							}#foreach end
724
 
725
						}#foreach end
726
 
727
					#結束認證成功後的流程
728
					return true;
729
 
730
					}#else end
731
 
732
				}#else end
733
 
734
			#結束認證流程
735
			return true;	
736
 
737
			}#if end
738
 
739
		#如果收到 "id?"
740
		else if($msg==="id?"){
741
 
742
			#傳他人的id給client
743
			$from->send(json_encode($from->resourceId));
744
 
745
			#回傳成功
746
			return true;
747
 
748
			}#if end
749
 
750
		#如果收到 "ids?"
751
		else if($msg==="ids?"){
752
 
753
			#初始化儲存其他人的id
754
			$idsArray=array();
755
 
756
			#針對所的client
757
			foreach ($this->clients as $client){
758
 
759
				#排除自己
760
				if($from !== $client){
761
 
762
					#取得其他人的id
763
					$idsArray[]=$client->resourceId;
764
 
765
					}#if end
766
 
767
				}#foreach end			
768
 
769
			#傳他人的id給client
770
			$from->send(json_encode($idsArray));
771
 
772
			#回傳成功
773
			return true;
774
 
775
			}#if end
776
 
777
		#如果收到 "talkTo?"
778
		else if($msg==="talkTo?"){
779
 
780
			#正在對話的對象id給client
781
			$from->send(json_encode($this->connInfo[$from->resourceId]["talkTo"]));
782
 
783
			#回傳成功
784
			return true;
785
 
786
			}#if end
787
 
788
		#如果收到的$msg長度大於 "talkTo:"
789
		if(strlen($msg)>strlen("talkTo:")){
790
 
791
			#如果收到開頭為 "talkTo:"    
792
			#涵式說明:
793
			#取得符合特定字首與字尾的字串
794
			#回傳的結果:
795
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
796
			#$result["function"],當前執行的函數名稱.
797
			#$result["error"],錯誤訊息陣列.
798
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
799
			#$result["returnString"],爲符合字首條件的字串內容。
800
			#必填參數:
801
			#$conf["checkString"],字串,要檢查的字串.
802
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
803
			#可省略參數:
804
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
805
			$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
806
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
807
			#$conf["tailWord"]="";
808
			#參考資料:
809
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
810
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
811
			unset($conf["search::getMeetConditionsString"]);
812
 
813
			#如果選找前置字串 "talkTo:" 失敗
814
			if($getMeetConditionsString["status"]==="false"){
815
 
816
				#設置執行失敗
817
				$result["status"]="false";
818
 
819
				#設置執行錯誤訊息
820
				$result["error"]=$getMeetConditionsString;
821
 
822
				#回傳結果
823
				return $result;
824
 
825
				}#if end
826
 
827
			#如果存在 "talkTo:" 前置字串
828
			if($getMeetConditionsString["founded"]==="true"){
829
 
830
				#用 "talkTo:" 分割 $buf
831
				#涵式說明:
832
				#將固定格式的字串分開,並回傳分開的結果。
833
				#回傳結果:
834
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
835
				#$result["error"],錯誤訊息陣列
836
				#$result["function"],當前執行的函數名稱.
837
				#$result["oriStr"],要分割的原始字串內容
838
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
839
				#$result["dataCounts"],爲總共分成幾段
840
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
841
				#必填的參數:
842
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
843
				$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
844
				#可省略參數:
845
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
846
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
847
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
848
				unset($conf["stringProcess::spiltString"]);
849
 
850
				#如果分割字串失敗
851
				if($spiltString["status"]==="false"){
852
 
853
					#設置執行失敗
854
					$result["status"]="false";
855
 
856
					#設置執行錯誤訊息
857
					$result["error"]=$spiltString;
858
 
859
					#回傳結果
860
					return $result;
861
 
862
					}#if end
863
 
864
				#如果剛好分割出一筆資料
865
				if($spiltString["dataCounts"]===1){
866
 
867
					#取得自己的id
868
					$myId=$from->resourceId;
869
 
870
					#取得講話對象的id
871
					$toId=$spiltString["dataArray"][0];
872
 
873
					#設置對象不存在的識別
874
					$targetExist=false;
875
 
876
					#設置通話對象的key
877
					$targetKey="";
878
 
879
					#如果要對話的對象存在
880
					if(isset($this->connInfo[$toId])){
881
 
882
						#取得對象的userId
883
						$toUserId=$this->connInfo[$toId]["userId"];
884
 
885
						#取得同userId的對象id們
886
 
887
						#初始化同userId的對象id
888
						$targetC=array();
889
 
890
						#針對每個連線
891
						foreach($this->connInfo as $eachIndex=>$eachInfo){
892
 
893
							#如果是自己
894
							if($eachIndex===$myId){
895
 
896
								#跳到下一輪
897
								continue;
898
 
899
								}#if end
900
 
901
							#如果是同userId的對象
902
							if($eachInfo["userId"]===$toUserId){
903
 
904
								#取出連線
905
								$targetC[$eachIndex]=$this->connInfo[$eachIndex];
906
 
907
								}#if end
908
 
909
							}#foreach end
910
 
911
						#針對每個同userId的連線
912
						foreach($targetC as $tcIndex=>$tcInfo){
913
 
914
							#檢查自己的對話對象是否已經在清單裡面了
915
 
916
							#假設對象可以加到自己對話清單裡面
917
							$add=true;
918
 
919
							#針對每個要講話的對象
920
							foreach($this->connInfo[$myId]["talkTo"] as $index=>$cInfo){
921
 
922
								#如果對話對象已經在清單裡面了
923
								if($this->connInfo[$tcIndex]["userId"]===$cInfo["userId"] && $tcIndex===$cInfo["id"]){
924
 
925
									#設置不要再加到清單裡面
926
									$add=false;
927
 
928
									#跳出foreach
929
									break;
930
 
931
									}#if end								
932
 
933
								}#foreach end
934
 
935
							#如果要加入到對話清單裡面
936
							if($add){
937
 
938
								#增加自己的對話對象
939
								$this->connInfo[$myId]["talkTo"][]=array("id"=>$tcIndex,"userId"=>$this->connInfo[$tcIndex]["userId"]);
940
 
941
								#假設對方可以加自己到對話清單裡面
942
								$add=true;
943
 
944
								#檢查通話對象能否跟自己對話
945
								foreach($this->connInfo[$tcIndex]["talkTo"] as $index=>$cInfo){
946
 
947
									#如果對話對象已經在清單裡面了
948
									if($this->connInfo[$myId]["userId"]===$cInfo["userId"]){
949
 
950
										#設置不要再加到清單裡面
951
										$add=false;
952
 
953
										#跳出 foreach
954
										break;
955
 
956
										}#if end
957
 
958
									}#foreach end
959
 
960
								#如果對方可以加自己到對話清單裡面
961
								if($add){
962
 
963
									#讓通話對象也可以傳送訊息回來
964
									$this->connInfo[$tcIndex]["talkTo"][]=array("id"=>$myId,"userId"=>$this->connInfo[$myId]["userId"]);
965
 
966
									}#if end
967
 
968
								#設置要給自己看的訊息
969
								$from->send(json_encode("true"));
970
 
971
								}#if end
972
 
973
							#反之
974
							else{
975
 
976
								#設置要給自己看的訊息
977
								$from->send(json_encode("false"));
978
 
979
								}#else end
980
 
981
							}#foreach end
982
 
983
						#回傳成功
984
						return true;
985
 
986
						}#if end
987
 
988
					#反之不存在
989
					else{
990
 
991
						#設置要給自己看的訊息
992
						$from->send(json_encode("false"));
993
 
994
						#回傳成功
995
						return true;
996
 
997
						}#else end
998
 
999
					}#if end
1000
 
1001
				}#if end
1002
 
1003
			}#if end
1004
 
1005
		#如果有要講話的對象
1006
		if(count($this->connInfo[$from->resourceId]["talkTo"])>0){
1007
 
1008
			#依據每個對話對象
1009
			foreach($this->connInfo[$from->resourceId]["talkTo"] as $index => $cInfo){
1010
 
1011
				#如果要講話的對象不存在(socket已經斷開)
1012
				if(!isset($this->connInfo[$cInfo["id"]])){
1013
 
1014
					#將訊息儲存起來,等對象上線後再把訊息傳過去.
1015
					$this->unSendMsg[]=array(
1016
						"fromId"=>$from->resourceId,
1017
						"toId"=>"",
1018
						"fromUserId"=>$this->connInfo[$from->resourceId]["userId"],
1019
						"toUserId"=>$cInfo["userId"],
1020
						"msg"=>$msg
1021
						);
1022
 
1023
					}#if end
1024
 
1025
				#反之
1026
				else{
1027
 
1028
					#另存 ConnectionInterface 物件
1029
					$connObject=$this->connInfo[$cInfo["id"]]["conn"];
1030
 
1031
					#傳送訊息給對方
1032
					$snedResult=$connObject->send(json_encode($msg));
1033
 
1034
					}#else end
1035
 
1036
				}#foreach end
1037
 
1038
			}#if end
1039
 
1040
		#反之沒有講話的對象
1041
		else{
1042
 
1043
			#提示server訊息被拋棄
1044
			echo "Message 「".$msg."」 will not be received by any one";
1045
 
1046
			#設置要給自己看的訊息
1047
			$from->send(json_encode("false"));
1048
 
1049
			}#else end
1050
 
1051
		}#function onMessage end
1052
 
1053
	#當clinet的連線斷掉前
1054
	public function onClose(ConnectionInterface $conn){
1055
 
1056
		// The connection is closed, remove it, as we can no longer send it messages
1057
        	$this->clients->detach($conn);
1058
 
1059
        	echo "Connection {$conn->resourceId} has disconnected\n";
1060
 
1061
		#移除連線的資訊
1062
		unset($this->connInfo[$conn->resourceId]);
1063
 
1064
		}#function onClose end
1065
 
1066
	#當出現錯誤時
1067
    	public function onError(ConnectionInterface $conn, \Exception $e){
1068
 
1069
		echo "An error has occurred: {$e->getMessage()}\n";
1070
 
1071
        	$conn->close();
1072
 
1073
		}#fucntion onError end
1074
 
1075
	}#class Chat end
1076
 
1077
#用 ChatV2 類別來實作 MessageComponentInterface 界面,
1078
#改善了用戶網路斷掉但Server端不會將連線斷掉的問題
1079
#改善了用戶端網路恢復後無法收到之前未收到的訊息的問題
1080
class ChatV2 implements MessageComponentInterface{
1081
 
1082
	#初始化儲存使用者資訊的陣列
1083
	private $connInfo=array();	
1084
 
1085
	#初始化儲存未傳送出去的留言訊息
1086
	#"fromId",訊息來源的id
1087
	#"toId",訊息目的的id
1088
	#"fromUserId",訊息來源的userId
1089
	#"toUserId",訊息目標的userId
1090
	#"msg",傳送的訊息
1091
	private $unSendMsg=array();
1092
 
1093
	#初始化儲存待確認是否送達到對方的訊息
1094
	#$unConfirmMsg[$id],$id為訊息接收方,亦即收到訊息後,要跟server說有收到訊息者.
1095
	#"fromId",訊息來源的id
1096
	#"toId",訊息目的的id
1097
	#"fromUserId",訊息來源的userId
1098
	#"toUserId",訊息目標的userId
1099
	#"msg",傳送的訊息
1100
	private $unConfirmMsg=array();
1101
 
1102
	#初始化一開始尚未能夠連線到資料庫
1103
	private static $dbTouchable=false;
1104
 
1105
	#初始化db的位置
1106
	public static $dbAddress="localhost";	
1107
 
1108
	#初始化連線db用的帳戶
1109
	public static $dbAccount="root";
1110
 
1111
	#初始化連線的db名稱
1112
	public static $dbName="test";
1113
 
1114
	#初始化連線db時用的密碼
1115
	public static $dbPassword="";
1116
 
1117
	#初始化連線db的哪個資料表
1118
	public static $memberTableName="member";
1119
 
1120
	#初始化登入時用來驗證帳號的資料表欄位名稱
1121
	public static $accountCol="account";
1122
 
1123
	#初始化登入時用來驗證密碼的資料表欄位名稱,設為""代表不用密碼來認證
1124
	public static $passwordCol="password";
1125
 
1126
	#建構子
1127
	public function __construct(){
1128
 
1129
		#如果尚未可以上資料庫
1130
		if(!(self::$dbTouchable)){
1131
 
1132
			#嘗試連線到目標資料庫.資料表
1133
			#涵式說明:
1134
			#一次取得資料庫、表的資料
1135
			#回傳的結果
1136
			#$result["status"],執行結果"true"為成功;"false"為執行失敗。
1137
			#$result["error"],錯誤訊息陣列。
1138
			#$result["function"],當前執行的漢書名稱.
1139
			#$result["dataColumnName"],抓取的資料欄位名稱陣列.
1140
				#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
1141
			#$result["dataContent"],爲資料的內容。
1142
			#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
1143
				#$dataSetNum 爲第$dataSetNum+1筆資料
1144
				#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
1145
			#$result["dataCount"],爲取得的資料筆數。
1146
			#$result["sql"],執行的sql字串.
1147
			#必填的參數:
1148
			$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
1149
			$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
1150
			$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
1151
			$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
1152
			$conf["db::fastGetDbData"]["columnYouWant"]=array("id",self::$accountCol);#你想要的欄位!,若設為「array("*")」則代表全部欄位.
1153
 
1154
			#如果 $passwordCol 不為空
1155
			if(self::$passwordCol!=""){
1156
 
1157
				#加上密碼欄位
1158
				$conf["db::fastGetDbData"]["columnYouWant"][]=self::$passwordCol;
1159
 
1160
				}#if end
1161
 
1162
			#可省略的參數:
1163
			$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
1164
			#$conf["db::fastGetDbData"]["WhereColumnName"]=array("account","password");#用於判斷語句的欄位項目陣列。
1165
			#$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac,$pw);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
1166
			#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
1167
			#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
1168
			#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
1169
			#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
1170
			#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
1171
			#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
1172
			$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
1173
			#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
1174
			#備註:
1175
			#建議在查詢資料前,能夠檢查是否每個欄位都存在.
1176
			$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
1177
			unset($conf["db::fastGetDbData"]);
1178
 
1179
			#如果取得資料失敗
1180
			if($fastGetDbData["status"]==="false"){
1181
 
1182
				#設置執行失敗
1183
				$result["status"]="false";
1184
 
1185
				#設置執行錯誤訊息
1186
				$result["error"]=$fastGetDbData;
1187
 
1188
				#印出debug訊息
1189
				var_dump($result);
1190
 
1191
				#結束程式
1192
				exit;
1193
 
1194
				}#if end
1195
 
1196
			#連線成功,將self::dbTouchable設為true
1197
			self::$dbTouchable=true;
1198
 
1199
			}#if end
1200
 
1201
		$this->clients = new \SplObjectStorage;
1202
 
1203
		}#funciton __construct end
1204
 
1205
	#當用戶與伺服器建立連線時
1206
	public function onOpen(ConnectionInterface $conn){
1207
 
1208
		// Store the new connection to send messages to later
1209
        	$this->clients->attach($conn);
1210
 
1211
		#提示server有clent連上web socket.
1212
        	echo "New connection! ({$conn->resourceId})\n";
1213
 
1214
 		#用client的id為index來儲存額外的資訊
1215
 		#元素 "conn" 代表已經建立連線的ConnectionInterface物件
1216
        	#元素 "talkTo" 代表要跟誰講話
1217
		#元素 "userId" 代表辨識使用者的id
1218
		#元素 "loigin=array("ac","pw")" 代表client輸入的帳號與密碼
1219
		#元素 "msgId" 為用來識別待確認訊息的索引
1220
		#元素 "gotMsgId" 為用來識別是否已經設置過 msgId 了
1221
 		#$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""),"type"=>"");
1222
        	$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""),"msgId"=>"","gotMsgId"=>"false");
1223
 
1224
		#包裝訊息
1225
		#"type"為"login"	
1226
		#"status"為"true"		
1227
		#"data"為實際的訊息內容
1228
		$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
1229
 
1230
		#提示輸入帳號	
1231
		$conn->send(json_encode($packedMsg));
1232
 
1233
		}#function onOpen end
1234
 
1235
	#當伺服器收到訊息時
1236
	public function onMessage(ConnectionInterface $from, $msg){
1237
 
1238
		#debug
1239
		#$array=array("msgId"=>$this->connInfo[$from->resourceId]["msgId"],"resourceId"=>$from->resourceId,"msg"=>$msg);
1240
		#var_dump($array);
1241
 
1242
		#如果該連線沒有使用者id
1243
		if($this->connInfo[$from->resourceId]["userId"]===""){
1244
 
1245
			#代表需要認證,認證的會員資料表 slef::memberTableName,需要以下三個欄位.
1246
			#id		自訂
1247
			#account  	自訂
1248
			#password varchar(33)
1249
 
1250
			/*
1251
 
1252
			#如果尚未輸入用戶端類型
1253
			if($this->connInfo[$from->resourceId]["type"]===""){
1254
 
1255
				#如果 $msg 長度大於 "type:"
1256
				if(strlen($msg) > strlen("type:")){
1257
 
1258
					#檢查有無前置字元 "account:"
1259
					#函式說明:
1260
					#將字串特定關鍵字與其前面的內容剔除
1261
					#回傳結果:
1262
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1263
					#$result["error"],錯誤訊息陣列.
1264
					#$result["warning"],警告訊息鎮列.
1265
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
1266
					#$result["function"],當前執行的函數名稱.
1267
					#$result["oriStr"],要處理的原始字串內容.
1268
					#$result["content"],處理好的的字串內容.
1269
					#必填的參數:
1270
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
1271
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="type:";#特定字串.
1272
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
1273
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
1274
 
1275
					#如果移除前置字元失敗
1276
					if($delStrBeforeKeyWord["status"]==="false"){
1277
 
1278
						#設置執行失敗
1279
						$result["status"]="false";
1280
 
1281
						#設置執行錯誤訊息
1282
						$result["error"]=$delStrBeforeKeyWord;
1283
 
1284
						#回傳結果
1285
						return $result;
1286
 
1287
						}#if end
1288
 
1289
					#如果有符合條件的前置字元
1290
					if($delStrBeforeKeyWord["founded"]==="true"){
1291
 
1292
						#儲存用戶端類型
1293
						$this->connInfo[$from->resourceId]["type"]=$delStrBeforeKeyWord["content"];
1294
 
1295
						}#if end
1296
 
1297
					#反之
1298
					else{
1299
 
1300
						#提示輸入用戶端類型
1301
						$from->send(json_encode("Please input your type! ex:type:user"));
1302
 
1303
						#結束程式
1304
						return true;
1305
 
1306
						}#else end
1307
 
1308
					}#if end
1309
 
1310
				#反之代表輸入錯誤格式的type
1311
				else{
1312
 
1313
					#提示輸入用戶端類型
1314
					$from->send(json_encode("Please input your type! ex:type:user"));
1315
 
1316
					#結束程式
1317
					return true;
1318
 
1319
					}#else end
1320
 
1321
				}#if end
1322
 
1323
			#如果用戶端是"user"
1324
			if($this->connInfo[$from->resourceId]["type"]==="user"){
1325
 
1326
				#...
1327
 
1328
				}#if end
1329
 
1330
			#反之如果用戶端是"device"
1331
			else if($this->connInfo[$from->resourceId]["type"]==="device"){
1332
 
1333
				#...
1334
 
1335
				}#if end
1336
 
1337
			*/
1338
 
1339
			#如果尚未輸入帳戶
1340
			if($this->connInfo[$from->resourceId]["login"]["ac"]===""){
1341
 
1342
				#如果 $msg 長度大於 "account:"
1343
				if(strlen($msg) > strlen("account:")){
1344
 
1345
					#檢查有無前置字元 "account:"
1346
					#函式說明:
1347
					#將字串特定關鍵字與其前面的內容剔除
1348
					#回傳結果:
1349
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1350
					#$result["error"],錯誤訊息陣列.
1351
					#$result["warning"],警告訊息鎮列.
1352
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
1353
					#$result["function"],當前執行的函數名稱.
1354
					#$result["oriStr"],要處理的原始字串內容.
1355
					#$result["content"],處理好的的字串內容.
1356
					#必填的參數:
1357
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
1358
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="account:";#特定字串.
1359
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
1360
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
1361
 
1362
					#如果移除前置字元失敗
1363
					if($delStrBeforeKeyWord["status"]==="false"){
1364
 
1365
						#設置執行失敗
1366
						$result["status"]="false";
1367
 
1368
						#設置執行錯誤訊息
1369
						$result["error"]=$delStrBeforeKeyWord;
1370
 
1371
						#回傳結果
1372
						return $result;
1373
 
1374
						}#if end
1375
 
1376
					#如果有符合條件的前置字元
1377
					if($delStrBeforeKeyWord["founded"]==="true"){
1378
 
1379
						#儲存帳戶
1380
						$this->connInfo[$from->resourceId]["login"]["ac"]=$delStrBeforeKeyWord["content"];
1381
 
1382
						}#if end
1383
 
1384
					#反之代表格式錯誤	
1385
					else{
1386
 
1387
						#包裝訊息
1388
						#"type"為"login"	
1389
						#"status"為"true"		
1390
						#"data"為實際的訊息內容
1391
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
1392
 
1393
						#提示輸入帳號	
1394
						$from->send(json_encode($packedMsg));
1395
 
1396
						#結束程式
1397
						return true;
1398
 
1399
						}#else end
1400
 
1401
					}#if end
1402
 
1403
				#反之代表輸入錯誤格式的account
1404
				else{
1405
 
1406
					#包裝訊息
1407
					#"type"為"login"	
1408
					#"status"為"true"		
1409
					#"data"為實際的訊息內容
1410
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
1411
 
1412
					#提示輸入帳號	
1413
					$from->send(json_encode($packedMsg));
1414
 
1415
					#結束程式
1416
					return true;
1417
 
1418
					}#else end
1419
 
1420
				}#if end
1421
 
1422
			#如果有設置密碼欄位
1423
			if(self::$passwordCol!==""){
1424
 
1425
				#如果尚未輸入密碼
1426
				if($this->connInfo[$from->resourceId]["login"]["pw"]===""){
1427
 
1428
					#$msg 長度大於 "password:"
1429
					if(strlen($msg) > strlen("password:")){
1430
 
1431
						#檢查有無前置字元 "password:"
1432
						#函式說明:
1433
						#將字串特定關鍵字與其前面的內容剔除
1434
						#回傳結果:
1435
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
1436
						#$result["error"],錯誤訊息陣列.
1437
						#$result["warning"],警告訊息鎮列.
1438
						#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
1439
						#$result["function"],當前執行的函數名稱.
1440
						#$result["oriStr"],要處理的原始字串內容.
1441
						#$result["content"],處理好的的字串內容.
1442
						#必填的參數:
1443
						$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
1444
						$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="password:";#特定字串.
1445
						$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
1446
						unset($conf["stringProcess::delStrBeforeKeyWord"]);
1447
 
1448
						#如果移除前置字元失敗
1449
						if($delStrBeforeKeyWord["status"]==="false"){
1450
 
1451
							#設置執行失敗
1452
							$result["status"]="false";
1453
 
1454
							#設置執行錯誤訊息
1455
							$result["error"]=$delStrBeforeKeyWord;
1456
 
1457
							#回傳結果
1458
							return $result;
1459
 
1460
							}#if end
1461
 
1462
						#如果有符合條件的前置字元
1463
						if($delStrBeforeKeyWord["founded"]==="true"){
1464
 
1465
							#儲存密碼
1466
							$this->connInfo[$from->resourceId]["login"]["pw"]=$delStrBeforeKeyWord["content"];
1467
 
1468
							}#if end
1469
 
1470
						#反之代表格式錯誤
1471
						else{
1472
 
1473
							#包裝訊息
1474
							#"type"為"login"	
1475
							#"status"為"true"		
1476
							#"data"為實際的訊息內容
1477
							$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
1478
 
1479
							#提示輸入密碼		
1480
							$from->send(json_encode($packedMsg));
1481
 
1482
							#結束程式
1483
							return true;
1484
 
1485
							}#else end
1486
 
1487
						}#if end
1488
 
1489
					#反之代表格式錯誤
1490
					else{
1491
 
1492
						#包裝訊息
1493
						#"type"為"login"	
1494
						#"status"為"true"		
1495
						#"data"為實際的訊息內容
1496
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
1497
 
1498
						#提示輸入密碼		
1499
						$from->send(json_encode($packedMsg));
1500
 
1501
						#結束程式
1502
						return true;
1503
 
1504
						}#else end
1505
 
1506
					}#if end
1507
 
1508
				}#if end
1509
 
1510
			#如果已經輸入帳號了
1511
			if($this->connInfo[$from->resourceId]["login"]["ac"]!=""){
1512
 
1513
				#設置可以進行驗證
1514
				$startAuth=true;
1515
 
1516
				#另存帳號
1517
				$ac=$this->connInfo[$from->resourceId]["login"]["ac"];
1518
 
1519
				#初始化密碼
1520
				$pw="";
1521
 
1522
				#如果有設置密碼欄位
1523
				if(self::$passwordCol!==""){
1524
 
1525
					#如果client已經輸入密碼了
1526
					if($this->connInfo[$from->resourceId]["login"]["pw"]!=""){
1527
 
1528
						#另存密碼
1529
						$pw=md5($this->connInfo[$from->resourceId]["login"]["pw"]);
1530
 
1531
						}#if end
1532
 
1533
					#反之
1534
					else{
1535
 
1536
						#設置尚不能進行認證
1537
						$startAuth=false;
1538
 
1539
						}#else end
1540
 
1541
					}#if end
1542
 
1543
				#如果尚不能進行驗證
1544
				if(!$startAuth){
1545
 
1546
					#結束程式
1547
					return true;
1548
 
1549
					}#if end
1550
 
1551
				#檢查有無符合的帳戶密碼
1552
				#涵式說明:
1553
				#一次取得資料庫、表的資料
1554
				#回傳的結果
1555
				#$result["status"],執行結果"true"為成功;"false"為執行失敗。
1556
				#$result["error"],錯誤訊息陣列。
1557
				#$result["function"],當前執行的漢書名稱.
1558
				#$result["dataColumnName"],抓取的資料欄位名稱陣列.
1559
					#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
1560
				#$result["dataContent"],爲資料的內容。
1561
				#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
1562
					#$dataSetNum 爲第$dataSetNum+1筆資料
1563
					#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
1564
				#$result["dataCount"],爲取得的資料筆數。
1565
				#$result["sql"],執行的sql字串.
1566
				#必填的參數:
1567
				$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
1568
				$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
1569
				$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
1570
				$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
1571
				$conf["db::fastGetDbData"]["columnYouWant"]=array("id");#你想要的欄位!,若設為「array("*")」則代表全部欄位.
1572
				#可省略的參數:
1573
				$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
1574
				$conf["db::fastGetDbData"]["WhereColumnName"]=array(self::$accountCol);#用於判斷語句的欄位項目陣列。
1575
				$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
1576
 
1577
				#如果有輸入密碼
1578
				if($pw!==""){
1579
 
1580
					#新增要判斷 self::$password 欄位,是否有於 $pw
1581
					$conf["db::fastGetDbData"]["WhereColumnName"][]=self::$passwordCol;
1582
					$conf["db::fastGetDbData"]["WhereColumnValue"][]=$pw;
1583
 
1584
					}#if end
1585
 
1586
				#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
1587
				#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
1588
				#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
1589
				#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
1590
				#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
1591
				#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
1592
				$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
1593
				#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
1594
				#備註:
1595
				#建議在查詢資料前,能夠檢查是否每個欄位都存在.
1596
				$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
1597
				unset($conf["db::fastGetDbData"]);
1598
 
1599
				#如果取得資料失敗
1600
				if($fastGetDbData["status"]==="false"){
1601
 
1602
					#設置執行失敗
1603
					$result["status"]="false";
1604
 
1605
					#設置執行錯誤訊息
1606
					$result["error"]=$fastGetDbData;					
1607
 
1608
					#提示server有資料庫錯誤
1609
					echo "dbError!";
1610
 
1611
					#結束程式
1612
					exit;
1613
 
1614
					}#if end
1615
 
1616
				#如果沒有一筆資料
1617
				if($fastGetDbData["dataCount"]!==1){
1618
 
1619
					#代表登入失敗
1620
 
1621
					#清空登入用的帳戶
1622
					$this->connInfo[$from->resourceId]["login"]["ac"]="";
1623
 
1624
					#清空登入用的密碼
1625
					$this->connInfo[$from->resourceId]["login"]["pw"]="";
1626
 
1627
					#包裝訊息
1628
					#"type"為"login"	
1629
					#"status"為"false"		
1630
					#"data"為實際的訊息內容
1631
					$packedMsg=array("type"=>"login","status"=>"false","data"=>"Login failed, please input account. ex:account:ws1");
1632
 
1633
					#提示登入失敗					
1634
					$from->send(json_encode($packedMsg));
1635
 
1636
					#執行到這即可
1637
					return true;
1638
 
1639
					}#if end
1640
 
1641
				#反之代表帳戶資訊正確
1642
				else{
1643
 
1644
					#設置 $myUserId
1645
					$myUserId=$this->connInfo[$from->resourceId]["userId"]=$fastGetDbData["dataContent"]["id"][0];
1646
 
1647
					#設置 $myId
1648
					$myId=$from->resourceId;
1649
 
1650
					#初始化msgId的部份內容
1651
					$msgId=$myUserId."-";
1652
 
1653
					#初始化儲存msgId的陣列
1654
					$msgIdArray=array();
1655
 
1656
					#取得所有client的msgId
1657
					foreach($this->connInfo as $clientInfoArray){
1658
 
1659
						#如果msgId不為""
1660
						if($clientInfoArray["msgId"]!==""){
1661
 
1662
							#取得msgId
1663
							$msgIdArray[]=$clientInfoArray["msgId"];
1664
 
1665
							}#if end
1666
 
1667
						}#foreach end
1668
 
1669
					#如果尚未產生完整的msgId或msgId有重複
1670
					while($msgId===$myUserId."-" || in_array($msgId,$msgIdArray)){
1671
 
1672
						#涵式說明:
1673
						#建立以圖片(PNG格式)呈現的驗證碼.
1674
						#回傳的解果:
1675
						#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
1676
						#$result["error"],錯誤訊息.
1677
						#$result["function"],檔前執行的函數名稱.
1678
						#$result["randNumberWord"],傳驗證碼的內容.
1679
						#$result["imgAddress"],圖片的位置與名稱.
1680
						#必填的參數:
1681
						#$conf["imgAddressAndName"],字串,爲驗證碼圖片儲存的位置與名稱,副檔名程式會自動產生
1682
						$conf["authenticate::validationCode"]["imgAddressAndName"]="no used!";
1683
						#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
1684
						$conf["authenticate::validationCode"]["fileArgu"]="no used!";
1685
						#可省略的參數:
1686
						#$conf["num"],字串,爲驗證碼的位數,請輸入阿拉伯數字,預設為"8"位數.
1687
						#$conf["num"]="8";
1688
						#$conf["disableImg"],字串,是否要取消驗證碼圖片的輸出,"true"為要取消,預設為"false"為不取消
1689
						$conf["authenticate::validationCode"]["disableImg"]="true";
1690
						#$conf["imgToData"],字串,預設為"true"代表將圖片轉存成base64圖片,並將原始圖片移除;反之為"false"
1691
						#$conf["imgToData"]="true";
1692
						$validationCode=authenticate::validationCode($conf["authenticate::validationCode"]);
1693
						unset($conf["authenticate::validationCode"]);
1694
 
1695
						#如果產生亂數失敗
1696
						if($validationCode["status"]==="false"){
1697
 
1698
							#設置錯誤狀態
1699
							$result["status"]="false";
1700
 
1701
							#設置錯誤提示
1702
							$result["error"]=$validationCode;
1703
 
1704
							#印出錯誤訊息
1705
							var_dump($result);
1706
 
1707
							#回傳結果			
1708
							return $result;				
1709
 
1710
							}#if end
1711
 
1712
						#儲存產生好的msgId	
1713
						$msgId=$myUserId."-".$validationCode["randNumberWord"];
1714
 
1715
						}#while end
1716
 
1717
					#設置獨立於id與userId且用於驗證訊息是否收到的msgId
1718
					$this->connInfo[$from->resourceId]["msgId"]=$msgId;
1719
 
1720
					#包裝訊息
1721
					#"type"為"login"	
1722
					#"status"為"true"		
1723
					#"data"為實際的訊息內容
1724
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Login successfully!");
1725
 
1726
					#提示登入成功
1727
					$from->send(json_encode($packedMsg));
1728
 
1729
					#檢查是否有訊息是要給自己的
1730
					foreach($this->unSendMsg as $index => $historyMsg){
1731
 
1732
						#如果有要給自己的訊息
1733
						if($myUserId===$historyMsg["toUserId"]){
1734
 
1735
							#包裝訊息
1736
							#"type"為"unSendMsg?"	
1737
							#"status"為"true"		
1738
							#"data"為實際的訊息內容
1739
							$packedMsg=array("type"=>"unSendMsg?","status"=>"true","data"=>$historyMsg["msg"]);
1740
 
1741
							#接收別人給的留言
1742
							$from->send(json_encode($packedMsg));
1743
 
1744
							#有幾個人在線上就執行幾次
1745
							foreach($this->connInfo as $toId => $cInfo){
1746
 
1747
								#如果是自己
1748
								if($myId===$toId ){
1749
 
1750
									#跳過
1751
									continue;
1752
 
1753
									}#if end
1754
 
1755
								#如果留言的對象有在線上
1756
								if($historyMsg["fromUserId"]===$cInfo["userId"]){
1757
 
1758
									#檢查對方是否已經在自己的通話清單裡面了
1759
 
1760
									#初始化要將對方加到自己的對話清單裡面
1761
									$add=false;
1762
 
1763
									#根據自己的每個通話對象
1764
									foreach($this->connInfo[$myId]["talkTo"] as $myToIndex=>$myToCinfo ){
1765
 
1766
										#如果對對方已經存在於自己的對話清單裡面了
1767
										if($myToCinfo["userId"]===$historyMsg["fromUserId"] && $myId===$historyMsg["fromId"]){
1768
 
1769
											#設置不要將對方加到自己的對話清單裡面
1770
											$add=false;
1771
 
1772
											#跳出foreach
1773
											break;
1774
 
1775
											}#if end
1776
 
1777
										}#foreach end
1778
 
1779
									#如果要將對方加到自己的對話清單裡面
1780
									if($add){
1781
 
1782
										#將對方加到自己的talkTo清單裡面
1783
										$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$historyMsg["fromUserId"],"msgId"=>$this->connInfo[$toId]["msgId"]);
1784
 
1785
										}#if end
1786
 
1787
									#檢查自己有沒有在對方talkTo清單裡面
1788
 
1789
									#假設對方需要加自己到對話清單裡面
1790
									$add=true;
1791
 
1792
									#檢查通話對象能否跟自己對話
1793
 
1794
									#依據對方每個通話的對象
1795
									foreach($this->connInfo[$toId]["talkTo"] as $talkToIndex=>$talkToCinfo){
1796
 
1797
										#如果自己的userId已經在對方的對話清單裡面了
1798
										if($myUserId===$talkToCinfo["userId"]){
1799
 
1800
											#如果對方對話userId對應的id不在線上
1801
											if(!isset($this->connInfo[$toId])){
1802
 
1803
												#debug
1804
												#var_dump("對方對話userId(".$talkToCinfo["userId"].")應的id(".$toId.")不在線上");	
1805
 
1806
												#檢查對方對話清單是否已經含有自己的id與userId了
1807
 
1808
												#假設對方對話清單沒有自己的id與userId
1809
												$update=true;
1810
 
1811
												#依據對方每個通話的對象
1812
												foreach($this->connInfo[$toId]["talkTo"] as $ceToIndex=>$ceToCinfo){
1813
 
1814
													#如果對方對話清單已經含有自己的id與userId了												
1815
													if($ceToCinfo["id"]===$myId && $ceToCinfo["userId"]===$myUserId){
1816
 
1817
														#debug
1818
														#var_dump("對方對話清單已經含有自己的id(".$myId.")與userId了(".$myUserId.")");
1819
 
1820
														#設置不需要更新
1821
														$update=false;
1822
 
1823
														#debug
1824
														#var_dump($toId."要加".$myId."到通話清單裡面");
1825
 
1826
														#設置對方不需要加自己到對話清單裡面
1827
														$add=false;
1828
 
1829
														}#if end
1830
 
1831
													}#foreach end
1832
 
1833
												#如果對方對話清單沒有自己的id與userId與msgId
1834
												if($update){
1835
 
1836
													#debug
1837
													#var_dump($toId."要更新對話清單中索引為".$talkToIndex."的id(".$this->connInfo[$toId]["talkTo"][$talkToIndex]["id"].")為".$myId);
1838
 
1839
													#將自己在對方對話清單裡面的id改成現在的id
1840
													$this->connInfo[$toId]["talkTo"][$talkToIndex]["id"]=$myId;
1841
 
1842
													}#if end
1843
 
1844
												#反之對方對話清單已經有自己的id與userId
1845
												else{
1846
 
1847
													#移除對方該已經斷線的對話id
1848
													unset($this->connInfo[$toId]["talkTo"][$talkToIndex]);
1849
 
1850
													}#else end
1851
 
1852
												}#if end
1853
 
1854
											}#if end
1855
 
1856
										}#foreach end
1857
 
1858
									#如果對方需要加自己到對話清單裡面
1859
									if($add){
1860
 
1861
										#檢查對方每個通話對象
1862
										foreach($this->connInfo[$toId]["talkTo"] as $reCktIndex=>$reCktInfo){
1863
 
1864
											#如果已經有將自己加到對方的對話清單裡面
1865
											if($reCktInfo["id"]===$myId && $reCktInfo["userId"]===$myUserId){
1866
 
1867
												#設置不用將自己加到對方的對話清單裡面
1868
												$add=false;
1869
 
1870
												}#if end
1871
 
1872
											}#foreach end
1873
 
1874
										#如果對方需要加自己到對話清單裡面
1875
										if($add){
1876
 
1877
											#debug
1878
											#var_dump($toId."要加".$myId."(msgId為".$this->connInfo[$myId]["msgId"].")到通話清單裡面");
1879
 
1880
											#讓通話對象也可以傳送訊息回來
1881
											$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId,"msgId"=>$this->connInfo[$myId]["msgId"]);
1882
 
1883
											}#if end
1884
 
1885
										}#if end
1886
 
1887
									}#if end
1888
 
1889
								}#foreach end
1890
 
1891
							#移除留言紀錄
1892
							unset($this->unSendMsg[$index]);
1893
 
1894
							}#if end
1895
 
1896
						}#foreach end
1897
 
1898
					#檢查線上是否有人想跟我對話
1899
 
1900
					#有幾個人在線上就執行幾次
1901
					foreach($this->connInfo as $toId => $cInfo){
1902
 
1903
						#如果是自己
1904
						if($myId===$toId){
1905
 
1906
							#跳過
1907
							continue;
1908
 
1909
							}#if end
1910
 
1911
						#該cliet目前再跟幾個人通話,就執行幾次
1912
						foreach($cInfo["talkTo"] as $tIndex=>$tInfo){
1913
 
1914
							#如果自己的userId在對方的對話清單裡面
1915
							if($myUserId===$tInfo["userId"]){
1916
 
1917
								#假設自己需要被對方加到對話清單裡面
1918
								$add=true;
1919
 
1920
								#檢查自己是否已經在對方的對話清單裡面
1921
 
1922
								#對方有幾個通話對象就執行幾次
1923
								foreach($this->connInfo[$toId]["talkTo"] as $toIndex=>$toCinfo){
1924
 
1925
									#如果自己已經在對方的對話清單裡面
1926
									if($myUserId===$toCinfo["userId"] && $myId===$toCinfo["id"]){
1927
 
1928
										#設置自己不需要被對方加到對話清單裡面
1929
										$add=false;
1930
 
1931
										#跳出迴圈
1932
										break;
1933
 
1934
										}#if end
1935
 
1936
									}#foreach end
1937
 
1938
								#另存針對自己userId的連線id
1939
								$oneIdOfMyUserid=$this->connInfo[$toId]["talkTo"][$tIndex]["id"];
1940
 
1941
								#如果對方對話清單裡面的用戶id不在線
1942
								if(!isset($this->connInfo[$oneIdOfMyUserid])){
1943
 
1944
									#假設要將自己在對方對話清單裡面的id改成現在的id
1945
									$update=true;
1946
 
1947
									#自己不需要被對方加到對話清單裡面
1948
									$add=false;
1949
 
1950
									#檢查自己的id是否已經在對方的對話id裡面
1951
									foreach($this->connInfo[$toId]["talkTo"] as $ceIndex=>$ceInfo){
1952
 
1953
										#如果自己的id已經在對方的對話清單裡面
1954
										if($myId===$ceInfo["id"]){
1955
 
1956
											#設置不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
1957
											$update=false;
1958
 
1959
											#跳出迴圈
1960
											break;
1961
 
1962
											}#if end
1963
 
1964
										}#foreach end
1965
 
1966
									#如果要將自己在對方對話清單裡面的id改成現在的id
1967
									if($update){
1968
 
1969
										#debug
1970
										#var_dump($toId."要更新對話清單中索引為".$tIndex."的id(".$this->connInfo[$toId]["talkTo"][$tIndex]["id"].")為".$myId);
1971
 
1972
										#將自己在對方對話清單裡面的id改成現在的id
1973
										$this->connInfo[$toId]["talkTo"][$tIndex]["id"]=$myId;
1974
 
1975
										}#if end
1976
 
1977
									#反之不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
1978
									else{
1979
 
1980
										#移除該對話id
1981
										unset($this->connInfo[$toId]["talkTo"][$tIndex]);
1982
 
1983
										}#else end
1984
 
1985
									}#if end	
1986
 
1987
								#如果要將自己加到對方的的通話清單裡面
1988
								if($add){
1989
 
1990
									#debug
1991
									#var_dump($toId."要加".$myId."(msgId為".$this->connInfo[$myId]["msgId"].")到通話清單裡面");
1992
 
1993
									#將自己加到對方的的通話清單裡面
1994
									$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId,"msgId"=>$this->connInfo[$myId]["msgId"]);			
1995
 
1996
									}#if end								
1997
 
1998
								#檢查對方是否已經在自己的對話清單裡面
1999
 
2000
								#設置要新增對方到自己的對話清單裡面.
2001
								$add=true;
2002
 
2003
								#自己有幾個對話對象就執行幾次
2004
								foreach($this->connInfo[$myId]["talkTo"] as $mtIndex=>$mtInfo){
2005
 
2006
									#對方的userId與id若在自己的對話清單裡面
2007
									if($mtInfo["userId"]===$cInfo["userId"] && $mtInfo["id"]===$toId){
2008
 
2009
										#設置不需要新增對方到自己的對話清單裡面
2010
										$add=false;
2011
 
2012
										#跳出 foreach
2013
										break;
2014
 
2015
										}#if end
2016
 
2017
									}#foreache end
2018
 
2019
								#如果要新增對方到自己的對話清單裡面.
2020
								if($add){
2021
 
2022
									#自己有幾個對話對象就執行幾次
2023
									foreach($this->connInfo[$myId]["talkTo"] as $mtIndex=>$mtInfo){
2024
 
2025
										#如果對方已經在自己的通話清單
2026
										if($mtInfo["userId"]===$cInfo["userId"] && $mtInfo["id"]===$toId){
2027
 
2028
											#設置不要將對方到自己的對話清單裡面.
2029
											$add=false;
2030
 
2031
											#跳出 foreach end
2032
											break;
2033
 
2034
											}#if end
2035
 
2036
										}#foreach end
2037
 
2038
									#如果要新增對方到自己的對話清單裡面.
2039
									if($add){
2040
 
2041
										#將對方加到自己的對話清單裡面
2042
										$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$cInfo["userId"],"msgId"=>$this->connInfo[$toId]["msgId"]);
2043
 
2044
										}#if end
2045
 
2046
									}#if end
2047
 
2048
								}#if end
2049
 
2050
							}#foreach end
2051
 
2052
						}#foreach end
2053
 
2054
					#結束認證成功後的流程
2055
					return true;
2056
 
2057
					}#else end
2058
 
2059
				}#else end
2060
 
2061
			#結束認證流程
2062
			return true;	
2063
 
2064
			}#if end
2065
 
2066
		#如果收到 "id?"
2067
		else if($msg==="id?"){
2068
 
2069
			#包裝訊息
2070
			#"type"為"id?"	
2071
			#"status"為"true"		
2072
			#"data"為實際的訊息內容
2073
			$packedMsg=array("type"=>"id?","status"=>"true","data"=>$from->resourceId);
2074
 
2075
			#傳自己的id給client
2076
			$from->send(json_encode($packedMsg));
2077
 
2078
			#回傳成功
2079
			return true;
2080
 
2081
			}#if end
2082
 
2083
		#如果收到 "ids?"
2084
		else if($msg==="ids?"){
2085
 
2086
			#初始化儲存其他人的id
2087
			$idsArray=array();
2088
 
2089
			#針對所的client
2090
			foreach ($this->clients as $client){
2091
 
2092
				#排除自己
2093
				if($from !== $client){
2094
 
2095
					#取得其他人的id
2096
					$idsArray[]=$client->resourceId;
2097
 
2098
					}#if end
2099
 
2100
				}#foreach end			
2101
 
2102
			#包裝訊息
2103
			#"type"為"ids?"	
2104
			#"status"為"true"		
2105
			#"data"為實際的訊息內容
2106
			$packedMsg=array("type"=>"ids?","status"=>"true","data"=>$idsArray);
2107
 
2108
			#傳他人的id給client
2109
			$from->send(json_encode($packedMsg));
2110
 
2111
			#回傳成功
2112
			return true;
2113
 
2114
			}#if end
2115
 
2116
		#如果收到 "talkTo?"
2117
		else if($msg==="talkTo?"){
2118
 
2119
			#包裝訊息
2120
			#"type"為"talkTo?"	
2121
			#"status"為"true"		
2122
			#"data"為實際的訊息內容
2123
			$packedMsg=array("type"=>"talkTo?","status"=>"true","data"=>$this->connInfo[$from->resourceId]["talkTo"]);
2124
 
2125
			#正在對話的對象id給client
2126
			$from->send(json_encode($packedMsg));
2127
 
2128
			#回傳成功
2129
			return true;
2130
 
2131
			}#if end
2132
 
2133
		#反之如果是 "msgId?"
2134
		else if($msg==="msgId?"){
2135
 
2136
			#包裝訊息
2137
			#"type"為"talkTo?"	
2138
			#"status"為"true"		
2139
			#"data"為實際的訊息內容
2140
			$packedMsg=array("type"=>"msgId?","status"=>"true","data"=>$this->connInfo[$from->resourceId]["msgId"]);
2141
 
2142
			#取得自己的msgId
2143
			$from->send(json_encode($packedMsg));
2144
 
2145
			#回傳成功
2146
			return true;
2147
 
2148
			}#if end
2149
 
2150
		#如果收到的$msg長度大於 "talkTo:"
2151
		if(strlen($msg)>strlen("talkTo:")){
2152
 
2153
			#如果收到開頭為 "talkTo:"    
2154
			#涵式說明:
2155
			#取得符合特定字首與字尾的字串
2156
			#回傳的結果:
2157
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
2158
			#$result["function"],當前執行的函數名稱.
2159
			#$result["error"],錯誤訊息陣列.
2160
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
2161
			#$result["returnString"],爲符合字首條件的字串內容。
2162
			#必填參數:
2163
			#$conf["checkString"],字串,要檢查的字串.
2164
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
2165
			#可省略參數:
2166
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
2167
			$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
2168
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
2169
			#$conf["tailWord"]="";
2170
			#參考資料:
2171
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
2172
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
2173
			unset($conf["search::getMeetConditionsString"]);
2174
 
2175
			#如果選找前置字串 "talkTo:" 失敗
2176
			if($getMeetConditionsString["status"]==="false"){
2177
 
2178
				#設置執行失敗
2179
				$result["status"]="false";
2180
 
2181
				#設置執行錯誤訊息
2182
				$result["error"]=$getMeetConditionsString;
2183
 
2184
				#回傳結果
2185
				return $result;
2186
 
2187
				}#if end
2188
 
2189
			#如果存在 "talkTo:" 前置字串
2190
			if($getMeetConditionsString["founded"]==="true"){
2191
 
2192
				#用 "talkTo:" 分割 $buf
2193
				#涵式說明:
2194
				#將固定格式的字串分開,並回傳分開的結果。
2195
				#回傳結果:
2196
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
2197
				#$result["error"],錯誤訊息陣列
2198
				#$result["function"],當前執行的函數名稱.
2199
				#$result["oriStr"],要分割的原始字串內容
2200
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
2201
				#$result["dataCounts"],爲總共分成幾段
2202
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
2203
				#必填的參數:
2204
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
2205
				$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
2206
				#可省略參數:
2207
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
2208
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
2209
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
2210
				unset($conf["stringProcess::spiltString"]);
2211
 
2212
				#如果分割字串失敗
2213
				if($spiltString["status"]==="false"){
2214
 
2215
					#設置執行失敗
2216
					$result["status"]="false";
2217
 
2218
					#設置執行錯誤訊息
2219
					$result["error"]=$spiltString;
2220
 
2221
					#回傳結果
2222
					return $result;
2223
 
2224
					}#if end
2225
 
2226
				#如果剛好分割出一筆資料
2227
				if($spiltString["dataCounts"]===1){
2228
 
2229
					#取得自己的id
2230
					$myId=$from->resourceId;
2231
 
2232
					#取得講話對象的id
2233
					$toId=$spiltString["dataArray"][0];
2234
 
2235
					#設置對象不存在的識別
2236
					$targetExist=false;
2237
 
2238
					#設置通話對象的key
2239
					$targetKey="";					
2240
 
2241
					#如果要對話的對象存在
2242
					if(isset($this->connInfo[$toId])){
2243
 
2244
						#取得對象的userId
2245
						$toUserId=$this->connInfo[$toId]["userId"];
2246
 
2247
						#取得同userId的對象id們
2248
 
2249
						#初始化同userId的對象id
2250
						$targetC=array();
2251
 
2252
						#針對每個連線
2253
						foreach($this->connInfo as $eachIndex=>$eachInfo){
2254
 
2255
							#如果是自己
2256
							if($eachIndex===$myId){
2257
 
2258
								#跳到下一輪
2259
								continue;
2260
 
2261
								}#if end
2262
 
2263
							#如果是同userId的對象
2264
							if($eachInfo["userId"]===$toUserId){
2265
 
2266
								#取出連線
2267
								$targetC[$eachIndex]=$this->connInfo[$eachIndex];
2268
 
2269
								}#if end
2270
 
2271
							}#foreach end
2272
 
2273
						#針對每個同userId的連線
2274
						foreach($targetC as $tcIndex=>$tcInfo){
2275
 
2276
							#檢查自己的對話對象是否已經在清單裡面了
2277
 
2278
							#假設對象可以加到自己對話清單裡面
2279
							$add=true;
2280
 
2281
							#針對每個要講話的對象
2282
							foreach($this->connInfo[$myId]["talkTo"] as $index=>$cInfo){
2283
 
2284
								#如果對話對象已經在清單裡面了
2285
								if($this->connInfo[$tcIndex]["userId"]===$cInfo["userId"] && $tcIndex===$cInfo["id"] && $tcInfo["msgId"]===$cInfo["msgId"]){
2286
 
2287
									#設置不要再加到清單裡面
2288
									$add=false;
2289
 
2290
									#跳出foreach
2291
									break;
2292
 
2293
									}#if end								
2294
 
2295
								}#foreach end
2296
 
2297
							#如果要加入到對話清單裡面
2298
							if($add){
2299
 
2300
								#增加自己的對話對象
2301
								$this->connInfo[$myId]["talkTo"][]=array("id"=>$tcIndex,"userId"=>$this->connInfo[$tcIndex]["userId"],"msgId"=>$this->connInfo[$tcIndex]["msgId"]);
2302
 
2303
								#假設對方可以加自己到對話清單裡面
2304
								$add=true;
2305
 
2306
								#檢查通話對象能否跟自己對話
2307
								foreach($this->connInfo[$tcIndex]["talkTo"] as $index=>$cInfo){
2308
 
2309
									#如果對話對象已經在清單裡面了
2310
									if($this->connInfo[$myId]["userId"]===$cInfo["userId"]){
2311
 
2312
										#設置不要再加到清單裡面
2313
										$add=false;
2314
 
2315
										#跳出 foreach
2316
										break;
2317
 
2318
										}#if end
2319
 
2320
									}#foreach end
2321
 
2322
								#如果對方可以加自己到對話清單裡面
2323
								if($add){
2324
 
2325
									#讓通話對象也可以傳送訊息回來
2326
									$this->connInfo[$tcIndex]["talkTo"][]=array("id"=>$myId,"userId"=>$this->connInfo[$myId]["userId"],"msgId"=>$this->connInfo[$myId]["msgId"]);
2327
 
2328
									}#if end
2329
 
2330
								#設置成功訊息
2331
								$msg="client id ".$toId." added to talkTo list";
2332
 
2333
								#包裝訊息
2334
								#"type"為"status"	
2335
								#"status"為"true"		
2336
								#"data"為實際的訊息內容
2337
								$packedMsg=array("type"=>"status","status"=>"true","data"=>$msg);
2338
 
2339
								#設置要給自己看的訊息
2340
								$from->send(json_encode($packedMsg));							
2341
 
2342
								}#if end
2343
 
2344
							#反之
2345
							else{
2346
 
2347
								#設置錯誤訊息
2348
								$msg="client id ".$toId." already in talkTo list";
2349
 
2350
								#包裝訊息
2351
								#"type"為"status"	
2352
								#"status"為"false"		
2353
								#"data"為實際的訊息內容
2354
								$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
2355
 
2356
								#設置要給自己看的訊息
2357
								$from->send(json_encode($packedMsg));
2358
 
2359
								}#else end
2360
 
2361
							}#foreach end
2362
 
2363
						#回傳成功
2364
						return true;
2365
 
2366
						}#if end
2367
 
2368
					#反之不存在
2369
					else{
2370
 
2371
						#設置錯誤訊息
2372
						$msg="client id ".$toId." doesn't exist";
2373
 
2374
						#包裝訊息
2375
						#"type"為"status"	
2376
						#"status"為"false"		
2377
						#"data"為實際的訊息內容
2378
						$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
2379
 
2380
						#設置要給自己看的訊息
2381
						$from->send(json_encode($packedMsg));
2382
 
2383
						#回傳成功
2384
						return true;
2385
 
2386
						}#else end		
2387
 
2388
					}#if end
2389
 
2390
				}#if end
2391
 
2392
			}#if end
2393
 
2394
		#預設沒有收到確認收到訊息的回應訊息
2395
		$mIndex="false";
2396
 
2397
		#如果收到的$msg長度大於 "msgId:"
2398
		if(strlen($msg)>strlen("msgId:")){
2399
 
2400
			#解析 $msg
2401
 
2402
			#如果收到開頭為 "msgId:"    
2403
			#涵式說明:
2404
			#取得符合特定字首與字尾的字串
2405
			#回傳的結果:
2406
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
2407
			#$result["function"],當前執行的函數名稱.
2408
			#$result["error"],錯誤訊息陣列.
2409
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
2410
			#$result["returnString"],爲符合字首條件的字串內容。
2411
			#必填參數:
2412
			#$conf["checkString"],字串,要檢查的字串.
2413
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
2414
			#可省略參數:
2415
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
2416
			$conf["search::getMeetConditionsString"]["frontWord"]="msgId:";
2417
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
2418
			#$conf["tailWord"]="";
2419
			#參考資料:
2420
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
2421
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
2422
			unset($conf["search::getMeetConditionsString"]);
2423
 
2424
			#如果選找前置字串 "msgId:" 失敗
2425
			if($getMeetConditionsString["status"]==="false"){
2426
 
2427
				#設置執行失敗
2428
				$result["status"]="false";
2429
 
2430
				#設置執行錯誤訊息
2431
				$result["error"]=$getMeetConditionsString;
2432
 
2433
				#回傳結果
2434
				return $result;
2435
 
2436
				}#if end
2437
 
2438
			#如果存在	 "msgId:" 前置字串
2439
			if($getMeetConditionsString["founded"]==="true"){
2440
 
2441
				#用 "msgId:" 分割 $msg
2442
				#涵式說明:
2443
				#將固定格式的字串分開,並回傳分開的結果。
2444
				#回傳結果:
2445
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
2446
				#$result["error"],錯誤訊息陣列
2447
				#$result["function"],當前執行的函數名稱.
2448
				#$result["oriStr"],要分割的原始字串內容
2449
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
2450
				#$result["dataCounts"],爲總共分成幾段
2451
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
2452
				#必填的參數:
2453
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
2454
				$conf["stringProcess::spiltString"]["spiltSymbol"]="msgId:";#爲以哪個符號作爲分割
2455
				#可省略參數:
2456
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
2457
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
2458
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
2459
				unset($conf["stringProcess::spiltString"]);
2460
 
2461
				#如果分割字串失敗
2462
				if($spiltString["status"]==="false"){
2463
 
2464
					#設置執行失敗
2465
					$result["status"]="false";
2466
 
2467
					#設置執行錯誤訊息
2468
					$result["error"]=$spiltString;
2469
 
2470
					#回傳結果
2471
					return $result;
2472
 
2473
					}#if end
2474
 
2475
				#如果剛好分割出一筆資料
2476
				if($spiltString["dataCounts"]===1){
2477
 
2478
					#如果尚未設置過msgId
2479
					if($this->connInfo[$from->resourceId]["gotMsgId"]==="false"){
2480
 
2481
						#取得待確認訊息id
2482
						$msgId=$spiltString["dataArray"][0];
2483
 
2484
						#初始化儲存現有msgId的變數
2485
						$msgIdArray=array();
2486
 
2487
						#取得現有的msgId
2488
						foreach($this->connInfo as $cInfo){
2489
 
2490
							#如果msgId不為空
2491
							if($cInfo["msgId"]!==""){
2492
 
2493
								#儲存msgId
2494
								$msgIdArray[]=$cInfo["msgId"];
2495
 
2496
								}#if end
2497
 
2498
							}#foreach end
2499
 
2500
						#檢查msgId是否存在於$msgIdArray裡面
2501
						if(in_array($msgId,$msgIdArray)){
2502
 
2503
							#設置自己的msgId
2504
							$this->connInfo[$from->resourceId]["msgId"]=$msgId;						
2505
 
2506
							#設置已經設置過msgId
2507
							$this->connInfo[$from->resourceId]["gotMsgId"]="true";
2508
 
2509
							#設置成功訊息
2510
							$msg="set msgId successfully";
2511
 
2512
							#包裝訊息
2513
							#"type"為"status"	
2514
							#"status"為"false"		
2515
							#"data"為實際的訊息內容
2516
							$packedMsg=array("type"=>"status","status"=>"true","data"=>$msg);
2517
 
2518
							#設置要給自己看的訊息
2519
							$from->send(json_encode($packedMsg));
2520
 
2521
							#針對每個連線
2522
							foreach($this->connInfo as $connIndex=>$connInfo){
2523
 
2524
								#如果是跟發訊息者同msgId但id不一樣的連線
2525
								if($connInfo["msgId"]===$msgId && $connIndex!==$from->resourceId){
2526
 
2527
									#將id為$connIndex的連線斷線
2528
									$this->clients->detach($this->connInfo[$connIndex]["conn"]);
2529
 
2530
									#提示已經將連線斷開
2531
									echo "Connection {$connIndex} has disconnected\n";
2532
 
2533
									#移除先前同msgId但id不一樣的連線
2534
									unset($this->connInfo[$connIndex]);
2535
 
2536
									#針對每個連線
2537
									foreach($this->connInfo as $cIndexForTD=>$cInfoForTD){
2538
 
2539
										#針對 talkTo 的每個項目
2540
										foreach($cInfoForTD["talkTo"] as $ttIndex=>$ttInfo){
2541
 
2542
											#如果是不存在的通話對象
2543
											if($ttInfo["id"]===$connIndex){
2544
 
2545
												#移除之
2546
												unset($this->connInfo[$cIndexForTD]["talkTo"][$ttIndex]);
2547
 
2548
												}#if end
2549
 
2550
											}#foreach end
2551
 
2552
										}#foreach end
2553
 
2554
									}#if end
2555
 
2556
								}#foreach end
2557
 
2558
							#如果有要確認的訊息陣列
2559
							if(isset($this->unConfirmMsg[$msgId])){
2560
 
2561
								#初始化要傳送的待確認訊息
2562
								$packedMsg=array();
2563
 
2564
								#有幾個要確認的訊息就執行幾次
2565
								foreach($this->unConfirmMsg[$msgId] as $unCMindex=>$unCMinfo){
2566
 
2567
									#如果待確認訊息的傳送目標id不等於剛要求更換msgId的用戶id
2568
									if($unCMinfo["toId"]!==$from->resourceId){
2569
 
2570
										#設置傳送目標id為要求更換msgId的用戶id
2571
										$this->unConfirmMsg[$msgId][$unCMindex]["toId"]=$from->resourceId;
2572
 
2573
										#檢查所有連線資訊
2574
										foreach($this->connInfo as $connId=>$connInfo){
2575
 
2576
											#依據talkTo清單的每個對象
2577
											foreach($connInfo["talkTo"] as $talk2Index=>$talk2Info){
2578
 
2579
												#若對象的id為$unCMinfo["toId"]且userId為$this->connInfo[$from->resourceId]["userId"]且msgId為$this->connInfo[$from->resourceId]["msgId"]者
2580
												if($talk2Info["id"]===$unCMinfo["toId"] && $talk2Info["userId"]===$this->connInfo[$from->resourceId]["userId"] && $talk2Info["msgId"]===$this->connInfo[$from->resourceId]["msgId"]){
2581
 
2582
													#移除該talkTo對象
2583
													unset($this->connInfo[$connId]["talkTo"][$talk2Index]);
2584
 
2585
													}#if ded
2586
 
2587
												}#foreach end
2588
 
2589
											}#foreach end
2590
 
2591
										}#if end
2592
 
2593
									#如果要傳送的待確認訊息為空陣列
2594
									if($packedMsg===array()){
2595
 
2596
										#包裝訊息
2597
										#"type"為"msg"
2598
										#"index"為$cInfo["id"]
2599
										#"data"為實際的訊息內容
2600
										$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
2601
 
2602
										}#if end
2603
 
2604
									}#foreach end
2605
 
2606
								#如果要傳送的待確認訊息不為空陣列
2607
								if($packedMsg!==array()){
2608
 
2609
									#var_dump("重新登入更改msgId後要傳送的未確認訊息:".print_r($packedMsg,true));
2610
 
2611
									#傳送包裝好的待確認訊息給對方
2612
									$from->send(json_encode($packedMsg));
2613
 
2614
									}#if end
2615
 
2616
								}#if end
2617
 
2618
							#結束程式
2619
							return true;
2620
 
2621
							}#if end
2622
 
2623
						}#if end
2624
 
2625
					#反之已經設置過 msgId 了
2626
					else{
2627
 
2628
						#設置錯誤訊息
2629
						$msg="msgId already set";
2630
 
2631
						#包裝訊息
2632
						#"type"為"status"	
2633
						#"status"為"false"		
2634
						#"data"為實際的訊息內容
2635
						$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
2636
 
2637
						#設置要給自己看的訊息
2638
						$from->send(json_encode($packedMsg));
2639
 
2640
						#結束程式
2641
						return true;
2642
 
2643
						}#else end
2644
 
2645
					}#if end
2646
 
2647
				#設置失敗訊息
2648
				$msg="set msgId failed";
2649
 
2650
				#包裝訊息
2651
				#"type"為"status"	
2652
				#"status"為"false"		
2653
				#"data"為實際的訊息內容
2654
				$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
2655
 
2656
				#設置要給自己看的訊息
2657
				$from->send(json_encode($packedMsg));
2658
 
2659
				#結束程式
2660
				return true;
2661
 
2662
				}#if end
2663
 
2664
			}#if end
2665
 
2666
		#如果訊息長度大於 strlen("mIndex:")
2667
		if(strlen($msg)>strlen("mIndex:")){
2668
 
2669
			#如果是確認收到訊息的回應訊息開頭 "mIndex:"    
2670
			#涵式說明:
2671
			#取得符合特定字首與字尾的字串
2672
			#回傳的結果:
2673
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
2674
			#$result["function"],當前執行的函數名稱.
2675
			#$result["error"],錯誤訊息陣列.
2676
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
2677
			#$result["returnString"],爲符合字首條件的字串內容。
2678
			#必填參數:
2679
			#$conf["checkString"],字串,要檢查的字串.
2680
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
2681
			#可省略參數:
2682
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
2683
			$conf["search::getMeetConditionsString"]["frontWord"]="mIndex:";
2684
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
2685
			#$conf["tailWord"]="";
2686
			#參考資料:
2687
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
2688
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
2689
			unset($conf["search::getMeetConditionsString"]);
2690
 
2691
			#如果選找前置字串 "mIndex:" 失敗
2692
			if($getMeetConditionsString["status"]==="false"){
2693
 
2694
				#設置執行失敗
2695
				$result["status"]="false";
2696
 
2697
				#設置執行錯誤訊息
2698
				$result["error"]=$getMeetConditionsString;
2699
 
2700
				#回傳結果
2701
				return $result;
2702
 
2703
				}#if end
2704
 
2705
			#如果存在	 "mIndex:" 前置字串
2706
			if($getMeetConditionsString["founded"]==="true"){
2707
 
2708
				#用 "mIndex:" 分割 $buf
2709
				#涵式說明:
2710
				#將固定格式的字串分開,並回傳分開的結果。
2711
				#回傳結果:
2712
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
2713
				#$result["error"],錯誤訊息陣列
2714
				#$result["function"],當前執行的函數名稱.
2715
				#$result["oriStr"],要分割的原始字串內容
2716
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
2717
				#$result["dataCounts"],爲總共分成幾段
2718
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
2719
				#必填的參數:
2720
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
2721
				$conf["stringProcess::spiltString"]["spiltSymbol"]="mIndex:";#爲以哪個符號作爲分割
2722
				#可省略參數:
2723
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
2724
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
2725
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
2726
				unset($conf["stringProcess::spiltString"]);
2727
 
2728
				#如果分割字串失敗
2729
				if($spiltString["status"]==="false"){
2730
 
2731
					#設置執行失敗
2732
					$result["status"]="false";
2733
 
2734
					#設置執行錯誤訊息
2735
					$result["error"]=$spiltString;
2736
 
2737
					#回傳結果
2738
					return $result;
2739
 
2740
					}#if end
2741
 
2742
				#如果存在分割的識別字串
2743
				if($spiltString["found"]==="true"){
2744
 
2745
					#如果只分割出一段
2746
					if($spiltString["dataCounts"]===1){
2747
 
2748
						#取得待確認訊息的索引
2749
						$mIndex=$spiltString["dataArray"][0];
2750
 
2751
						}#if end
2752
 
2753
					}#if end
2754
 
2755
				}#if end
2756
 
2757
			}#if end
2758
 
2759
		#如果有要講話的對象
2760
		if(count($this->connInfo[$from->resourceId]["talkTo"])>0){
2761
 
2762
			#依據每個對話對象
2763
			foreach($this->connInfo[$from->resourceId]["talkTo"] as $index => $cInfo){
2764
 
2765
				#如果要講話的對象不存在(socket已經斷開)
2766
				if(!isset($this->connInfo[$cInfo["id"]])){
2767
 
2768
					#將訊息儲存起來,等對象上線後再把訊息傳過去.
2769
					$this->unSendMsg[]=array(
2770
						"fromId"=>$from->resourceId,
2771
						"toId"=>"",
2772
						"fromUserId"=>$this->connInfo[$from->resourceId]["userId"],
2773
						"toUserId"=>$cInfo["userId"],
2774
						"msg"=>$msg
2775
						);
2776
 
2777
					}#if end
2778
 
2779
				#反之,講話的對象存在
2780
				else{
2781
 
2782
					#如果收到確認收到訊息的回應
2783
					if($mIndex!=="false"){
2784
 
2785
						#儲存對話目標的msgId
2786
						$targetMsgId=$this->connInfo[$from->resourceId]["msgId"];
2787
 
2788
						#針對每個連線的待確認訊息
2789
						foreach($this->unConfirmMsg as $unCMindex=>$unCMinfo){
2790
 
2791
							#debug
2792
							#var_dump($unCMindex."!==".$targetMsgId." && count(\$unCMinfo):".count($unCMinfo));
2793
 
2794
							#如果 未確認訊息達到10則以上 且不是接收訊息者的msgId
2795
							if($unCMindex!==$targetMsgId && count($unCMinfo)>10){
2796
 
2797
								#代表接收訊息的用戶無法透過網路跟server溝通
2798
 
2799
								#提示 server 連線已結束
2800
								echo "Connection {$unCMinfo["id"]} has disconnected\n";
2801
 
2802
								#將待驗證的訊息變成留言訊息
2803
 
2804
								#有幾個未確認訊息就執行幾次
2805
								foreach($this->unConfirmMsg[$unCMindex] as $unConMsgIndex => $unConMsgInfo){
2806
 
2807
									#將訊息儲存起來,等對象上線後再把訊息傳過去.
2808
									$this->unSendMsg[]=array(
2809
										"fromId"=>$unConMsgInfo["fromId"],
2810
										"toId"=>"",
2811
										"fromUserId"=>$unConMsgInfo["fromUserId"],
2812
										"toUserId"=>$unConMsgInfo["toUserId"],
2813
										"msg"=>$unConMsgInfo["msg"]
2814
										);
2815
 
2816
									}#foreach end
2817
 
2818
								#移除待驗證的訊息資訊
2819
								unset($this->unConfirmMsg[$unCMindex]);
2820
 
2821
								#將client的連線斷開
2822
								$this->clients->detach($this->connInfo[$unConMsgInfo["fromId"]]["conn"]);
2823
 
2824
								#移除連線的資訊
2825
								unset($this->connInfo[$unConMsgInfo["fromId"]]);								
2826
 
2827
								}#if end
2828
 
2829
							}#foreach end
2830
 
2831
						#存在收到訊息用戶id的待確認訊息
2832
						if(isset($this->unConfirmMsg[$targetMsgId])){
2833
 
2834
							#如果該未確認訊息存在
2835
							if(isset($this->unConfirmMsg[$targetMsgId][$mIndex])){
2836
 
2837
								#debug
2838
								#var_dump("移除待確認的訊息".print_r($this->unConfirmMsg[$targetMsgId][$mIndex],true));
2839
 
2840
								#移除該確認訊息
2841
								unset($this->unConfirmMsg[$targetMsgId][$mIndex]);
2842
 
2843
								#還剩下幾個待確認訊息就執行幾次
2844
								foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex=>$unCMinfo){
2845
 
2846
									#如果後面還有訊息
2847
									if(isset($this->unConfirmMsg[$targetMsgId][$unCMindex+1])){
2848
 
2849
										#如果與下一份訊息的 fromUserId一樣, toUserId 一樣, fromId一樣, toId 不同, msg 一樣.
2850
										if(
2851
											(
2852
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]
2853
												)
2854
											&&
2855
											(
2856
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]
2857
												)
2858
											&&
2859
											(
2860
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]
2861
												)
2862
											&&
2863
											(
2864
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"]!==$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]
2865
												)	
2866
											&&
2867
											(
2868
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]
2869
												)									
2870
											){
2871
 
2872
											#卸除該筆重複的訊息
2873
											unset($this->unConfirmMsg[$targetMsgId][$unCMindex]);
2874
 
2875
											#跳到下一則訊息
2876
											continue;	
2877
 
2878
											}#if end
2879
 
2880
										/*	
2881
										#debug
2882
										else{
2883
 
2884
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]);
2885
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]);
2886
 
2887
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]);
2888
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]);
2889
 
2890
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]);
2891
 
2892
											}#else end
2893
										*/
2894
 
2895
										}#if end
2896
 
2897
									#包裝訊息
2898
									#"type"為"msg"
2899
									#"index"為$cInfo["id"]
2900
									#"data"為實際的訊息內容
2901
									$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
2902
 
2903
									#傳送包裝好的待確認訊息給對方
2904
									$from->send(json_encode($packedMsg));
2905
 
2906
									#一次只送一則訊息
2907
									break;
2908
 
2909
									}#foreach end
2910
 
2911
								}#if end
2912
 
2913
							}#if end
2914
 
2915
						}#if end
2916
 
2917
					#反之為要傳送的訊息
2918
					else{
2919
 
2920
						#儲存對話目標的msgId
2921
						$targetMsgId=$this->connInfo[$cInfo["id"]]["msgId"];
2922
 
2923
						#$unConfirmMsg[$msgId],為訊息接收方的$msgId,亦即收到訊息後,要跟server說有收到訊息者.
2924
						#"fromId",訊息來源的id
2925
						#"toId",訊息目的的id
2926
						#"fromUserId",訊息來源的userId
2927
						#"toUserId",訊息目標的userId
2928
						#"msg",傳送的訊息
2929
						#"msgId",訊息目標連線的msgId
2930
						#儲存待確認傳送的訊息到 $unConfirmMsg
2931
						$this->unConfirmMsg[$targetMsgId][]=array('fromId'=>$from->resourceId,'toId'=>$cInfo["id"],'fromUserId'=>$this->connInfo[$from->resourceId]["userId"],'toUserId'=>$cInfo["userId"],'msg'=>$msg,'msgId'=>$this->connInfo[$cInfo["id"]]["msgId"]);
2932
 
2933
						#var_dump($this->unConfirmMsg[$targetMsgId]);			
2934
 
2935
						#如果未確認的訊息數量已經達到10則
2936
						if(count($this->unConfirmMsg[$targetMsgId])>10){
2937
 
2938
							#代表用戶無法透過網路跟server溝通
2939
 
2940
							#提示 server 連線已結束
2941
							echo "Connection {$cInfo["id"]} has disconnected\n";
2942
 
2943
							#將待驗證的訊息變成留言訊息
2944
 
2945
							#有幾個未確認訊息就執行幾次
2946
							foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex => $unCMinfo){
2947
 
2948
								#將訊息儲存起來,等對象上線後再把訊息傳過去.
2949
								$this->unSendMsg[]=array(
2950
									"fromId"=>$unCMinfo["fromId"],
2951
									"toId"=>"",
2952
									"fromUserId"=>$unCMinfo["fromUserId"],
2953
									"toUserId"=>$unCMinfo["toUserId"],
2954
									"msg"=>$unCMinfo["msg"]
2955
									);
2956
 
2957
								}#foreach end
2958
 
2959
							#移除待驗證的訊息資訊
2960
							unset($this->unConfirmMsg[$targetMsgId]);
2961
 
2962
							#將client的連線斷開
2963
							$this->clients->detach($this->connInfo[$cInfo["id"]]["conn"]);
2964
 
2965
							#移除連線的資訊
2966
							unset($this->connInfo[$cInfo["id"]]);
2967
 
2968
							}#if end
2969
 
2970
						#反之
2971
						else{
2972
 
2973
							#裡面有幾個待確認的訊息就執行幾次
2974
							foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex=>$unCMinfo){
2975
 
2976
								#如果後面還有訊息
2977
								if(isset($this->unConfirmMsg[$targetMsgId][$unCMindex+1])){
2978
 
2979
									#debug
2980
									#var_dump($this->unConfirmMsg[$targetMsgId]);
2981
 
2982
									#如果與下一份訊息的 fromUserId一樣, toUserId 一樣, fromId一樣, toId 不同, msg 一樣.
2983
									if(
2984
										(
2985
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]
2986
											)
2987
										&&
2988
										(
2989
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]
2990
											)
2991
										&&
2992
										(
2993
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]
2994
											)
2995
										&&
2996
										(
2997
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"]!==$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]
2998
											)	
2999
										&&
3000
										(
3001
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]
3002
											)									
3003
										){
3004
 
3005
										#卸除該筆重複的訊息
3006
										unset($this->unConfirmMsg[$targetMsgId][$unCMindex]);
3007
 
3008
										#跳到下一則訊息
3009
										continue;	
3010
 
3011
										}#if end
3012
 
3013
									/*	
3014
									#debug
3015
									else{
3016
 
3017
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]);
3018
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]);
3019
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]);
3020
 
3021
										}#else end
3022
									*/
3023
 
3024
									}#if end
3025
 
3026
								#debug
3027
								#var_dump("index:".$targetMsgId.print_r($this->unConfirmMsg[$targetMsgId],true));
3028
 
3029
								#另存 ConnectionInterface 物件
3030
								$connObject=$this->connInfo[$cInfo["id"]]["conn"];
3031
 
3032
								#包裝訊息
3033
								#"type"為"msg"
3034
								#"index"為$cInfo["id"]
3035
								#"data"為實際的訊息內容
3036
								$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
3037
 
3038
								#傳送包裝好的訊息給對方
3039
								$connObject->send(json_encode($packedMsg));
3040
 
3041
								#一次只送一則訊息
3042
								break;
3043
 
3044
								}#foreach end
3045
 
3046
							}#else end
3047
 
3048
						}#else end	
3049
 
3050
					}#else end
3051
 
3052
				}#foreach end
3053
 
3054
			}#if end
3055
 
3056
		#反之沒有講話的對象
3057
		else{
3058
 
3059
			$msg="Message 「".$msg."」 will not be received by any one";
3060
 
3061
			#提示server訊息被拋棄
3062
			echo $msg;
3063
 
3064
			#包裝訊息
3065
			#"type"為"status"	
3066
			#"status"為"false"		
3067
			#"data"為實際的訊息內容
3068
			$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
3069
 
3070
			#設置要給自己看的訊息
3071
			$from->send(json_encode($packedMsg));
3072
 
3073
			}#else end
3074
 
3075
		}#function onMessage end
3076
 
3077
	#當clinet的連線斷掉前
3078
    	public function onClose(ConnectionInterface $conn){
3079
 
3080
		// The connection is closed, remove it, as we can no longer send it messages
3081
        	$this->clients->detach($conn);
3082
 
3083
		#提示 server 連線已結束
3084
        	echo "Connection {$conn->resourceId} has disconnected\n";
3085
 
3086
		#取得斷線目標的待確認訊息id
3087
		$msgId=$this->connInfo[$conn->resourceId]["msgId"];
3088
 
3089
		#移除目標id的待確認訊息
3090
		unset($this->unConfirmMsg[$msgId]);
3091
 
3092
		#移除連線的資訊
3093
		unset($this->connInfo[$conn->resourceId]);
3094
 
3095
		}#function onClose end
3096
 
3097
		#當出現錯誤時
3098
    		public function onError(ConnectionInterface $conn, \Exception $e){
3099
 
3100
		#提示出現連線錯誤
3101
		echo "An error has occurred: {$e->getMessage()}\n";
3102
 
3103
		#關閉socket
3104
        	$conn->close();
3105
 
3106
		}#fucntion onError end
3107
 
3108
	}#class ChatV2 end
3109
 
3110
#用 ChatV3 類別來實作 MessageComponentInterface 界面,
3111
#新增可以對Server下達command的功能
3112
#修正要設置的msgId不存在時不會回傳錯誤訊息且繼續執行的問題
3113
class ChatV3 implements MessageComponentInterface{
3114
 
3115
	#初始化儲存使用者資訊的陣列
3116
	private $connInfo=array();	
3117
 
3118
	#初始化儲存未傳送出去的留言訊息
3119
	#"fromId",訊息來源的id
3120
	#"toId",訊息目的的id
3121
	#"fromUserId",訊息來源的userId
3122
	#"toUserId",訊息目標的userId
3123
	#"msg",傳送的訊息
3124
	private $unSendMsg=array();
3125
 
3126
	#初始化儲存待確認是否送達到對方的訊息
3127
	#$unConfirmMsg[$id],$id為訊息接收方,亦即收到訊息後,要跟server說有收到訊息者.
3128
	#"fromId",訊息來源的id
3129
	#"toId",訊息目的的id
3130
	#"fromUserId",訊息來源的userId
3131
	#"toUserId",訊息目標的userId
3132
	#"msg",傳送的訊息
3133
	private $unConfirmMsg=array();
3134
 
3135
	#初始化一開始尚未能夠連線到資料庫
3136
	private static $dbTouchable=false;
3137
 
3138
	#初始化db的位置
3139
	public static $dbAddress="localhost";	
3140
 
3141
	#初始化連線db用的帳戶
3142
	public static $dbAccount="root";
3143
 
3144
	#初始化連線的db名稱
3145
	public static $dbName="test";
3146
 
3147
	#初始化連線db時用的密碼
3148
	public static $dbPassword="";
3149
 
3150
	#初始化連線db的哪個資料表
3151
	public static $memberTableName="member";
3152
 
3153
	#初始化登入時用來驗證帳號的資料表欄位名稱
3154
	public static $accountCol="account";
3155
 
3156
	#初始化登入時用來驗證密碼的資料表欄位名稱,設為""代表不用密碼來認證
3157
	public static $passwordCol="password";
3158
 
3159
	#初始化用來儲存 __FILE__ 內容的變數 fileArgu
3160
	public static $fileArgu=__FILE__;	
3161
 
3162
	#建構子
3163
	public function __construct(){
3164
 
3165
		#如果尚未可以上資料庫
3166
		if(!(self::$dbTouchable)){
3167
 
3168
			#嘗試連線到目標資料庫.資料表
3169
			#涵式說明:
3170
			#一次取得資料庫、表的資料
3171
			#回傳的結果
3172
			#$result["status"],執行結果"true"為成功;"false"為執行失敗。
3173
			#$result["error"],錯誤訊息陣列。
3174
			#$result["function"],當前執行的漢書名稱.
3175
			#$result["dataColumnName"],抓取的資料欄位名稱陣列.
3176
				#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
3177
			#$result["dataContent"],爲資料的內容。
3178
			#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
3179
				#$dataSetNum 爲第$dataSetNum+1筆資料
3180
				#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
3181
			#$result["dataCount"],爲取得的資料筆數。
3182
			#$result["sql"],執行的sql字串.
3183
			#必填的參數:
3184
			$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
3185
			$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
3186
			$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
3187
			$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
3188
			$conf["db::fastGetDbData"]["columnYouWant"]=array("id",self::$accountCol);#你想要的欄位!,若設為「array("*")」則代表全部欄位.
3189
 
3190
			#如果 $passwordCol 不為空
3191
			if(self::$passwordCol!=""){
3192
 
3193
				#加上密碼欄位
3194
				$conf["db::fastGetDbData"]["columnYouWant"][]=self::$passwordCol;
3195
 
3196
				}#if end
3197
 
3198
			#可省略的參數:
3199
			$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
3200
			#$conf["db::fastGetDbData"]["WhereColumnName"]=array("account","password");#用於判斷語句的欄位項目陣列。
3201
			#$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac,$pw);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
3202
			#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
3203
			#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
3204
			#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
3205
			#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
3206
			#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
3207
			#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
3208
			$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
3209
			#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
3210
			#備註:
3211
			#建議在查詢資料前,能夠檢查是否每個欄位都存在.
3212
			$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
3213
			unset($conf["db::fastGetDbData"]);
3214
 
3215
			#如果取得資料失敗
3216
			if($fastGetDbData["status"]==="false"){
3217
 
3218
				#設置執行失敗
3219
				$result["status"]="false";
3220
 
3221
				#設置執行錯誤訊息
3222
				$result["error"]=$fastGetDbData;
3223
 
3224
				#印出debug訊息
3225
				var_dump($result);
3226
 
3227
				#結束程式
3228
				exit;
3229
 
3230
				}#if end
3231
 
3232
			#連線成功,將self::dbTouchable設為true
3233
			self::$dbTouchable=true;
3234
 
3235
			}#if end
3236
 
3237
		$this->clients = new \SplObjectStorage;
3238
 
3239
		}#funciton __construct end
3240
 
3241
	#當用戶與伺服器建立連線時
3242
	public function onOpen(ConnectionInterface $conn){
3243
 
3244
		// Store the new connection to send messages to later
3245
		 $this->clients->attach($conn);
3246
 
3247
		#提示server有clent連上web socket.
3248
		echo "New connection! ({$conn->resourceId})\n";
3249
 
3250
		#用client的id為index來儲存額外的資訊
3251
		#元素 "conn" 代表已經建立連線的ConnectionInterface物件
3252
		#元素 "talkTo" 代表要跟誰講話
3253
		#元素 "userId" 代表辨識使用者的id
3254
		#元素 "loigin=array("ac","pw")" 代表client輸入的帳號與密碼
3255
		#元素 "msgId" 為用來識別待確認訊息的索引
3256
		#元素 "gotMsgId" 為用來識別是否已經設置過 msgId 了
3257
	 	#$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""),"type"=>"");
3258
		$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"talkTo"=>array(),"userId"=>"","login"=>array("ac"=>"","pw"=>""),"msgId"=>"","gotMsgId"=>"false");
3259
 
3260
		#包裝訊息
3261
		#"type"為"login"	
3262
		#"status"為"true"		
3263
		#"data"為實際的訊息內容
3264
		$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
3265
 
3266
		#提示輸入帳號	
3267
		$conn->send(json_encode($packedMsg));
3268
 
3269
		}#function onOpen end
3270
 
3271
	#當伺服器收到訊息時
3272
	public function onMessage(ConnectionInterface $from, $msg){
3273
 
3274
		#debug
3275
		#$array=array("msgId"=>$this->connInfo[$from->resourceId]["msgId"],"resourceId"=>$from->resourceId,"msg"=>$msg);
3276
		#var_dump($array);
3277
 
3278
		#如果該連線沒有使用者id
3279
		if($this->connInfo[$from->resourceId]["userId"]===""){
3280
 
3281
			#代表需要認證,認證的會員資料表 slef::memberTableName,需要以下三個欄位.
3282
			#id		  自訂
3283
			#account  自訂
3284
			#password varchar(33)
3285
 
3286
			/*
3287
 
3288
			#如果尚未輸入用戶端類型
3289
			if($this->connInfo[$from->resourceId]["type"]===""){
3290
 
3291
				#如果 $msg 長度大於 "type:"
3292
				if(strlen($msg) > strlen("type:")){
3293
 
3294
					#檢查有無前置字元 "account:"
3295
					#函式說明:
3296
					#將字串特定關鍵字與其前面的內容剔除
3297
					#回傳結果:
3298
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
3299
					#$result["error"],錯誤訊息陣列.
3300
					#$result["warning"],警告訊息鎮列.
3301
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
3302
					#$result["function"],當前執行的函數名稱.
3303
					#$result["oriStr"],要處理的原始字串內容.
3304
					#$result["content"],處理好的的字串內容.
3305
					#必填的參數:
3306
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
3307
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="type:";#特定字串.
3308
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
3309
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
3310
 
3311
					#如果移除前置字元失敗
3312
					if($delStrBeforeKeyWord["status"]==="false"){
3313
 
3314
						#設置執行失敗
3315
						$result["status"]="false";
3316
 
3317
						#設置執行錯誤訊息
3318
						$result["error"]=$delStrBeforeKeyWord;
3319
 
3320
						#回傳結果
3321
						return $result;
3322
 
3323
						}#if end
3324
 
3325
					#如果有符合條件的前置字元
3326
					if($delStrBeforeKeyWord["founded"]==="true"){
3327
 
3328
						#儲存用戶端類型
3329
						$this->connInfo[$from->resourceId]["type"]=$delStrBeforeKeyWord["content"];
3330
 
3331
						}#if end
3332
 
3333
					#反之
3334
					else{
3335
 
3336
						#提示輸入用戶端類型
3337
						$from->send(json_encode("Please input your type! ex:type:user"));
3338
 
3339
						#結束程式
3340
						return true;
3341
 
3342
						}#else end
3343
 
3344
					}#if end
3345
 
3346
				#反之代表輸入錯誤格式的type
3347
				else{
3348
 
3349
					#提示輸入用戶端類型
3350
					$from->send(json_encode("Please input your type! ex:type:user"));
3351
 
3352
					#結束程式
3353
					return true;
3354
 
3355
					}#else end
3356
 
3357
				}#if end
3358
 
3359
			#如果用戶端是"user"
3360
			if($this->connInfo[$from->resourceId]["type"]==="user"){
3361
 
3362
				#...
3363
 
3364
				}#if end
3365
 
3366
			#反之如果用戶端是"device"
3367
			else if($this->connInfo[$from->resourceId]["type"]==="device"){
3368
 
3369
				#...
3370
 
3371
				}#if end
3372
 
3373
			*/
3374
 
3375
			#如果尚未輸入帳戶
3376
			if($this->connInfo[$from->resourceId]["login"]["ac"]===""){
3377
 
3378
				#如果 $msg 長度大於 "account:"
3379
				if(strlen($msg) > strlen("account:")){
3380
 
3381
					#檢查有無前置字元 "account:"
3382
					#函式說明:
3383
					#將字串特定關鍵字與其前面的內容剔除
3384
					#回傳結果:
3385
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
3386
					#$result["error"],錯誤訊息陣列.
3387
					#$result["warning"],警告訊息鎮列.
3388
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
3389
					#$result["function"],當前執行的函數名稱.
3390
					#$result["oriStr"],要處理的原始字串內容.
3391
					#$result["content"],處理好的的字串內容.
3392
					#必填的參數:
3393
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
3394
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="account:";#特定字串.
3395
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
3396
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
3397
 
3398
					#如果移除前置字元失敗
3399
					if($delStrBeforeKeyWord["status"]==="false"){
3400
 
3401
						#設置執行失敗
3402
						$result["status"]="false";
3403
 
3404
						#設置執行錯誤訊息
3405
						$result["error"]=$delStrBeforeKeyWord;
3406
 
3407
						#回傳結果
3408
						return $result;
3409
 
3410
						}#if end
3411
 
3412
					#如果有符合條件的前置字元
3413
					if($delStrBeforeKeyWord["founded"]==="true"){
3414
 
3415
						#儲存帳戶
3416
						$this->connInfo[$from->resourceId]["login"]["ac"]=$delStrBeforeKeyWord["content"];
3417
 
3418
						}#if end
3419
 
3420
					#反之代表格式錯誤	
3421
					else{
3422
 
3423
						#包裝訊息
3424
						#"type"為"login"	
3425
						#"status"為"true"		
3426
						#"data"為實際的訊息內容
3427
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
3428
 
3429
						#提示輸入帳號	
3430
						$from->send(json_encode($packedMsg));
3431
 
3432
						#結束程式
3433
						return true;
3434
 
3435
						}#else end
3436
 
3437
					}#if end
3438
 
3439
				#反之代表輸入錯誤格式的account
3440
				else{
3441
 
3442
					#包裝訊息
3443
					#"type"為"login"	
3444
					#"status"為"true"		
3445
					#"data"為實際的訊息內容
3446
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
3447
 
3448
					#提示輸入帳號	
3449
					$from->send(json_encode($packedMsg));
3450
 
3451
					#結束程式
3452
					return true;
3453
 
3454
					}#else end
3455
 
3456
				}#if end
3457
 
3458
			#如果有設置密碼欄位
3459
			if(self::$passwordCol!==""){
3460
 
3461
				#如果尚未輸入密碼
3462
				if($this->connInfo[$from->resourceId]["login"]["pw"]===""){
3463
 
3464
					#$msg 長度大於 "password:"
3465
					if(strlen($msg) > strlen("password:")){
3466
 
3467
						#檢查有無前置字元 "password:"
3468
						#函式說明:
3469
						#將字串特定關鍵字與其前面的內容剔除
3470
						#回傳結果:
3471
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
3472
						#$result["error"],錯誤訊息陣列.
3473
						#$result["warning"],警告訊息鎮列.
3474
						#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
3475
						#$result["function"],當前執行的函數名稱.
3476
						#$result["oriStr"],要處理的原始字串內容.
3477
						#$result["content"],處理好的的字串內容.
3478
						#必填的參數:
3479
						$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
3480
						$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="password:";#特定字串.
3481
						$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
3482
						unset($conf["stringProcess::delStrBeforeKeyWord"]);
3483
 
3484
						#如果移除前置字元失敗
3485
						if($delStrBeforeKeyWord["status"]==="false"){
3486
 
3487
							#設置執行失敗
3488
							$result["status"]="false";
3489
 
3490
							#設置執行錯誤訊息
3491
							$result["error"]=$delStrBeforeKeyWord;
3492
 
3493
							#回傳結果
3494
							return $result;
3495
 
3496
							}#if end
3497
 
3498
						#如果有符合條件的前置字元
3499
						if($delStrBeforeKeyWord["founded"]==="true"){
3500
 
3501
							#儲存密碼
3502
							$this->connInfo[$from->resourceId]["login"]["pw"]=$delStrBeforeKeyWord["content"];
3503
 
3504
							}#if end
3505
 
3506
						#反之代表格式錯誤
3507
						else{
3508
 
3509
							#包裝訊息
3510
							#"type"為"login"	
3511
							#"status"為"true"		
3512
							#"data"為實際的訊息內容
3513
							$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
3514
 
3515
							#提示輸入密碼		
3516
							$from->send(json_encode($packedMsg));
3517
 
3518
							#結束程式
3519
							return true;
3520
 
3521
							}#else end
3522
 
3523
						}#if end
3524
 
3525
					#反之代表格式錯誤
3526
					else{
3527
 
3528
						#包裝訊息
3529
						#"type"為"login"	
3530
						#"status"為"true"		
3531
						#"data"為實際的訊息內容
3532
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
3533
 
3534
						#提示輸入密碼		
3535
						$from->send(json_encode($packedMsg));
3536
 
3537
						#結束程式
3538
						return true;
3539
 
3540
						}#else end
3541
 
3542
					}#if end
3543
 
3544
				}#if end
3545
 
3546
			#如果已經輸入帳號了
3547
			if($this->connInfo[$from->resourceId]["login"]["ac"]!=""){
3548
 
3549
				#設置可以進行驗證
3550
				$startAuth=true;
3551
 
3552
				#另存帳號
3553
				$ac=$this->connInfo[$from->resourceId]["login"]["ac"];
3554
 
3555
				#初始化密碼
3556
				$pw="";
3557
 
3558
				#如果有設置密碼欄位
3559
				if(self::$passwordCol!==""){
3560
 
3561
					#如果client已經輸入密碼了
3562
					if($this->connInfo[$from->resourceId]["login"]["pw"]!=""){
3563
 
3564
						#另存密碼
3565
						$pw=md5($this->connInfo[$from->resourceId]["login"]["pw"]);
3566
 
3567
						}#if end
3568
 
3569
					#反之
3570
					else{
3571
 
3572
						#設置尚不能進行認證
3573
						$startAuth=false;
3574
 
3575
						}#else end
3576
 
3577
					}#if end
3578
 
3579
				#如果尚不能進行驗證
3580
				if(!$startAuth){
3581
 
3582
					#結束程式
3583
					return true;
3584
 
3585
					}#if end
3586
 
3587
				#檢查有無符合的帳戶密碼
3588
				#涵式說明:
3589
				#一次取得資料庫、表的資料
3590
				#回傳的結果
3591
				#$result["status"],執行結果"true"為成功;"false"為執行失敗。
3592
				#$result["error"],錯誤訊息陣列。
3593
				#$result["function"],當前執行的漢書名稱.
3594
				#$result["dataColumnName"],抓取的資料欄位名稱陣列.
3595
					#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
3596
				#$result["dataContent"],爲資料的內容。
3597
				#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
3598
					#$dataSetNum 爲第$dataSetNum+1筆資料
3599
					#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
3600
				#$result["dataCount"],爲取得的資料筆數。
3601
				#$result["sql"],執行的sql字串.
3602
				#必填的參數:
3603
				$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
3604
				$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
3605
				$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
3606
				$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
3607
				$conf["db::fastGetDbData"]["columnYouWant"]=array("id");#你想要的欄位!,若設為「array("*")」則代表全部欄位.
3608
				#可省略的參數:
3609
				$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
3610
				$conf["db::fastGetDbData"]["WhereColumnName"]=array(self::$accountCol);#用於判斷語句的欄位項目陣列。
3611
				$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
3612
 
3613
				#如果有輸入密碼
3614
				if($pw!==""){
3615
 
3616
					#新增要判斷 self::$password 欄位,是否有於 $pw
3617
					$conf["db::fastGetDbData"]["WhereColumnName"][]=self::$passwordCol;
3618
					$conf["db::fastGetDbData"]["WhereColumnValue"][]=$pw;
3619
 
3620
					}#if end
3621
 
3622
				#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
3623
				#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
3624
				#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
3625
				#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
3626
				#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
3627
				#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
3628
				$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
3629
				#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
3630
				#備註:
3631
				#建議在查詢資料前,能夠檢查是否每個欄位都存在.
3632
				$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
3633
				unset($conf["db::fastGetDbData"]);
3634
 
3635
				#如果取得資料失敗
3636
				if($fastGetDbData["status"]==="false"){
3637
 
3638
					#設置執行失敗
3639
					$result["status"]="false";
3640
 
3641
					#設置執行錯誤訊息
3642
					$result["error"]=$fastGetDbData;					
3643
 
3644
					#提示server有資料庫錯誤
3645
					echo "dbError!";
3646
 
3647
					#結束程式
3648
					exit;
3649
 
3650
					}#if end
3651
 
3652
				#如果沒有一筆資料
3653
				if($fastGetDbData["dataCount"]!==1){
3654
 
3655
					#代表登入失敗
3656
 
3657
					#清空登入用的帳戶
3658
					$this->connInfo[$from->resourceId]["login"]["ac"]="";
3659
 
3660
					#清空登入用的密碼
3661
					$this->connInfo[$from->resourceId]["login"]["pw"]="";
3662
 
3663
					#包裝訊息
3664
					#"type"為"login"	
3665
					#"status"為"false"		
3666
					#"data"為實際的訊息內容
3667
					$packedMsg=array("type"=>"login","status"=>"false","data"=>"Login failed, please input account. ex:account:ws1");
3668
 
3669
					#提示登入失敗					
3670
					$from->send(json_encode($packedMsg));
3671
 
3672
					#執行到這即可
3673
					return true;
3674
 
3675
					}#if end
3676
 
3677
				#反之代表帳戶資訊正確
3678
				else{
3679
 
3680
					#設置 $myUserId
3681
					$myUserId=$this->connInfo[$from->resourceId]["userId"]=$fastGetDbData["dataContent"]["id"][0];
3682
 
3683
					#設置 $myId
3684
					$myId=$from->resourceId;
3685
 
3686
					#初始化msgId的部份內容
3687
					$msgId=$myUserId."-";
3688
 
3689
					#初始化儲存msgId的陣列
3690
					$msgIdArray=array();
3691
 
3692
					#取得所有client的msgId
3693
					foreach($this->connInfo as $clientInfoArray){
3694
 
3695
						#如果msgId不為""
3696
						if($clientInfoArray["msgId"]!==""){
3697
 
3698
							#取得msgId
3699
							$msgIdArray[]=$clientInfoArray["msgId"];
3700
 
3701
							}#if end
3702
 
3703
						}#foreach end
3704
 
3705
					#如果尚未產生完整的msgId或msgId有重複
3706
					while($msgId===$myUserId."-" || in_array($msgId,$msgIdArray)){
3707
 
3708
						#涵式說明:
3709
						#建立以圖片(PNG格式)呈現的驗證碼.
3710
						#回傳的解果:
3711
						#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
3712
						#$result["error"],錯誤訊息.
3713
						#$result["function"],檔前執行的函數名稱.
3714
						#$result["randNumberWord"],傳驗證碼的內容.
3715
						#$result["imgAddress"],圖片的位置與名稱.
3716
						#必填的參數:
3717
						#$conf["imgAddressAndName"],字串,爲驗證碼圖片儲存的位置與名稱,副檔名程式會自動產生
3718
						$conf["authenticate::validationCode"]["imgAddressAndName"]="no used!";
3719
						#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
3720
						$conf["authenticate::validationCode"]["fileArgu"]="no used!";
3721
						#可省略的參數:
3722
						#$conf["num"],字串,爲驗證碼的位數,請輸入阿拉伯數字,預設為"8"位數.
3723
						#$conf["num"]="8";
3724
						#$conf["disableImg"],字串,是否要取消驗證碼圖片的輸出,"true"為要取消,預設為"false"為不取消
3725
						$conf["authenticate::validationCode"]["disableImg"]="true";
3726
						#$conf["imgToData"],字串,預設為"true"代表將圖片轉存成base64圖片,並將原始圖片移除;反之為"false"
3727
						#$conf["imgToData"]="true";
3728
						$validationCode=authenticate::validationCode($conf["authenticate::validationCode"]);
3729
						unset($conf["authenticate::validationCode"]);
3730
 
3731
						#如果產生亂數失敗
3732
						if($validationCode["status"]==="false"){
3733
 
3734
							#設置錯誤狀態
3735
							$result["status"]="false";
3736
 
3737
							#設置錯誤提示
3738
							$result["error"]=$validationCode;
3739
 
3740
							#印出錯誤訊息
3741
							var_dump($result);
3742
 
3743
							#回傳結果			
3744
							return $result;				
3745
 
3746
							}#if end
3747
 
3748
						#儲存產生好的msgId	
3749
						$msgId=$myUserId."-".$validationCode["randNumberWord"];
3750
 
3751
						}#while end
3752
 
3753
					#設置獨立於id與userId且用於驗證訊息是否收到的msgId
3754
					$this->connInfo[$from->resourceId]["msgId"]=$msgId;
3755
 
3756
					#包裝訊息
3757
					#"type"為"login"	
3758
					#"status"為"true"		
3759
					#"data"為實際的訊息內容
3760
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Login successfully!");
3761
 
3762
					#提示登入成功
3763
					$from->send(json_encode($packedMsg));
3764
 
3765
					#檢查是否有訊息是要給自己的
3766
					foreach($this->unSendMsg as $index => $historyMsg){
3767
 
3768
						#如果有要給自己的訊息
3769
						if($myUserId===$historyMsg["toUserId"]){
3770
 
3771
							#包裝訊息
3772
							#"type"為"unSendMsg?"	
3773
							#"status"為"true"		
3774
							#"data"為實際的訊息內容
3775
							$packedMsg=array("type"=>"unSendMsg?","status"=>"true","data"=>$historyMsg["msg"]);
3776
 
3777
							#接收別人給的留言
3778
							$from->send(json_encode($packedMsg));
3779
 
3780
							#有幾個人在線上就執行幾次
3781
							foreach($this->connInfo as $toId => $cInfo){
3782
 
3783
								#如果是自己
3784
								if($myId===$toId ){
3785
 
3786
									#跳過
3787
									continue;
3788
 
3789
									}#if end
3790
 
3791
								#如果留言的對象有在線上
3792
								if($historyMsg["fromUserId"]===$cInfo["userId"]){
3793
 
3794
									#檢查對方是否已經在自己的通話清單裡面了
3795
 
3796
									#初始化要將對方加到自己的對話清單裡面
3797
									$add=false;
3798
 
3799
									#根據自己的每個通話對象
3800
									foreach($this->connInfo[$myId]["talkTo"] as $myToIndex=>$myToCinfo ){
3801
 
3802
										#如果對對方已經存在於自己的對話清單裡面了
3803
										if($myToCinfo["userId"]===$historyMsg["fromUserId"] && $myId===$historyMsg["fromId"]){
3804
 
3805
											#設置不要將對方加到自己的對話清單裡面
3806
											$add=false;
3807
 
3808
											#跳出foreach
3809
											break;
3810
 
3811
											}#if end
3812
 
3813
										}#foreach end
3814
 
3815
									#如果要將對方加到自己的對話清單裡面
3816
									if($add){
3817
 
3818
										#將對方加到自己的talkTo清單裡面
3819
										$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$historyMsg["fromUserId"],"msgId"=>$this->connInfo[$toId]["msgId"]);
3820
 
3821
										}#if end
3822
 
3823
									#檢查自己有沒有在對方talkTo清單裡面
3824
 
3825
									#假設對方需要加自己到對話清單裡面
3826
									$add=true;
3827
 
3828
									#檢查通話對象能否跟自己對話
3829
 
3830
									#依據對方每個通話的對象
3831
									foreach($this->connInfo[$toId]["talkTo"] as $talkToIndex=>$talkToCinfo){
3832
 
3833
										#如果自己的userId已經在對方的對話清單裡面了
3834
										if($myUserId===$talkToCinfo["userId"]){
3835
 
3836
											#如果對方對話userId對應的id不在線上
3837
											if(!isset($this->connInfo[$toId])){
3838
 
3839
												#debug
3840
												#var_dump("對方對話userId(".$talkToCinfo["userId"].")應的id(".$toId.")不在線上");	
3841
 
3842
												#檢查對方對話清單是否已經含有自己的id與userId了
3843
 
3844
												#假設對方對話清單沒有自己的id與userId
3845
												$update=true;
3846
 
3847
												#依據對方每個通話的對象
3848
												foreach($this->connInfo[$toId]["talkTo"] as $ceToIndex=>$ceToCinfo){
3849
 
3850
													#如果對方對話清單已經含有自己的id與userId了												
3851
													if($ceToCinfo["id"]===$myId && $ceToCinfo["userId"]===$myUserId){
3852
 
3853
														#debug
3854
														#var_dump("對方對話清單已經含有自己的id(".$myId.")與userId了(".$myUserId.")");
3855
 
3856
														#設置不需要更新
3857
														$update=false;
3858
 
3859
														#debug
3860
														#var_dump($toId."要加".$myId."到通話清單裡面");
3861
 
3862
														#設置對方不需要加自己到對話清單裡面
3863
														$add=false;
3864
 
3865
														}#if end
3866
 
3867
													}#foreach end
3868
 
3869
												#如果對方對話清單沒有自己的id與userId與msgId
3870
												if($update){
3871
 
3872
													#debug
3873
													#var_dump($toId."要更新對話清單中索引為".$talkToIndex."的id(".$this->connInfo[$toId]["talkTo"][$talkToIndex]["id"].")為".$myId);
3874
 
3875
													#將自己在對方對話清單裡面的id改成現在的id
3876
													$this->connInfo[$toId]["talkTo"][$talkToIndex]["id"]=$myId;
3877
 
3878
													}#if end
3879
 
3880
												#反之對方對話清單已經有自己的id與userId
3881
												else{
3882
 
3883
													#移除對方該已經斷線的對話id
3884
													unset($this->connInfo[$toId]["talkTo"][$talkToIndex]);
3885
 
3886
													}#else end
3887
 
3888
												}#if end
3889
 
3890
											}#if end
3891
 
3892
										}#foreach end
3893
 
3894
									#如果對方需要加自己到對話清單裡面
3895
									if($add){
3896
 
3897
										#檢查對方每個通話對象
3898
										foreach($this->connInfo[$toId]["talkTo"] as $reCktIndex=>$reCktInfo){
3899
 
3900
											#如果已經有將自己加到對方的對話清單裡面
3901
											if($reCktInfo["id"]===$myId && $reCktInfo["userId"]===$myUserId){
3902
 
3903
												#設置不用將自己加到對方的對話清單裡面
3904
												$add=false;
3905
 
3906
												}#if end
3907
 
3908
											}#foreach end
3909
 
3910
										#如果對方需要加自己到對話清單裡面
3911
										if($add){
3912
 
3913
											#debug
3914
											#var_dump($toId."要加".$myId."(msgId為".$this->connInfo[$myId]["msgId"].")到通話清單裡面");
3915
 
3916
											#讓通話對象也可以傳送訊息回來
3917
											$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId,"msgId"=>$this->connInfo[$myId]["msgId"]);
3918
 
3919
											}#if end
3920
 
3921
										}#if end
3922
 
3923
									}#if end
3924
 
3925
								}#foreach end
3926
 
3927
							#移除留言紀錄
3928
							unset($this->unSendMsg[$index]);
3929
 
3930
							}#if end
3931
 
3932
						}#foreach end
3933
 
3934
					#檢查線上是否有人想跟我對話
3935
 
3936
					#有幾個人在線上就執行幾次
3937
					foreach($this->connInfo as $toId => $cInfo){
3938
 
3939
						#如果是自己
3940
						if($myId===$toId){
3941
 
3942
							#跳過
3943
							continue;
3944
 
3945
							}#if end
3946
 
3947
						#該cliet目前再跟幾個人通話,就執行幾次
3948
						foreach($cInfo["talkTo"] as $tIndex=>$tInfo){
3949
 
3950
							#如果自己的userId在對方的對話清單裡面
3951
							if($myUserId===$tInfo["userId"]){
3952
 
3953
								#假設自己需要被對方加到對話清單裡面
3954
								$add=true;
3955
 
3956
								#檢查自己是否已經在對方的對話清單裡面
3957
 
3958
								#對方有幾個通話對象就執行幾次
3959
								foreach($this->connInfo[$toId]["talkTo"] as $toIndex=>$toCinfo){
3960
 
3961
									#如果自己已經在對方的對話清單裡面
3962
									if($myUserId===$toCinfo["userId"] && $myId===$toCinfo["id"]){
3963
 
3964
										#設置自己不需要被對方加到對話清單裡面
3965
										$add=false;
3966
 
3967
										#跳出迴圈
3968
										break;
3969
 
3970
										}#if end
3971
 
3972
									}#foreach end
3973
 
3974
								#另存針對自己userId的連線id
3975
								$oneIdOfMyUserid=$this->connInfo[$toId]["talkTo"][$tIndex]["id"];
3976
 
3977
								#如果對方對話清單裡面的用戶id不在線
3978
								if(!isset($this->connInfo[$oneIdOfMyUserid])){
3979
 
3980
									#假設要將自己在對方對話清單裡面的id改成現在的id
3981
									$update=true;
3982
 
3983
									#自己不需要被對方加到對話清單裡面
3984
									$add=false;
3985
 
3986
									#檢查自己的id是否已經在對方的對話id裡面
3987
									foreach($this->connInfo[$toId]["talkTo"] as $ceIndex=>$ceInfo){
3988
 
3989
										#如果自己的id已經在對方的對話清單裡面
3990
										if($myId===$ceInfo["id"]){
3991
 
3992
											#設置不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
3993
											$update=false;
3994
 
3995
											#跳出迴圈
3996
											break;
3997
 
3998
											}#if end
3999
 
4000
										}#foreach end
4001
 
4002
									#如果要將自己在對方對話清單裡面的id改成現在的id
4003
									if($update){
4004
 
4005
										#debug
4006
										#var_dump($toId."要更新對話清單中索引為".$tIndex."的id(".$this->connInfo[$toId]["talkTo"][$tIndex]["id"].")為".$myId);
4007
 
4008
										#將自己在對方對話清單裡面的id改成現在的id
4009
										$this->connInfo[$toId]["talkTo"][$tIndex]["id"]=$myId;
4010
 
4011
										}#if end
4012
 
4013
									#反之不要將自己在對方對話清單裡面的id改成現在的id(可以移除該對話id)
4014
									else{
4015
 
4016
										#移除該對話id
4017
										unset($this->connInfo[$toId]["talkTo"][$tIndex]);
4018
 
4019
										}#else end
4020
 
4021
									}#if end	
4022
 
4023
								#如果要將自己加到對方的的通話清單裡面
4024
								if($add){
4025
 
4026
									#debug
4027
									#var_dump($toId."要加".$myId."(msgId為".$this->connInfo[$myId]["msgId"].")到通話清單裡面");
4028
 
4029
									#將自己加到對方的的通話清單裡面
4030
									$this->connInfo[$toId]["talkTo"][]=array("id"=>$myId,"userId"=>$myUserId,"msgId"=>$this->connInfo[$myId]["msgId"]);			
4031
 
4032
									}#if end								
4033
 
4034
								#檢查對方是否已經在自己的對話清單裡面
4035
 
4036
								#設置要新增對方到自己的對話清單裡面.
4037
								$add=true;
4038
 
4039
								#自己有幾個對話對象就執行幾次
4040
								foreach($this->connInfo[$myId]["talkTo"] as $mtIndex=>$mtInfo){
4041
 
4042
									#對方的userId與id若在自己的對話清單裡面
4043
									if($mtInfo["userId"]===$cInfo["userId"] && $mtInfo["id"]===$toId){
4044
 
4045
										#設置不需要新增對方到自己的對話清單裡面
4046
										$add=false;
4047
 
4048
										#跳出 foreach
4049
										break;
4050
 
4051
										}#if end
4052
 
4053
									}#foreache end
4054
 
4055
								#如果要新增對方到自己的對話清單裡面.
4056
								if($add){
4057
 
4058
									#自己有幾個對話對象就執行幾次
4059
									foreach($this->connInfo[$myId]["talkTo"] as $mtIndex=>$mtInfo){
4060
 
4061
										#如果對方已經在自己的通話清單
4062
										if($mtInfo["userId"]===$cInfo["userId"] && $mtInfo["id"]===$toId){
4063
 
4064
											#設置不要將對方到自己的對話清單裡面.
4065
											$add=false;
4066
 
4067
											#跳出 foreach end
4068
											break;
4069
 
4070
											}#if end
4071
 
4072
										}#foreach end
4073
 
4074
									#如果要新增對方到自己的對話清單裡面.
4075
									if($add){
4076
 
4077
										#將對方加到自己的對話清單裡面
4078
										$this->connInfo[$myId]["talkTo"][]=array("id"=>$toId,"userId"=>$cInfo["userId"],"msgId"=>$this->connInfo[$toId]["msgId"]);
4079
 
4080
										}#if end
4081
 
4082
									}#if end
4083
 
4084
								}#if end
4085
 
4086
							}#foreach end
4087
 
4088
						}#foreach end
4089
 
4090
					#結束認證成功後的流程
4091
					return true;
4092
 
4093
					}#else end
4094
 
4095
				}#else end
4096
 
4097
			#結束認證流程
4098
			return true;	
4099
 
4100
			}#if end
4101
 
4102
		#如果收到 "id?"
4103
		else if($msg==="id?"){
4104
 
4105
			#包裝訊息
4106
			#"type"為"id?"	
4107
			#"status"為"true"		
4108
			#"data"為實際的訊息內容
4109
			$packedMsg=array("type"=>"id?","status"=>"true","data"=>$from->resourceId);
4110
 
4111
			#傳自己的id給client
4112
			$from->send(json_encode($packedMsg));
4113
 
4114
			#回傳成功
4115
			return true;
4116
 
4117
			}#if end
4118
 
4119
		#如果收到 "ids?"
4120
		else if($msg==="ids?"){
4121
 
4122
			#初始化儲存其他人的id
4123
			$idsArray=array();
4124
 
4125
			#針對所的client
4126
			foreach ($this->clients as $client){
4127
 
4128
				#排除自己
4129
				if($from !== $client){
4130
 
4131
					#取得其他人的id
4132
					$idsArray[]=$client->resourceId;
4133
 
4134
					}#if end
4135
 
4136
				}#foreach end			
4137
 
4138
			#包裝訊息
4139
			#"type"為"ids?"	
4140
			#"status"為"true"		
4141
			#"data"為實際的訊息內容
4142
			$packedMsg=array("type"=>"ids?","status"=>"true","data"=>$idsArray);
4143
 
4144
			#傳他人的id給client
4145
			$from->send(json_encode($packedMsg));
4146
 
4147
			#回傳成功
4148
			return true;
4149
 
4150
			}#if end
4151
 
4152
		#如果收到 "talkTo?"
4153
		else if($msg==="talkTo?"){
4154
 
4155
			#包裝訊息
4156
			#"type"為"talkTo?"	
4157
			#"status"為"true"		
4158
			#"data"為實際的訊息內容
4159
			$packedMsg=array("type"=>"talkTo?","status"=>"true","data"=>$this->connInfo[$from->resourceId]["talkTo"]);
4160
 
4161
			#正在對話的對象id給client
4162
			$from->send(json_encode($packedMsg));
4163
 
4164
			#回傳成功
4165
			return true;
4166
 
4167
			}#if end
4168
 
4169
		#反之如果是 "msgId?"
4170
		else if($msg==="msgId?"){
4171
 
4172
			#包裝訊息
4173
			#"type"為"talkTo?"	
4174
			#"status"為"true"		
4175
			#"data"為實際的訊息內容
4176
			$packedMsg=array("type"=>"msgId?","status"=>"true","data"=>$this->connInfo[$from->resourceId]["msgId"]);
4177
 
4178
			#取得自己的msgId
4179
			$from->send(json_encode($packedMsg));
4180
 
4181
			#回傳成功
4182
			return true;
4183
 
4184
			}#if end
4185
 
4186
		#如果收到的$msg長度大於 "talkTo:"
4187
		if(strlen($msg)>strlen("talkTo:")){
4188
 
4189
			#如果收到開頭為 "talkTo:"    
4190
			#涵式說明:
4191
			#取得符合特定字首與字尾的字串
4192
			#回傳的結果:
4193
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
4194
			#$result["function"],當前執行的函數名稱.
4195
			#$result["error"],錯誤訊息陣列.
4196
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
4197
			#$result["returnString"],爲符合字首條件的字串內容。
4198
			#必填參數:
4199
			#$conf["checkString"],字串,要檢查的字串.
4200
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
4201
			#可省略參數:
4202
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
4203
			$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
4204
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
4205
			#$conf["tailWord"]="";
4206
			#參考資料:
4207
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
4208
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
4209
			unset($conf["search::getMeetConditionsString"]);
4210
 
4211
			#如果選找前置字串 "talkTo:" 失敗
4212
			if($getMeetConditionsString["status"]==="false"){
4213
 
4214
				#設置執行失敗
4215
				$result["status"]="false";
4216
 
4217
				#設置執行錯誤訊息
4218
				$result["error"]=$getMeetConditionsString;
4219
 
4220
				#回傳結果
4221
				return $result;
4222
 
4223
				}#if end
4224
 
4225
			#如果存在 "talkTo:" 前置字串
4226
			if($getMeetConditionsString["founded"]==="true"){
4227
 
4228
				#用 "talkTo:" 分割 $buf
4229
				#涵式說明:
4230
				#將固定格式的字串分開,並回傳分開的結果。
4231
				#回傳結果:
4232
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
4233
				#$result["error"],錯誤訊息陣列
4234
				#$result["function"],當前執行的函數名稱.
4235
				#$result["oriStr"],要分割的原始字串內容
4236
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
4237
				#$result["dataCounts"],爲總共分成幾段
4238
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
4239
				#必填的參數:
4240
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
4241
				$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
4242
				#可省略參數:
4243
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
4244
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
4245
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
4246
				unset($conf["stringProcess::spiltString"]);
4247
 
4248
				#如果分割字串失敗
4249
				if($spiltString["status"]==="false"){
4250
 
4251
					#設置執行失敗
4252
					$result["status"]="false";
4253
 
4254
					#設置執行錯誤訊息
4255
					$result["error"]=$spiltString;
4256
 
4257
					#回傳結果
4258
					return $result;
4259
 
4260
					}#if end
4261
 
4262
				#如果剛好分割出一筆資料
4263
				if($spiltString["dataCounts"]===1){
4264
 
4265
					#取得自己的id
4266
					$myId=$from->resourceId;
4267
 
4268
					#取得講話對象的id
4269
					$toId=$spiltString["dataArray"][0];
4270
 
4271
					#設置對象不存在的識別
4272
					$targetExist=false;
4273
 
4274
					#設置通話對象的key
4275
					$targetKey="";					
4276
 
4277
					#如果要對話的對象存在
4278
					if(isset($this->connInfo[$toId])){
4279
 
4280
						#取得對象的userId
4281
						$toUserId=$this->connInfo[$toId]["userId"];
4282
 
4283
						#取得同userId的對象id們
4284
 
4285
						#初始化同userId的對象id
4286
						$targetC=array();
4287
 
4288
						#針對每個連線
4289
						foreach($this->connInfo as $eachIndex=>$eachInfo){
4290
 
4291
							#如果是自己
4292
							if($eachIndex===$myId){
4293
 
4294
								#跳到下一輪
4295
								continue;
4296
 
4297
								}#if end
4298
 
4299
							#如果是同userId的對象
4300
							if($eachInfo["userId"]===$toUserId){
4301
 
4302
								#取出連線
4303
								$targetC[$eachIndex]=$this->connInfo[$eachIndex];
4304
 
4305
								}#if end
4306
 
4307
							}#foreach end
4308
 
4309
						#針對每個同userId的連線
4310
						foreach($targetC as $tcIndex=>$tcInfo){
4311
 
4312
							#檢查自己的對話對象是否已經在清單裡面了
4313
 
4314
							#假設對象可以加到自己對話清單裡面
4315
							$add=true;
4316
 
4317
							#針對每個要講話的對象
4318
							foreach($this->connInfo[$myId]["talkTo"] as $index=>$cInfo){
4319
 
4320
								#如果對話對象已經在清單裡面了
4321
								if($this->connInfo[$tcIndex]["userId"]===$cInfo["userId"] && $tcIndex===$cInfo["id"] && $tcInfo["msgId"]===$cInfo["msgId"]){
4322
 
4323
									#設置不要再加到清單裡面
4324
									$add=false;
4325
 
4326
									#跳出foreach
4327
									break;
4328
 
4329
									}#if end								
4330
 
4331
								}#foreach end
4332
 
4333
							#如果要加入到對話清單裡面
4334
							if($add){
4335
 
4336
								#增加自己的對話對象
4337
								$this->connInfo[$myId]["talkTo"][]=array("id"=>$tcIndex,"userId"=>$this->connInfo[$tcIndex]["userId"],"msgId"=>$this->connInfo[$tcIndex]["msgId"]);
4338
 
4339
								#假設對方可以加自己到對話清單裡面
4340
								$add=true;
4341
 
4342
								#檢查通話對象能否跟自己對話
4343
								foreach($this->connInfo[$tcIndex]["talkTo"] as $index=>$cInfo){
4344
 
4345
									#如果對話對象已經在清單裡面了
4346
									if($this->connInfo[$myId]["userId"]===$cInfo["userId"]){
4347
 
4348
										#設置不要再加到清單裡面
4349
										$add=false;
4350
 
4351
										#跳出 foreach
4352
										break;
4353
 
4354
										}#if end
4355
 
4356
									}#foreach end
4357
 
4358
								#如果對方可以加自己到對話清單裡面
4359
								if($add){
4360
 
4361
									#讓通話對象也可以傳送訊息回來
4362
									$this->connInfo[$tcIndex]["talkTo"][]=array("id"=>$myId,"userId"=>$this->connInfo[$myId]["userId"],"msgId"=>$this->connInfo[$myId]["msgId"]);
4363
 
4364
									}#if end
4365
 
4366
								#設置成功訊息
4367
								$msg="client id ".$toId." added to talkTo list";
4368
 
4369
								#包裝訊息
4370
								#"type"為"status"	
4371
								#"status"為"true"		
4372
								#"data"為實際的訊息內容
4373
								$packedMsg=array("type"=>"status","status"=>"true","data"=>$msg);
4374
 
4375
								#設置要給自己看的訊息
4376
								$from->send(json_encode($packedMsg));							
4377
 
4378
								}#if end
4379
 
4380
							#反之
4381
							else{
4382
 
4383
								#設置錯誤訊息
4384
								$msg="client id ".$toId." already in talkTo list";
4385
 
4386
								#包裝訊息
4387
								#"type"為"status"	
4388
								#"status"為"false"		
4389
								#"data"為實際的訊息內容
4390
								$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
4391
 
4392
								#設置要給自己看的訊息
4393
								$from->send(json_encode($packedMsg));
4394
 
4395
								}#else end
4396
 
4397
							}#foreach end
4398
 
4399
						#回傳成功
4400
						return true;
4401
 
4402
						}#if end
4403
 
4404
					#反之不存在
4405
					else{
4406
 
4407
						#設置錯誤訊息
4408
						$msg="client id ".$toId." doesn't exist";
4409
 
4410
						#包裝訊息
4411
						#"type"為"status"	
4412
						#"status"為"false"		
4413
						#"data"為實際的訊息內容
4414
						$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
4415
 
4416
						#設置要給自己看的訊息
4417
						$from->send(json_encode($packedMsg));
4418
 
4419
						#回傳成功
4420
						return true;
4421
 
4422
						}#else end		
4423
 
4424
					}#if end
4425
 
4426
				}#if end
4427
 
4428
			}#if end
4429
 
4430
		#預設沒有收到確認收到訊息的回應訊息
4431
		$mIndex="false";
4432
 
4433
		#如果收到的$msg長度大於 "msgId:"
4434
		if(strlen($msg)>strlen("msgId:")){
4435
 
4436
			#解析 $msg
4437
 
4438
			#如果收到開頭為 "msgId:"    
4439
			#涵式說明:
4440
			#取得符合特定字首與字尾的字串
4441
			#回傳的結果:
4442
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
4443
			#$result["function"],當前執行的函數名稱.
4444
			#$result["error"],錯誤訊息陣列.
4445
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
4446
			#$result["returnString"],爲符合字首條件的字串內容。
4447
			#必填參數:
4448
			#$conf["checkString"],字串,要檢查的字串.
4449
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
4450
			#可省略參數:
4451
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
4452
			$conf["search::getMeetConditionsString"]["frontWord"]="msgId:";
4453
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
4454
			#$conf["tailWord"]="";
4455
			#參考資料:
4456
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
4457
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
4458
			unset($conf["search::getMeetConditionsString"]);
4459
 
4460
			#如果選找前置字串 "msgId:" 失敗
4461
			if($getMeetConditionsString["status"]==="false"){
4462
 
4463
				#設置執行失敗
4464
				$result["status"]="false";
4465
 
4466
				#設置執行錯誤訊息
4467
				$result["error"]=$getMeetConditionsString;
4468
 
4469
				#回傳結果
4470
				return $result;
4471
 
4472
				}#if end
4473
 
4474
			#如果存在	 "msgId:" 前置字串
4475
			if($getMeetConditionsString["founded"]==="true"){
4476
 
4477
				#用 "msgId:" 分割 $msg
4478
				#涵式說明:
4479
				#將固定格式的字串分開,並回傳分開的結果。
4480
				#回傳結果:
4481
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
4482
				#$result["error"],錯誤訊息陣列
4483
				#$result["function"],當前執行的函數名稱.
4484
				#$result["oriStr"],要分割的原始字串內容
4485
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
4486
				#$result["dataCounts"],爲總共分成幾段
4487
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
4488
				#必填的參數:
4489
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
4490
				$conf["stringProcess::spiltString"]["spiltSymbol"]="msgId:";#爲以哪個符號作爲分割
4491
				#可省略參數:
4492
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
4493
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
4494
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
4495
				unset($conf["stringProcess::spiltString"]);
4496
 
4497
				#如果分割字串失敗
4498
				if($spiltString["status"]==="false"){
4499
 
4500
					#設置執行失敗
4501
					$result["status"]="false";
4502
 
4503
					#設置執行錯誤訊息
4504
					$result["error"]=$spiltString;
4505
 
4506
					#回傳結果
4507
					return $result;
4508
 
4509
					}#if end
4510
 
4511
				#如果剛好分割出一筆資料
4512
				if($spiltString["dataCounts"]===1){
4513
 
4514
					#如果尚未設置過msgId
4515
					if($this->connInfo[$from->resourceId]["gotMsgId"]==="false"){
4516
 
4517
						#取得待確認訊息id
4518
						$msgId=$spiltString["dataArray"][0];
4519
 
4520
						#初始化儲存現有msgId的變數
4521
						$msgIdArray=array();
4522
 
4523
						#取得現有的msgId
4524
						foreach($this->connInfo as $cInfo){
4525
 
4526
							#如果msgId不為空
4527
							if($cInfo["msgId"]!==""){
4528
 
4529
								#儲存msgId
4530
								$msgIdArray[]=$cInfo["msgId"];
4531
 
4532
								}#if end
4533
 
4534
							}#foreach end
4535
 
4536
						#檢查msgId是否存在於$msgIdArray裡面
4537
						if(in_array($msgId,$msgIdArray)){
4538
 
4539
							#設置自己的msgId
4540
							$this->connInfo[$from->resourceId]["msgId"]=$msgId;						
4541
 
4542
							#設置已經設置過msgId
4543
							$this->connInfo[$from->resourceId]["gotMsgId"]="true";
4544
 
4545
							#設置成功訊息
4546
							$msg="set msgId successfully";
4547
 
4548
							#包裝訊息
4549
							#"type"為"status"	
4550
							#"status"為"false"		
4551
							#"data"為實際的訊息內容
4552
							$packedMsg=array("type"=>"status","status"=>"true","data"=>$msg);
4553
 
4554
							#設置要給自己看的訊息
4555
							$from->send(json_encode($packedMsg));
4556
 
4557
							#針對每個連線
4558
							foreach($this->connInfo as $connIndex=>$connInfo){
4559
 
4560
								#如果是跟發訊息者同msgId但id不一樣的連線
4561
								if($connInfo["msgId"]===$msgId && $connIndex!==$from->resourceId){
4562
 
4563
									#將id為$connIndex的連線斷線
4564
									$this->clients->detach($this->connInfo[$connIndex]["conn"]);
4565
 
4566
									#提示已經將連線斷開
4567
									echo "Connection {$connIndex} has disconnected\n";
4568
 
4569
									#移除先前同msgId但id不一樣的連線
4570
									unset($this->connInfo[$connIndex]);
4571
 
4572
									#針對每個連線
4573
									foreach($this->connInfo as $cIndexForTD=>$cInfoForTD){
4574
 
4575
										#針對 talkTo 的每個項目
4576
										foreach($cInfoForTD["talkTo"] as $ttIndex=>$ttInfo){
4577
 
4578
											#如果是不存在的通話對象
4579
											if($ttInfo["id"]===$connIndex){
4580
 
4581
												#移除之
4582
												unset($this->connInfo[$cIndexForTD]["talkTo"][$ttIndex]);
4583
 
4584
												}#if end
4585
 
4586
											}#foreach end
4587
 
4588
										}#foreach end
4589
 
4590
									}#if end
4591
 
4592
								}#foreach end
4593
 
4594
							#如果有要確認的訊息陣列
4595
							if(isset($this->unConfirmMsg[$msgId])){
4596
 
4597
								#初始化要傳送的待確認訊息
4598
								$packedMsg=array();
4599
 
4600
								#有幾個要確認的訊息就執行幾次
4601
								foreach($this->unConfirmMsg[$msgId] as $unCMindex=>$unCMinfo){
4602
 
4603
									#如果待確認訊息的傳送目標id不等於剛要求更換msgId的用戶id
4604
									if($unCMinfo["toId"]!==$from->resourceId){
4605
 
4606
										#設置傳送目標id為要求更換msgId的用戶id
4607
										$this->unConfirmMsg[$msgId][$unCMindex]["toId"]=$from->resourceId;
4608
 
4609
										#檢查所有連線資訊
4610
										foreach($this->connInfo as $connId=>$connInfo){
4611
 
4612
											#依據talkTo清單的每個對象
4613
											foreach($connInfo["talkTo"] as $talk2Index=>$talk2Info){
4614
 
4615
												#若對象的id為$unCMinfo["toId"]且userId為$this->connInfo[$from->resourceId]["userId"]且msgId為$this->connInfo[$from->resourceId]["msgId"]者
4616
												if($talk2Info["id"]===$unCMinfo["toId"] && $talk2Info["userId"]===$this->connInfo[$from->resourceId]["userId"] && $talk2Info["msgId"]===$this->connInfo[$from->resourceId]["msgId"]){
4617
 
4618
													#移除該talkTo對象
4619
													unset($this->connInfo[$connId]["talkTo"][$talk2Index]);
4620
 
4621
													}#if ded
4622
 
4623
												}#foreach end
4624
 
4625
											}#foreach end
4626
 
4627
										}#if end
4628
 
4629
									#如果要傳送的待確認訊息為空陣列
4630
									if($packedMsg===array()){
4631
 
4632
										#包裝訊息
4633
										#"type"為"msg"
4634
										#"index"為$cInfo["id"]
4635
										#"data"為實際的訊息內容
4636
										$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
4637
 
4638
										}#if end
4639
 
4640
									}#foreach end
4641
 
4642
								#如果要傳送的待確認訊息不為空陣列
4643
								if($packedMsg!==array()){
4644
 
4645
									#var_dump("重新登入更改msgId後要傳送的未確認訊息:".print_r($packedMsg,true));
4646
 
4647
									#傳送包裝好的待確認訊息給對方
4648
									$from->send(json_encode($packedMsg));
4649
 
4650
									}#if end
4651
 
4652
								}#if end
4653
 
4654
							#結束程式
4655
							return true;
4656
 
4657
							}#if end
4658
 
4659
							#反之想要用的msgId並不存在於server
4660
							else{
4661
 
4662
								#設置錯誤訊息
4663
								$msg="msgId 「".$msgId."」 doesn't exist";
4664
 
4665
								#包裝訊息
4666
								#"type"為"status"	
4667
								#"status"為"false"		
4668
								#"data"為實際的訊息內容
4669
								$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
4670
 
4671
								#設置要給自己看的訊息
4672
								$from->send(json_encode($packedMsg));
4673
 
4674
								#結束程式
4675
								return true;
4676
 
4677
								}#else end
4678
 
4679
						}#if end
4680
 
4681
					#反之已經設置過 msgId 了
4682
					else{
4683
 
4684
						#設置錯誤訊息
4685
						$msg="msgId already set";
4686
 
4687
						#包裝訊息
4688
						#"type"為"status"	
4689
						#"status"為"false"		
4690
						#"data"為實際的訊息內容
4691
						$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
4692
 
4693
						#設置要給自己看的訊息
4694
						$from->send(json_encode($packedMsg));
4695
 
4696
						#結束程式
4697
						return true;
4698
 
4699
						}#else end
4700
 
4701
					}#if end
4702
 
4703
				#設置失敗訊息
4704
				$msg="set msgId failed";
4705
 
4706
				#包裝訊息
4707
				#"type"為"status"	
4708
				#"status"為"false"		
4709
				#"data"為實際的訊息內容
4710
				$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
4711
 
4712
				#設置要給自己看的訊息
4713
				$from->send(json_encode($packedMsg));
4714
 
4715
				#結束程式
4716
				return true;
4717
 
4718
				}#if end
4719
 
4720
			}#if end
4721
 
4722
		#如果訊息長度大於 strlen("mIndex:")
4723
		if(strlen($msg)>strlen("mIndex:")){
4724
 
4725
			#如果是確認收到訊息的回應訊息開頭 "mIndex:"    
4726
			#涵式說明:
4727
			#取得符合特定字首與字尾的字串
4728
			#回傳的結果:
4729
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
4730
			#$result["function"],當前執行的函數名稱.
4731
			#$result["error"],錯誤訊息陣列.
4732
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
4733
			#$result["returnString"],爲符合字首條件的字串內容。
4734
			#必填參數:
4735
			#$conf["checkString"],字串,要檢查的字串.
4736
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
4737
			#可省略參數:
4738
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
4739
			$conf["search::getMeetConditionsString"]["frontWord"]="mIndex:";
4740
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
4741
			#$conf["tailWord"]="";
4742
			#參考資料:
4743
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
4744
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
4745
			unset($conf["search::getMeetConditionsString"]);
4746
 
4747
			#如果選找前置字串 "mIndex:" 失敗
4748
			if($getMeetConditionsString["status"]==="false"){
4749
 
4750
				#設置執行失敗
4751
				$result["status"]="false";
4752
 
4753
				#設置執行錯誤訊息
4754
				$result["error"]=$getMeetConditionsString;
4755
 
4756
				#回傳結果
4757
				return $result;
4758
 
4759
				}#if end
4760
 
4761
			#如果存在	 "mIndex:" 前置字串
4762
			if($getMeetConditionsString["founded"]==="true"){
4763
 
4764
				#用 "mIndex:" 分割 $buf
4765
				#涵式說明:
4766
				#將固定格式的字串分開,並回傳分開的結果。
4767
				#回傳結果:
4768
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
4769
				#$result["error"],錯誤訊息陣列
4770
				#$result["function"],當前執行的函數名稱.
4771
				#$result["oriStr"],要分割的原始字串內容
4772
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
4773
				#$result["dataCounts"],爲總共分成幾段
4774
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
4775
				#必填的參數:
4776
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
4777
				$conf["stringProcess::spiltString"]["spiltSymbol"]="mIndex:";#爲以哪個符號作爲分割
4778
				#可省略參數:
4779
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
4780
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
4781
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
4782
				unset($conf["stringProcess::spiltString"]);
4783
 
4784
				#如果分割字串失敗
4785
				if($spiltString["status"]==="false"){
4786
 
4787
					#設置執行失敗
4788
					$result["status"]="false";
4789
 
4790
					#設置執行錯誤訊息
4791
					$result["error"]=$spiltString;
4792
 
4793
					#回傳結果
4794
					return $result;
4795
 
4796
					}#if end
4797
 
4798
				#如果存在分割的識別字串
4799
				if($spiltString["found"]==="true"){
4800
 
4801
					#如果只分割出一段
4802
					if($spiltString["dataCounts"]===1){
4803
 
4804
						#取得待確認訊息的索引
4805
						$mIndex=$spiltString["dataArray"][0];
4806
 
4807
						}#if end
4808
 
4809
					}#if end
4810
 
4811
				}#if end
4812
 
4813
			}#if end
4814
 
4815
		#如果server收到訊息長度大於 "cmd:"
4816
		if(strlen($msg)>strlen("cmd:")){
4817
 
4818
			#如果$msg開頭為"cmd:"  
4819
			#涵式說明:
4820
			#取得符合特定字首與字尾的字串
4821
			#回傳的結果:
4822
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
4823
			#$result["function"],當前執行的函數名稱.
4824
			#$result["error"],錯誤訊息陣列.
4825
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
4826
			#$result["returnString"],爲符合字首條件的字串內容。
4827
			#必填參數:
4828
			#$conf["checkString"],字串,要檢查的字串.
4829
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
4830
			#可省略參數:
4831
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
4832
			$conf["search::getMeetConditionsString"]["frontWord"]="cmd:";
4833
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
4834
			#$conf["tailWord"]="";
4835
			#參考資料:
4836
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
4837
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
4838
			unset($conf["search::getMeetConditionsString"]);
4839
 
4840
			#如果選找前置字串 "cmd:" 失敗
4841
			if($getMeetConditionsString["status"]==="false"){
4842
 
4843
				#設置執行失敗
4844
				$result["status"]="false";
4845
 
4846
				#設置執行錯誤訊息
4847
				$result["error"]=$getMeetConditionsString;
4848
 
4849
				#回傳結果
4850
				return $result;
4851
 
4852
				}#if end
4853
 
4854
			#如果存在	 "cmd:" 前置字串
4855
			if($getMeetConditionsString["founded"]==="true"){
4856
 
4857
				#用 "cmd:" 分割 $buf
4858
				#涵式說明:
4859
				#將固定格式的字串分開,並回傳分開的結果。
4860
				#回傳結果:
4861
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
4862
				#$result["error"],錯誤訊息陣列
4863
				#$result["function"],當前執行的函數名稱.
4864
				#$result["oriStr"],要分割的原始字串內容
4865
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
4866
				#$result["dataCounts"],爲總共分成幾段
4867
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
4868
				#必填的參數:
4869
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
4870
				$conf["stringProcess::spiltString"]["spiltSymbol"]="cmd:";#爲以哪個符號作爲分割
4871
				#可省略參數:
4872
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
4873
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
4874
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
4875
				unset($conf["stringProcess::spiltString"]);
4876
 
4877
				#如果分割字串失敗
4878
				if($spiltString["status"]==="false"){
4879
 
4880
					#設置執行失敗
4881
					$result["status"]="false";
4882
 
4883
					#設置執行錯誤訊息
4884
					$result["error"]=$spiltString;
4885
 
4886
					#回傳結果
4887
					return $result;
4888
 
4889
					}#if end
4890
 
4891
				#如果剛好分割出一筆資料
4892
				if($spiltString["dataCounts"]===1){
4893
 
4894
					#取的要執行的指令
4895
					$cmd=$spiltString["dataArray"][0];
4896
 
4897
					#函式說明:
4898
					#呼叫shell執行系統命令,並取得回傳的內容.
4899
					#回傳的結果:
4900
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
4901
					#$result["error"],錯誤訊息陣列.
4902
					#$result["function"],當前執行的函數名稱.
4903
					#$result["cmd"],執行的指令內容.
4904
					#$result["output"],爲執行完二元碼後的輸出陣列.
4905
					#必填的參數
4906
					#$conf["command"],字串,要執行的指令與.
4907
					$conf["external::callShell"]["command"]=$cmd;
4908
					#$conf["fileArgu"],字串,變數__FILE__的內容.
4909
					$conf["external::callShell"]["fileArgu"]=self::$fileArgu;		
4910
					#可省略參數:
4911
					#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
4912
					#$conf["argu"]=array("");
4913
					#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
4914
					#$conf["arguIsAddr"]=array();
4915
					#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
4916
					#$conf["enablePrintDescription"]="true";
4917
					#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容.
4918
					#$conf["printDescription"]="";
4919
					#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
4920
					$conf["external::callShell"]["escapeshellarg"]="true";
4921
					#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
4922
					#$conf["username"]="";
4923
					#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
4924
					#$conf["password"]="";
4925
					#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要;"false"代表不要,預設為"false".
4926
					$conf["external::callShell"]["useScript"]="true";
4927
					#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 ".qbpwcf_tmp/external/callShell/".
4928
					#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
4929
					#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
4930
					#$conf["inBackGround"]="";
4931
					#備註:
4932
					#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
4933
					#參考資料:
4934
					#exec=>http://php.net/manual/en/function.exec.php
4935
					#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
4936
					#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
4937
					$callShell=external::callShell($conf["external::callShell"]);
4938
					unset($conf["external::callShell"]);
4939
 
4940
					#如果執行外部指令失敗
4941
					if($callShell["status"]==="false"){
4942
 
4943
						#設置要傳給client的訊息
4944
						$result=array("data"=>$callShell,"type"=>"status","status"=>"false");
4945
 
4946
						#將程式執行後的錯誤輸出傳給client					
4947
						$from->send(json_encode($result));
4948
 
4949
						#回傳結果
4950
						return true;
4951
 
4952
						}#if end
4953
 
4954
					#設置要傳給client的訊息
4955
					$result=array("data"=>$callShell["output"],"type"=>"cmd");
4956
 
4957
					#將程式執行後的輸出傳給client					
4958
					$from->send(json_encode($result));
4959
 
4960
					#結束程式
4961
					return true;
4962
 
4963
					}#if end
4964
 
4965
				}#if end
4966
 
4967
			}#if end
4968
 
4969
		#如果有要講話的對象
4970
		if(count($this->connInfo[$from->resourceId]["talkTo"])>0){
4971
 
4972
			#依據每個對話對象
4973
			foreach($this->connInfo[$from->resourceId]["talkTo"] as $index => $cInfo){
4974
 
4975
				#如果要講話的對象不存在(socket已經斷開)
4976
				if(!isset($this->connInfo[$cInfo["id"]])){
4977
 
4978
					#將訊息儲存起來,等對象上線後再把訊息傳過去.
4979
					$this->unSendMsg[]=array(
4980
						"fromId"=>$from->resourceId,
4981
						"toId"=>"",
4982
						"fromUserId"=>$this->connInfo[$from->resourceId]["userId"],
4983
						"toUserId"=>$cInfo["userId"],
4984
						"msg"=>$msg
4985
						);
4986
 
4987
					}#if end
4988
 
4989
				#反之,講話的對象存在
4990
				else{
4991
 
4992
					#如果收到確認收到訊息的回應
4993
					if($mIndex!=="false"){
4994
 
4995
						#儲存對話目標的msgId
4996
						$targetMsgId=$this->connInfo[$from->resourceId]["msgId"];
4997
 
4998
						#針對每個連線的待確認訊息
4999
						foreach($this->unConfirmMsg as $unCMindex=>$unCMinfo){
5000
 
5001
							#debug
5002
							#var_dump($unCMindex."!==".$targetMsgId." && count(\$unCMinfo):".count($unCMinfo));
5003
 
5004
							#如果 未確認訊息達到10則以上 且不是接收訊息者的msgId
5005
							if($unCMindex!==$targetMsgId && count($unCMinfo)>10){
5006
 
5007
								#代表接收訊息的用戶無法透過網路跟server溝通
5008
 
5009
								#提示 server 連線已結束
5010
								echo "Connection {$unCMinfo["id"]} has disconnected\n";
5011
 
5012
								#將待驗證的訊息變成留言訊息
5013
 
5014
								#有幾個未確認訊息就執行幾次
5015
								foreach($this->unConfirmMsg[$unCMindex] as $unConMsgIndex => $unConMsgInfo){
5016
 
5017
									#將訊息儲存起來,等對象上線後再把訊息傳過去.
5018
									$this->unSendMsg[]=array(
5019
										"fromId"=>$unConMsgInfo["fromId"],
5020
										"toId"=>"",
5021
										"fromUserId"=>$unConMsgInfo["fromUserId"],
5022
										"toUserId"=>$unConMsgInfo["toUserId"],
5023
										"msg"=>$unConMsgInfo["msg"]
5024
										);
5025
 
5026
									}#foreach end
5027
 
5028
								#移除待驗證的訊息資訊
5029
								unset($this->unConfirmMsg[$unCMindex]);
5030
 
5031
								#將client的連線斷開
5032
								$this->clients->detach($this->connInfo[$unConMsgInfo["fromId"]]["conn"]);
5033
 
5034
								#移除連線的資訊
5035
								unset($this->connInfo[$unConMsgInfo["fromId"]]);								
5036
 
5037
								}#if end
5038
 
5039
							}#foreach end
5040
 
5041
						#存在收到訊息用戶id的待確認訊息
5042
						if(isset($this->unConfirmMsg[$targetMsgId])){
5043
 
5044
							#如果該未確認訊息存在
5045
							if(isset($this->unConfirmMsg[$targetMsgId][$mIndex])){
5046
 
5047
								#debug
5048
								#var_dump("移除待確認的訊息".print_r($this->unConfirmMsg[$targetMsgId][$mIndex],true));
5049
 
5050
								#移除該確認訊息
5051
								unset($this->unConfirmMsg[$targetMsgId][$mIndex]);
5052
 
5053
								#還剩下幾個待確認訊息就執行幾次
5054
								foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex=>$unCMinfo){
5055
 
5056
									#如果後面還有訊息
5057
									if(isset($this->unConfirmMsg[$targetMsgId][$unCMindex+1])){
5058
 
5059
										#如果與下一份訊息的 fromUserId一樣, toUserId 一樣, fromId一樣, toId 不同, msg 一樣.
5060
										if(
5061
											(
5062
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]
5063
												)
5064
											&&
5065
											(
5066
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]
5067
												)
5068
											&&
5069
											(
5070
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]
5071
												)
5072
											&&
5073
											(
5074
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"]!==$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]
5075
												)	
5076
											&&
5077
											(
5078
												$this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]
5079
												)									
5080
											){
5081
 
5082
											#卸除該筆重複的訊息
5083
											unset($this->unConfirmMsg[$targetMsgId][$unCMindex]);
5084
 
5085
											#跳到下一則訊息
5086
											continue;	
5087
 
5088
											}#if end
5089
 
5090
										/*	
5091
										#debug
5092
										else{
5093
 
5094
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]);
5095
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]);
5096
 
5097
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]);
5098
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]);
5099
 
5100
											var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]);
5101
 
5102
											}#else end
5103
										*/
5104
 
5105
										}#if end
5106
 
5107
									#包裝訊息
5108
									#"type"為"msg"
5109
									#"index"為$cInfo["id"]
5110
									#"data"為實際的訊息內容
5111
									$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
5112
 
5113
									#傳送包裝好的待確認訊息給對方
5114
									$from->send(json_encode($packedMsg));
5115
 
5116
									#一次只送一則訊息
5117
									break;
5118
 
5119
									}#foreach end
5120
 
5121
								}#if end
5122
 
5123
							}#if end
5124
 
5125
						}#if end
5126
 
5127
					#反之為要傳送的訊息
5128
					else{
5129
 
5130
						#儲存對話目標的msgId
5131
						$targetMsgId=$this->connInfo[$cInfo["id"]]["msgId"];
5132
 
5133
						#$unConfirmMsg[$msgId],為訊息接收方的$msgId,亦即收到訊息後,要跟server說有收到訊息者.
5134
						#"fromId",訊息來源的id
5135
						#"toId",訊息目的的id
5136
						#"fromUserId",訊息來源的userId
5137
						#"toUserId",訊息目標的userId
5138
						#"msg",傳送的訊息
5139
						#"msgId",訊息目標連線的msgId
5140
						#儲存待確認傳送的訊息到 $unConfirmMsg
5141
						$this->unConfirmMsg[$targetMsgId][]=array('fromId'=>$from->resourceId,'toId'=>$cInfo["id"],'fromUserId'=>$this->connInfo[$from->resourceId]["userId"],'toUserId'=>$cInfo["userId"],'msg'=>$msg,'msgId'=>$this->connInfo[$cInfo["id"]]["msgId"]);
5142
 
5143
						#var_dump($this->unConfirmMsg[$targetMsgId]);			
5144
 
5145
						#如果未確認的訊息數量已經達到10則
5146
						if(count($this->unConfirmMsg[$targetMsgId])>10){
5147
 
5148
							#代表用戶無法透過網路跟server溝通
5149
 
5150
							#提示 server 連線已結束
5151
							echo "Connection {$cInfo["id"]} has disconnected\n";
5152
 
5153
							#將待驗證的訊息變成留言訊息
5154
 
5155
							#有幾個未確認訊息就執行幾次
5156
							foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex => $unCMinfo){
5157
 
5158
								#將訊息儲存起來,等對象上線後再把訊息傳過去.
5159
								$this->unSendMsg[]=array(
5160
									"fromId"=>$unCMinfo["fromId"],
5161
									"toId"=>"",
5162
									"fromUserId"=>$unCMinfo["fromUserId"],
5163
									"toUserId"=>$unCMinfo["toUserId"],
5164
									"msg"=>$unCMinfo["msg"]
5165
									);
5166
 
5167
								}#foreach end
5168
 
5169
							#移除待驗證的訊息資訊
5170
							unset($this->unConfirmMsg[$targetMsgId]);
5171
 
5172
							#將client的連線斷開
5173
							$this->clients->detach($this->connInfo[$cInfo["id"]]["conn"]);
5174
 
5175
							#移除連線的資訊
5176
							unset($this->connInfo[$cInfo["id"]]);
5177
 
5178
							}#if end
5179
 
5180
						#反之
5181
						else{
5182
 
5183
							#裡面有幾個待確認的訊息就執行幾次
5184
							foreach($this->unConfirmMsg[$targetMsgId] as $unCMindex=>$unCMinfo){
5185
 
5186
								#如果後面還有訊息
5187
								if(isset($this->unConfirmMsg[$targetMsgId][$unCMindex+1])){
5188
 
5189
									#debug
5190
									#var_dump($this->unConfirmMsg[$targetMsgId]);
5191
 
5192
									#如果與下一份訊息的 fromUserId一樣, toUserId 一樣, fromId一樣, toId 不同, msg 一樣.
5193
									if(
5194
										(
5195
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromUserId"]
5196
											)
5197
										&&
5198
										(
5199
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]
5200
											)
5201
										&&
5202
										(
5203
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["fromId"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["fromId"]
5204
											)
5205
										&&
5206
										(
5207
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"]!==$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]
5208
											)	
5209
										&&
5210
										(
5211
											$this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"]===$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]
5212
											)									
5213
										){
5214
 
5215
										#卸除該筆重複的訊息
5216
										unset($this->unConfirmMsg[$targetMsgId][$unCMindex]);
5217
 
5218
										#跳到下一則訊息
5219
										continue;	
5220
 
5221
										}#if end
5222
 
5223
									/*	
5224
									#debug
5225
									else{
5226
 
5227
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toUserId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toUserId"]);
5228
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["toId"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["toId"]);
5229
										var_dump($this->unConfirmMsg[$targetMsgId][$unCMindex]["msg"].":".$this->unConfirmMsg[$targetMsgId][$unCMindex+1]["msg"]);
5230
 
5231
										}#else end
5232
									*/
5233
 
5234
									}#if end
5235
 
5236
								#debug
5237
								#var_dump("index:".$targetMsgId.print_r($this->unConfirmMsg[$targetMsgId],true));
5238
 
5239
								#另存 ConnectionInterface 物件
5240
								$connObject=$this->connInfo[$cInfo["id"]]["conn"];
5241
 
5242
								#包裝訊息
5243
								#"type"為"msg"
5244
								#"index"為$cInfo["id"]
5245
								#"data"為實際的訊息內容
5246
								$packedMsg=array("type"=>"msg","index"=>$unCMindex,"data"=>$unCMinfo["msg"]);
5247
 
5248
								#傳送包裝好的訊息給對方
5249
								$connObject->send(json_encode($packedMsg));
5250
 
5251
								#一次只送一則訊息
5252
								break;
5253
 
5254
								}#foreach end
5255
 
5256
							}#else end
5257
 
5258
						}#else end	
5259
 
5260
					}#else end
5261
 
5262
				}#foreach end
5263
 
5264
			}#if end
5265
 
5266
		#反之沒有講話的對象
5267
		else{
5268
 
5269
			$msg="Message 「".$msg."」 will not be received by any one";
5270
 
5271
			#提示server訊息被拋棄
5272
			echo $msg;
5273
 
5274
			#包裝訊息
5275
			#"type"為"status"	
5276
			#"status"為"false"		
5277
			#"data"為實際的訊息內容
5278
			$packedMsg=array("type"=>"status","status"=>"false","data"=>$msg);
5279
 
5280
			#設置要給自己看的訊息
5281
			$from->send(json_encode($packedMsg));
5282
 
5283
			}#else end
5284
 
5285
		}#function onMessage end
5286
 
5287
	#當clinet的連線斷掉前
5288
	public function onClose(ConnectionInterface $conn){
5289
 
5290
		// The connection is closed, remove it, as we can no longer send it messages
5291
		$this->clients->detach($conn);
5292
 
5293
		#提示 server 連線已結束
5294
	 	echo "Connection {$conn->resourceId} has disconnected\n";
5295
 
5296
		#取得斷線目標的待確認訊息id
5297
		$msgId=$this->connInfo[$conn->resourceId]["msgId"];
5298
 
5299
		#移除目標id的待確認訊息
5300
		unset($this->unConfirmMsg[$msgId]);
5301
 
5302
		#移除連線的資訊
5303
		unset($this->connInfo[$conn->resourceId]);
5304
 
5305
		}#function onClose end
5306
 
5307
	#當出現錯誤時
5308
	public function onError(ConnectionInterface $conn, \Exception $e){
5309
 
5310
		#提示出現連線錯誤
5311
		echo "An error has occurred: {$e->getMessage()}\n";
5312
 
5313
		#關閉socket
5314
        	$conn->close();
5315
 
5316
		}#fucntion onError end
5317
 
5318
	}#class ChatV3 end
5319
 
5320
#用 soldier 類別來實作 MessageComponentInterface 界面,提供驗證身份後就可以執行系統命令的界面.
5321
class soldier implements MessageComponentInterface{
5322
 
5323
	#初始化儲存使用者資訊的陣列
5324
	private $connInfo=array();	
5325
 
5326
	#初始化一開始尚未能夠連線到資料庫
5327
	private static $dbTouchable=false;
5328
 
5329
	#初始化db的位置
5330
	public static $dbAddress="localhost";	
5331
 
5332
	#初始化連線db用的帳戶
5333
	public static $dbAccount="root";
5334
 
5335
	#初始化連線的db名稱
5336
	public static $dbName="test";
5337
 
5338
	#初始化連線db時用的密碼
5339
	public static $dbPassword="";
5340
 
5341
	#初始化連線db的哪個資料表
5342
	public static $memberTableName="member";
5343
 
5344
	#初始化登入時用來驗證帳號的資料表欄位名稱
5345
	public static $accountCol="account";
5346
 
5347
	#初始化登入時用來驗證密碼的資料表欄位名稱,設為""代表不用密碼來認證
5348
	public static $passwordCol="password";
5349
 
5350
	#初始化用來儲存 __FILE__ 內容的變數 fileArgu
5351
	public static $fileArgu=__FILE__;
5352
 
5353
	#當用戶與伺服器建立連線時
5354
    	public function onOpen(ConnectionInterface $conn){
5355
 
5356
		// Store the new connection to send messages to later
5357
        	$this->clients->attach($conn);
5358
 
5359
		#提示server有clent連上web socket.
5360
       		echo "New connection! ({$conn->resourceId})\n";
5361
 
5362
        	#用client的id為index來儲存額外的資訊
5363
        	#元素 "conn" 代表已經建立連線的ConnectionInterface物件
5364
        	#元素 "talkTo" 代表要跟誰講話
5365
		#元素 "userId" 代表辨識使用者的id
5366
		#元素 "loigin=array("ac","pw")" 代表client輸入的帳號與密碼
5367
        	$this->connInfo[$conn->resourceId]=array("conn"=>$conn,"userId"=>"","login"=>array("ac"=>"","pw"=>""));
5368
 
5369
		#包裝訊息
5370
		#"type"為"login"	
5371
		#"status"為"true"		
5372
		#"data"為實際的訊息內容
5373
		$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
5374
 
5375
		#提示輸入帳號	
5376
		$conn->send(json_encode($packedMsg));
5377
 
5378
		}#function onOpen end
5379
 
5380
	#當伺服器收到訊息時
5381
	public function onMessage(ConnectionInterface $from, $msg){
5382
 
5383
		#如果該連線沒有使用者id
5384
		if($this->connInfo[$from->resourceId]["userId"]===""){
5385
 
5386
			#如果尚未輸入帳戶
5387
			if($this->connInfo[$from->resourceId]["login"]["ac"]===""){
5388
 
5389
				#如果 $msg 長度大於 "account:"
5390
				if(strlen($msg) > strlen("account:")){
5391
 
5392
					#檢查有無前置字元 "account:"
5393
					#函式說明:
5394
					#將字串特定關鍵字與其前面的內容剔除
5395
					#回傳結果:
5396
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
5397
					#$result["error"],錯誤訊息陣列.
5398
					#$result["warning"],警告訊息鎮列.
5399
					#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
5400
					#$result["function"],當前執行的函數名稱.
5401
					#$result["oriStr"],要處理的原始字串內容.
5402
					#$result["content"],處理好的的字串內容.
5403
					#必填的參數:
5404
					$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
5405
					$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="account:";#特定字串.
5406
					$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
5407
					unset($conf["stringProcess::delStrBeforeKeyWord"]);
5408
 
5409
					#如果移除前置字元失敗
5410
					if($delStrBeforeKeyWord["status"]==="false"){
5411
 
5412
						#設置執行失敗
5413
						$result["status"]="false";
5414
 
5415
						#設置執行錯誤訊息
5416
						$result["error"]=$delStrBeforeKeyWord;
5417
 
5418
						#回傳結果
5419
						return $result;
5420
 
5421
						}#if end
5422
 
5423
					#如果有符合條件的前置字元
5424
					if($delStrBeforeKeyWord["founded"]==="true"){
5425
 
5426
						#儲存帳戶
5427
						$this->connInfo[$from->resourceId]["login"]["ac"]=$delStrBeforeKeyWord["content"];
5428
 
5429
						}#if end
5430
 
5431
					#反之代表格式錯誤	
5432
					else{
5433
 
5434
						#包裝訊息
5435
						#"type"為"login"	
5436
						#"status"為"true"		
5437
						#"data"為實際的訊息內容
5438
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
5439
 
5440
						#提示輸入帳號	
5441
						$from->send(json_encode($packedMsg));
5442
 
5443
						#結束程式
5444
						return true;
5445
 
5446
						}#else end
5447
 
5448
					}#if end
5449
 
5450
				#反之代表輸入錯誤格式的account
5451
				else{
5452
 
5453
					#包裝訊息
5454
					#"type"為"login"	
5455
					#"status"為"true"		
5456
					#"data"為實際的訊息內容
5457
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your account! ex:account:ws1");
5458
 
5459
					#提示輸入帳號	
5460
					$from->send(json_encode($packedMsg));
5461
 
5462
					#結束程式
5463
					return true;
5464
 
5465
					}#else end
5466
 
5467
				}#if end
5468
 
5469
			#如果有設置密碼欄位
5470
			if(self::$passwordCol!==""){
5471
 
5472
				#如果尚未輸入密碼
5473
				if($this->connInfo[$from->resourceId]["login"]["pw"]===""){
5474
 
5475
					#$msg 長度大於 "password:"
5476
					if(strlen($msg) > strlen("password:")){
5477
 
5478
						#檢查有無前置字元 "password:"
5479
						#函式說明:
5480
						#將字串特定關鍵字與其前面的內容剔除
5481
						#回傳結果:
5482
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
5483
						#$result["error"],錯誤訊息陣列.
5484
						#$result["warning"],警告訊息鎮列.
5485
						#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
5486
						#$result["function"],當前執行的函數名稱.
5487
						#$result["oriStr"],要處理的原始字串內容.
5488
						#$result["content"],處理好的的字串內容.
5489
						#必填的參數:
5490
						$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$msg;#要處理的字串.
5491
						$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="password:";#特定字串.
5492
						$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
5493
						unset($conf["stringProcess::delStrBeforeKeyWord"]);
5494
 
5495
						#如果移除前置字元失敗
5496
						if($delStrBeforeKeyWord["status"]==="false"){
5497
 
5498
							#設置執行失敗
5499
							$result["status"]="false";
5500
 
5501
							#設置執行錯誤訊息
5502
							$result["error"]=$delStrBeforeKeyWord;
5503
 
5504
							#回傳結果
5505
							return $result;
5506
 
5507
							}#if end
5508
 
5509
						#如果有符合條件的前置字元
5510
						if($delStrBeforeKeyWord["founded"]==="true"){
5511
 
5512
							#儲存密碼
5513
							$this->connInfo[$from->resourceId]["login"]["pw"]=$delStrBeforeKeyWord["content"];
5514
 
5515
							}#if end
5516
 
5517
						#反之代表格式錯誤
5518
						else{
5519
 
5520
							#包裝訊息
5521
							#"type"為"login"	
5522
							#"status"為"true"		
5523
							#"data"為實際的訊息內容
5524
							$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
5525
 
5526
							#提示輸入密碼		
5527
							$from->send(json_encode($packedMsg));
5528
 
5529
							#結束程式
5530
							return true;
5531
 
5532
							}#else end
5533
 
5534
						}#if end
5535
 
5536
					#反之代表格式錯誤
5537
					else{
5538
 
5539
						#包裝訊息
5540
						#"type"為"login"	
5541
						#"status"為"true"		
5542
						#"data"為實際的訊息內容
5543
						$packedMsg=array("type"=>"login","status"=>"true","data"=>"Please input your password! ex:password:ws1");
5544
 
5545
						#提示輸入密碼		
5546
						$from->send(json_encode($packedMsg));
5547
 
5548
						#結束程式
5549
						return true;
5550
 
5551
						}#else end
5552
 
5553
					}#if end
5554
 
5555
				}#if end
5556
 
5557
			#如果已經輸入帳號了
5558
			if($this->connInfo[$from->resourceId]["login"]["ac"]!=""){
5559
 
5560
				#設置可以進行驗證
5561
				$startAuth=true;
5562
 
5563
				#另存帳號
5564
				$ac=$this->connInfo[$from->resourceId]["login"]["ac"];
5565
 
5566
				#初始化密碼
5567
				$pw="";
5568
 
5569
				#如果有設置密碼欄位
5570
				if(self::$passwordCol!==""){
5571
 
5572
					#如果client已經輸入密碼了
5573
					if($this->connInfo[$from->resourceId]["login"]["pw"]!=""){
5574
 
5575
						#取得密碼
5576
						$pw=$this->connInfo[$from->resourceId]["login"]["pw"];
5577
 
5578
						}#if end
5579
 
5580
					#反之
5581
					else{
5582
 
5583
						#設置尚不能進行認證
5584
						$startAuth=false;
5585
 
5586
						}#else end
5587
 
5588
					}#if end
5589
 
5590
				#如果尚不能進行驗證
5591
				if(!$startAuth){
5592
 
5593
					#結束程式
5594
					return true;
5595
 
5596
					}#if end
5597
 
5598
				#檢查有無符合的帳戶密碼
5599
				#涵式說明:
5600
				#一次取得資料庫、表的資料
5601
				#回傳的結果
5602
				#$result["status"],執行結果"true"為成功;"false"為執行失敗。
5603
				#$result["error"],錯誤訊息陣列。
5604
				#$result["function"],當前執行的漢書名稱.
5605
				#$result["dataColumnName"],抓取的資料欄位名稱陣列.
5606
					#$result["dataColumnName"][$i]代表第$i+1個欄位名稱
5607
				#$result["dataContent"],爲資料的內容。
5608
				#$result["dataContent"][$conf["WhereColumnName"][$i]][$dataSetNum]
5609
					#$dataSetNum 爲第$dataSetNum+1筆資料
5610
					#$conf["WhereColumnName"][$i] 爲第 $i+1 個欄位的名稱
5611
				#$result["dataCount"],爲取得的資料筆數。
5612
				#$result["sql"],執行的sql字串.
5613
				#必填的參數:
5614
				$conf["db::fastGetDbData"]["dbAddress"]=self::$dbAddress;#爲dbServer的位置。
5615
				$conf["db::fastGetDbData"]["dbAccount"]=self::$dbAccount;#爲登入dbServer的帳號。
5616
				$conf["db::fastGetDbData"]["dbName"]=self::$dbName;#爲要存取的資料庫名稱
5617
				$conf["db::fastGetDbData"]["tableName"]=self::$memberTableName;#爲要存取的資料表名稱
5618
				$conf["db::fastGetDbData"]["columnYouWant"]=array("id","password");#你想要的欄位!,若設為「array("*")」則代表全部欄位.
5619
				#可省略的參數:
5620
				$conf["db::fastGetDbData"]["dbPassword"]=self::$dbPassword;#爲要存取dbServer的密碼
5621
				$conf["db::fastGetDbData"]["WhereColumnName"]=array(self::$accountCol);#用於判斷語句的欄位項目陣列。
5622
				$conf["db::fastGetDbData"]["WhereColumnValue"]=array($ac);#用於判斷語句的欄位數值陣列,若與LIKE搭配,則可以在關鍵自字串的左右名加上「%」符號,這樣就可以搜尋具有該字串的內容。
5623
 
5624
				/*
5625
 
5626
				#如果有輸入密碼
5627
				if($pw!==""){
5628
 
5629
					#新增要判斷 self::$password 欄位,是否有於 $pw
5630
					$conf["db::fastGetDbData"]["WhereColumnName"][]=self::$passwordCol;
5631
					$conf["db::fastGetDbData"]["WhereColumnValue"][]=$pw;
5632
 
5633
					}#if end
5634
 
5635
				*/
5636
 
5637
				#$conf["WhereColumnCombine"]=array("");#用於判斷語句當中需要()起來的判斷式,須爲陣列值,"s"代表「(」,"e"代表「)」 ,若無則須設爲""。
5638
				#$conf["WhereColumnOperator"]=array("");#用於判斷語句的比較符號陣列,可以用的符號有「"="、"!="、">"、"<"、"LIKE"、"NOT LIKE"」,預設都爲「=」。
5639
				#$conf["WhereColumnAndOr"]=array("");#用於判斷語句條件之間成立的條件是AND還是OR,須爲陣列值。其數量應爲要判斷的欄位數量減一。
5640
				#$conf["orderItem"]="";#爲排序的項目依據,若要用隨機抽樣,可以用"rand()",可省略。
5641
				#$conf["ascORdesc"]="";#爲要低增還是遞減排序,asc爲遞增;desc爲遞減。
5642
				#$conf["numberStart"]="0";#為從第幾筆開始讀取,預設為0,代筆第一筆。
5643
				$conf["db::fastGetDbData"]["numLimit"]="1";#為要取幾筆資料,可以省略,省略則表示不限制數目。
5644
				#$conf["groupBy"]=array("");#爲要以哪幾個欄爲作爲分羣的依據(欄位相同的數值僅會取出一筆)。
5645
				#備註:
5646
				#建議在查詢資料前,能夠檢查是否每個欄位都存在.
5647
				$fastGetDbData=db::fastGetDbData($conf["db::fastGetDbData"]);
5648
				unset($conf["db::fastGetDbData"]);
5649
 
5650
				#如果取得資料失敗
5651
				if($fastGetDbData["status"]==="false"){
5652
 
5653
					#設置執行失敗
5654
					$result["status"]="false";
5655
 
5656
					#設置執行錯誤訊息
5657
					$result["error"]=$fastGetDbData;
5658
 
5659
					#debug in server
5660
					var_dump($result);
5661
 
5662
					#提示server有資料庫錯誤
5663
					echo "dbError!";
5664
 
5665
					#結束程式
5666
					exit;
5667
 
5668
					}#if end
5669
 
5670
				#如果沒有一筆資料
5671
				if($fastGetDbData["dataCount"]!==1){
5672
 
5673
					#代表登入失敗
5674
 
5675
					#清空登入用的帳戶
5676
					$this->connInfo[$from->resourceId]["login"]["ac"]="";
5677
 
5678
					#清空登入用的密碼
5679
					$this->connInfo[$from->resourceId]["login"]["pw"]="";
5680
 
5681
					#包裝訊息
5682
					#"type"為"login"	
5683
					#"status"為"false"		
5684
					#"data"為實際的訊息內容
5685
					$packedMsg=array("type"=>"login","status"=>"false","data"=>"Login failed, please input account. ex:account:ws1");
5686
 
5687
					#提示登入失敗					
5688
					$from->send(json_encode($packedMsg));
5689
 
5690
					#執行到這即可
5691
					return true;
5692
 
5693
					}#if end
5694
 
5695
				#反之代表帳戶資訊正確
5696
				else{
5697
					#驗證密碼是否正確.
5698
					#函式說明:
5699
					#加密字串,可以用的方法有sha1,md5,password_sha,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
5700
					#回傳結果:
5701
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
5702
					#$result["function"],當前執行的函數名稱.
5703
					#$result["content"],加密後的結果.
5704
					#$result["error"],錯誤訊息陣列.
5705
					#$result["argu"],使用的參數.
5706
					#必填參數:
5707
					#$conf["enCodeStr"],"字串",要加密的字串.
5708
					$conf["authenticate::enCodeStr"]["enCodeStr"]=$pw;
5709
					#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"3種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密.
5710
					$conf["authenticate::enCodeStr"]["enCodeType"]="p_hash";
5711
					#可省略參數:
5712
					#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
5713
					#$conf["sha1Raw"]="false";
5714
					#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
5715
					$conf["authenticate::enCodeStr"]["p_hash"]=$fastGetDbData["dataContent"]["password"][0];
5716
					#參考資料來源:
5717
					#sha1=>http://php.net/manual/en/function.sha1.php
5718
					#md5=>http://php.net/manual/en/function.md5.php
5719
					#password_hash=>http://php.net/manual/en/function.password-hash.php
5720
					#password_verify=>http://php.net/manual/en/function.password-verify.php
5721
					$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
5722
					unset($conf["authenticate::enCodeStr"]);
5723
 
5724
					#如果加密密碼失敗
5725
					if($enCodeStr["status"]==="false"){
5726
 
5727
						#debug from server
5728
						var_dump($enCodeStr);
5729
 
5730
						#提示server有資料庫錯誤
5731
						echo "password verify error!";
5732
 
5733
						#代表登入失敗
5734
 
5735
						#清空登入用的帳戶
5736
						$this->connInfo[$from->resourceId]["login"]["ac"]="";
5737
 
5738
						#清空登入用的密碼
5739
						$this->connInfo[$from->resourceId]["login"]["pw"]="";
5740
 
5741
						#包裝訊息
5742
						#"type"為"login"	
5743
						#"status"為"false"		
5744
						#"data"為實際的訊息內容
5745
						$packedMsg=array("type"=>"login","status"=>"false","data"=>"Login failed, please input account. ex:account:ws1");
5746
 
5747
						#提示登入失敗					
5748
						$from->send(json_encode($packedMsg));
5749
 
5750
						#執行到這即可
5751
						return true;
5752
 
5753
						}#if end
5754
 
5755
					#反之認證成功
5756
					else{
5757
 
5758
						#debug for server
5759
						echo "new login:".PHP_EOL;
5760
						var_dump($enCodeStr);
5761
 
5762
						}#else end
5763
 
5764
					#設置 $myUserId
5765
					$myUserId=$this->connInfo[$from->resourceId]["userId"]=$fastGetDbData["dataContent"]["id"][0];
5766
 
5767
					#設置 $myId
5768
					$myId=$from->resourceId;
5769
 
5770
					#包裝訊息
5771
					#"type"為"login"	
5772
					#"status"為"true"		
5773
					#"data"為實際的訊息內容
5774
					$packedMsg=array("type"=>"login","status"=>"true","data"=>"Login successfully!");
5775
 
5776
					#提示登入成功
5777
					$from->send(json_encode($packedMsg));
5778
 
5779
					#結束認證成功後的流程
5780
					return true;
5781
 
5782
					}#else end
5783
 
5784
				}#else end
5785
 
5786
			#結束認證流程
5787
			return true;	
5788
 
5789
			}#if end
5790
 
5791
		#如果server收到訊息長度大於 "cmd:"
5792
		if(strlen($msg)>strlen("cmd:")){
5793
 
5794
			#如果$msg開頭為"cmd:"  
5795
			#涵式說明:
5796
			#取得符合特定字首與字尾的字串
5797
			#回傳的結果:
5798
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
5799
			#$result["function"],當前執行的函數名稱.
5800
			#$result["error"],錯誤訊息陣列.
5801
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
5802
			#$result["returnString"],爲符合字首條件的字串內容。
5803
			#必填參數:
5804
			#$conf["checkString"],字串,要檢查的字串.
5805
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
5806
			#可省略參數:
5807
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
5808
			$conf["search::getMeetConditionsString"]["frontWord"]="cmd:";
5809
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
5810
			#$conf["tailWord"]="";
5811
			#參考資料:
5812
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
5813
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
5814
			unset($conf["search::getMeetConditionsString"]);
5815
 
5816
			#如果選找前置字串 "cmd:" 失敗
5817
			if($getMeetConditionsString["status"]==="false"){
5818
 
5819
				#設置執行失敗
5820
				$result["status"]="false";
5821
 
5822
				#設置執行錯誤訊息
5823
				$result["error"]=$getMeetConditionsString;
5824
 
5825
				#回傳結果
5826
				return $result;
5827
 
5828
				}#if end
5829
 
5830
			#如果存在 "cmd:" 前置字串
5831
			if($getMeetConditionsString["founded"]==="true"){
5832
 
5833
				#用 "talkTo:" 分割 $buf
5834
				#涵式說明:
5835
				#將固定格式的字串分開,並回傳分開的結果。
5836
				#回傳結果:
5837
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
5838
				#$result["error"],錯誤訊息陣列
5839
				#$result["function"],當前執行的函數名稱.
5840
				#$result["oriStr"],要分割的原始字串內容
5841
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
5842
				#$result["dataCounts"],爲總共分成幾段
5843
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
5844
				#必填的參數:
5845
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
5846
				$conf["stringProcess::spiltString"]["spiltSymbol"]="cmd:";#爲以哪個符號作爲分割
5847
				#可省略參數:
5848
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
5849
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
5850
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
5851
				unset($conf["stringProcess::spiltString"]);
5852
 
5853
				#如果分割字串失敗
5854
				if($spiltString["status"]==="false"){
5855
 
5856
					#設置執行失敗
5857
					$result["status"]="false";
5858
 
5859
					#設置執行錯誤訊息
5860
					$result["error"]=$spiltString;
5861
 
5862
					#回傳結果
5863
					return $result;
5864
 
5865
					}#if end
5866
 
5867
				#如果剛好分割出一筆資料
5868
				if($spiltString["dataCounts"]===1){
5869
 
5870
					#取的要執行的指令
5871
					$cmd=$spiltString["dataArray"][0];
5872
 
5873
					#函式說明:
5874
					#呼叫shell執行系統命令,並取得回傳的內容.
5875
					#回傳的結果:
5876
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
5877
					#$result["error"],錯誤訊息陣列.
5878
					#$result["function"],當前執行的函數名稱.
5879
					#$result["cmd"],執行的指令內容.
5880
					#$result["output"],爲執行完二元碼後的輸出陣列.
5881
					#必填的參數
5882
					#$conf["command"],字串,要執行的指令與.
5883
					$conf["external::callShell"]["command"]=$cmd;
5884
					#$conf["fileArgu"],字串,變數__FILE__的內容.
5885
					$conf["external::callShell"]["fileArgu"]=self::$fileArgu;		
5886
					#可省略參數:
5887
					#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
5888
					#$conf["argu"]=array("");
5889
					#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
5890
					#$conf["arguIsAddr"]=array();
5891
					#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
5892
					#$conf["enablePrintDescription"]="true";
5893
					#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容.
5894
					#$conf["printDescription"]="";
5895
					#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
5896
					$conf["external::callShell"]["escapeshellarg"]="true";
5897
					#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
5898
					#$conf["username"]="";
5899
					#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
5900
					#$conf["password"]="";
5901
					#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要;"false"代表不要,預設為"false".
5902
					#$conf["useScript"]="";
5903
					#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 ".qbpwcf_tmp/external/callShell/".
5904
					#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
5905
					#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
5906
					#$conf["inBackGround"]="";
5907
					#備註:
5908
					#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
5909
					#參考資料:
5910
					#exec=>http://php.net/manual/en/function.exec.php
5911
					#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
5912
					#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
5913
					$callShell=external::callShell($conf["external::callShell"]);
5914
					unset($conf["external::callShell"]);
5915
 
5916
					#如果執行外部指令失敗
5917
					if($callShell["status"]==="false"){
5918
 
5919
						#設置執行失敗
5920
						$result["status"]="false";
5921
 
5922
						#設置執行錯誤訊息
5923
						$result["error"]=$callShell;
5924
 
5925
						#回傳結果
5926
						return $result;
5927
 
5928
						}#if end
5929
 
5930
					#設置要傳給client的訊息
5931
					$result=array("data"=>$callShell["output"],"type"=>"cmd");
5932
 
5933
					#將程式執行後的輸出傳給client					
5934
					$from->send(json_encode($result));
5935
 
5936
					}#if end
5937
 
5938
				}#if end
5939
 
5940
			}#if end
5941
 
5942
		#如果server收到訊息長度大於 "sql:"
5943
		if(strlen($msg)>strlen("sql:")){
5944
 
5945
			#如果$msg開頭為"sql:"  
5946
			#涵式說明:
5947
			#取得符合特定字首與字尾的字串
5948
			#回傳的結果:
5949
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
5950
			#$result["function"],當前執行的函數名稱.
5951
			#$result["error"],錯誤訊息陣列.
5952
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
5953
			#$result["returnString"],爲符合字首條件的字串內容。
5954
			#必填參數:
5955
			#$conf["checkString"],字串,要檢查的字串.
5956
			$conf["search::getMeetConditionsString"]["checkString"]=$msg;
5957
			#可省略參數:
5958
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
5959
			$conf["search::getMeetConditionsString"]["frontWord"]="sql:";
5960
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
5961
			#$conf["tailWord"]="";
5962
			#參考資料:
5963
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
5964
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
5965
			unset($conf["search::getMeetConditionsString"]);
5966
 
5967
			#如果選找前置字串 "sql:" 失敗
5968
			if($getMeetConditionsString["status"]==="false"){
5969
 
5970
				#設置執行失敗
5971
				$result["status"]="false";
5972
 
5973
				#設置執行錯誤訊息
5974
				$result["error"]=$getMeetConditionsString;
5975
 
5976
				#回傳結果
5977
				return $result;
5978
 
5979
				}#if end
5980
 
5981
			#如果存在 "sql:" 前置字串
5982
			if($getMeetConditionsString["founded"]==="true"){
5983
 
5984
				#用 "talkTo:" 分割 $buf
5985
				#涵式說明:
5986
				#將固定格式的字串分開,並回傳分開的結果。
5987
				#回傳結果:
5988
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
5989
				#$result["error"],錯誤訊息陣列
5990
				#$result["function"],當前執行的函數名稱.
5991
				#$result["oriStr"],要分割的原始字串內容
5992
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
5993
				#$result["dataCounts"],爲總共分成幾段
5994
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
5995
				#必填的參數:
5996
				$conf["stringProcess::spiltString"]["stringIn"]=$msg;#要處理的字串。
5997
				$conf["stringProcess::spiltString"]["spiltSymbol"]="sql:";#爲以哪個符號作爲分割
5998
				#可省略參數:
5999
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
6000
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
6001
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
6002
				unset($conf["stringProcess::spiltString"]);
6003
 
6004
				#如果分割字串失敗
6005
				if($spiltString["status"]==="false"){
6006
 
6007
					#設置執行失敗
6008
					$result["status"]="false";
6009
 
6010
					#設置執行錯誤訊息
6011
					$result["error"]=$spiltString;
6012
 
6013
					#回傳結果
6014
					return $result;
6015
 
6016
					}#if end
6017
 
6018
				#如果剛好分割出一筆資料
6019
				if($spiltString["dataCounts"]===1){
6020
 
6021
					#取的要執行的sql指令
6022
					$sql=$spiltString["dataArray"][0];
6023
 
6024
					#建立要執行的指令
6025
					#$cmd="echo \"".$sql."\" | mysql -u".self::$dbAccount." -p".self::$dbPassword;
6026
 
6027
					#函式說明:
6028
					#呼叫shell執行系統命令,並取得回傳的內容.
6029
					#回傳的結果:
6030
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6031
					#$result["error"],錯誤訊息陣列.
6032
					#$result["function"],當前執行的函數名稱.
6033
					#$result["cmd"],執行的指令內容.
6034
					#$result["output"],爲執行完二元碼後的輸出陣列.
6035
					#必填的參數
6036
					#$conf["command"],字串,要執行的指令與.
6037
					$conf["external::callShell"]["command"]="echo";
6038
					#$conf["fileArgu"],字串,變數__FILE__的內容.
6039
					$conf["external::callShell"]["fileArgu"]=self::$fileArgu;		
6040
					#可省略參數:
6041
					#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
6042
					$conf["external::callShell"]["argu"]=array($sql,"|","mysql","-u".self::$dbAccount,"-p".self::$dbPassword);
6043
					#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
6044
					#$conf["arguIsAddr"]=array();
6045
					#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
6046
					#$conf["enablePrintDescription"]="true";
6047
					#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容.
6048
					#$conf["printDescription"]="";
6049
					#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
6050
					$conf["external::callShell"]["escapeshellarg"]="true";
6051
					#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
6052
					#$conf["username"]="";
6053
					#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
6054
					#$conf["password"]="";
6055
					#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要;"false"代表不要,預設為"false".
6056
					#$conf["useScript"]="";
6057
					#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 ".qbpwcf_tmp/external/callShell/".
6058
					#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
6059
					#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
6060
					#$conf["inBackGround"]="";
6061
					#備註:
6062
					#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
6063
					#參考資料:
6064
					#exec=>http://php.net/manual/en/function.exec.php
6065
					#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
6066
					#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
6067
					$callShell=external::callShell($conf["external::callShell"]);
6068
					unset($conf["external::callShell"]);
6069
 
6070
					#如果執行外部指令失敗
6071
					if($callShell["status"]==="false"){
6072
 
6073
						#設置執行失敗
6074
						$result["status"]="false";
6075
 
6076
						#設置執行錯誤訊息
6077
						$result["error"]=$callShell;
6078
 
6079
						#回傳結果
6080
						return $result;
6081
 
6082
						}#if end
6083
 
6084
					#設置要傳給client的訊息
6085
					$result=array("data"=>$callShell["output"],"type"=>"sql");
6086
 
6087
					#將程式執行後的輸出傳給client					
6088
					$from->send(json_encode($result));
6089
 
6090
					}#if end
6091
 
6092
				}#if end
6093
 
6094
			}#if end	
6095
 
6096
		}#function onMessage end
6097
 
6098
	#建構子
6099
	function __construct(){
6100
 
6101
		#實做 SplObjectStorage
6102
		$this->clients = new \SplObjectStorage;
6103
 
6104
		}#function __construct end
6105
 
6106
	#在clinet的連線斷掉前
6107
    	public function onClose(ConnectionInterface $conn){
6108
 
6109
		// The connection is closed, remove it, as we can no longer send it messages
6110
        $this->clients->detach($conn);
6111
 
6112
        echo "Connection {$conn->resourceId} has disconnected\n";
6113
 
6114
		#移除連線的資訊
6115
		unset($this->connInfo[$conn->resourceId]);
6116
 
6117
		}#function onClose end
6118
 
6119
	#當出現錯誤時
6120
    	public function onError(ConnectionInterface $conn, \Exception $e){
6121
 
6122
		#印出錯誤訊息
6123
		echo "An error has occurred: {$e->getMessage()}\n";
6124
 
6125
		#關閉與client的socket
6126
        	$conn->close();
6127
 
6128
		}#fucntion onError end
6129
 
6130
	}#class soldier end 
6131
 
6132
#使用 Ratchet\Server\IoServer 類別
6133
use Ratchet\Server\IoServer;
6134
 
6135
#使用 Ratchet\WebSocket\WsServer 類別
6136
use Ratchet\WebSocket\WsServer;
6137
 
6138
#使用 Ratchet\Http\HttpServer類別
6139
use Ratchet\Http\HttpServer;
6140
 
6141
/*
6142
類別說明:
6143
跟webSocket應用相關的類別.
6144
備註:
6145
無.
6146
*/
6147
class webSock{ 
6148
 
6149
	/*
6150
	#函式說明:
6151
	#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.
6152
	#回傳結果:
6153
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6154
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
6155
	#$result["function"],當前執行的函式名稱.
6156
	#必填參數:
6157
	#$method,物件,為物件實體或類別名稱,會自動置入該參數.
6158
	#$arguments,陣列,為呼叫方法時所用的參數.
6159
	#參考資料:
6160
	#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
6161
	*/
6162
	public function __call($method,$arguments){
6163
 
6164
		#取得當前執行的函式
6165
		$result["function"]=__FUNCTION__;
6166
 
6167
		#設置執行不正常
6168
		$result["status"]="false";
6169
 
6170
		#設置執行錯誤
6171
		$result["error"][]=__NAMESPACE__ ."/".$method."() 不存在!";
6172
 
6173
		#設置所丟入的參數
6174
		$result["error"][]=$arguments;
6175
 
6176
		#回傳結果
6177
		return $result;
6178
 
6179
		}#function __call end
6180
 
6181
	/*
6182
	#函式說明:
6183
	#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.
6184
	#回傳結果:
6185
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6186
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
6187
	#$result["function"],當前執行的函式名稱.
6188
	#必填參數:
6189
	#$method,物件,為物件實體或類別名稱,會自動置入該參數.
6190
	#$arguments,陣列,為呼叫方法時所用的參數.
6191
	#參考資料:
6192
	#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic
6193
	*/
6194
	public static function __callStatic($method,$arguments){
6195
 
6196
		#取得當前執行的函式
6197
		$result["function"]=__FUNCTION__;
6198
 
6199
		#設置執行不正常
6200
		$result["status"]="false";
6201
 
6202
		#設置執行錯誤
6203
		$result["error"][]="欲呼叫的". __NAMESPACE__ ."/".$method."() 不存在!";
6204
 
6205
		#設置所丟入的參數
6206
		$result["error"][]=$arguments;
6207
 
6208
		#回傳結果
6209
		return $result;
6210
 
6211
		}#function __callStatic end
6212
 
6213
	/*
6214
	#函式說明:
6215
	#擴充過的Ratchet的聊天室用戶端與伺服端範例,port為8080.
6216
	#回傳結果:
6217
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6218
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
6219
	#$result["function"],當前執行的函式名稱.		
6220
	#必填參數:
6221
	#$conf["fileArgu"],字串,__FILE__的內容.
6222
	$conf["fileArgu"]=__FILE__;
6223
	#可省略參數:
6224
	#$conf["disReg"],字串,是否要取消apache的passProxy檢查與設定,預設為"false"不取消,"true"為取消.
6225
	#$conf["disReg"]="";
6226
	#參考資料:
6227
	#Ratchet官網=>http://socketo.me/
6228
	#聊天室範例=>http://socketo.me/docs/hello-world
6229
	#備註:
6230
	#必須要在命令列環境下執行一次,建立webSocket Server後,再於網頁端執行即可產生webSocket Client端的code.
6231
	#僅適用於https網頁透過wss連線到web socket server.
6232
	*/
6233
	public static function chatRoomDemo(&$conf){
6234
 
6235
		#初始化要回傳的結果
6236
		$result=array();
6237
 
6238
		#取得當前執行的函數名稱
6239
		$result["function"]=__FUNCTION__;
6240
 
6241
		#涵式說明:
6242
		#判斷當前環境為web還是cmd
6243
		#回傳結果:
6244
		#$result,"web"或"cmd"
6245
		if(csInformation::getEnv()==="web"){
6246
 
6247
			#建立 web socket client 的 js 語法
6248
			#函式說明:
6249
			#聊天室用戶端js範例
6250
			#回傳結果:
6251
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6252
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
6253
			#$result["function"],當前執行的函式名稱.		
6254
			#$result["content"],js語法.
6255
			#參考資料:
6256
			#Ratchet官網=>http://socketo.me/
6257
			#聊天室範例=>http://socketo.me/docs/hello-world
6258
			$chatRoomClientDemo=webSock::chatRoomClientDemo();
6259
 
6260
			#如果建立聊天室用戶端失敗
6261
			if($chatRoomClientDemo["status"]==="false"){
6262
 
6263
				#設置執行失敗
6264
				$result["status"]="false";
6265
 
6266
				#設置執行錯誤訊息
6267
				$result["error"]=$chatRoomClientDemo;
6268
 
6269
				#回傳結果
6270
				return $result;
6271
 
6272
				}#if end
6273
 
6274
			#取得聊天室的語法
6275
			$result["content"]=$chatRoomClientDemo["content"];
6276
 
6277
			#設置執行正常
6278
			$result["status"]="true";
6279
 
6280
			#回傳結果
6281
			return $result;
6282
 
6283
			}#if end
6284
 
6285
		#如果沒有參數
6286
		if(func_num_args()==0){
6287
 
6288
			#設置執行失敗
6289
			$result["status"]="false";
6290
 
6291
			#設置執行錯誤訊息
6292
			$result["error"]="函數".$result["function"]."需要參數";
6293
 
6294
			#回傳結果
6295
			return $result;
6296
 
6297
			}#if end
6298
 
6299
		#如果沒有參數
6300
		if(func_num_args()==0){
6301
 
6302
			#設置執行失敗
6303
			$result["status"]="false";
6304
 
6305
			#設置執行錯誤訊息
6306
			$result["error"]="函數".$result["function"]."需要參數";
6307
 
6308
			#回傳結果
6309
			return $result;
6310
 
6311
			}#if end
6312
 
6313
		#取得參數
6314
		$result["argu"]=$conf;
6315
 
6316
		#如果 $conf 不為陣列
6317
		if(gettype($conf)!=="array"){
6318
 
6319
			#設置執行失敗
6320
			$result["status"]="false";
6321
 
6322
			#設置執行錯誤訊息
6323
			$result["error"][]="\$conf變數須為陣列形態";
6324
 
6325
			#如果傳入的參數為 null
6326
			if($conf===null){
6327
 
6328
				#設置執行錯誤訊息
6329
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
6330
 
6331
				}#if end
6332
 
6333
			#回傳結果
6334
			return $result;
6335
 
6336
			}#if end
6337
 
6338
		#檢查參數
6339
		#函式說明:
6340
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
6341
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6342
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
6343
		#$result["function"],當前執行的函式名稱.
6344
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
6345
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
6346
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
6347
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
6348
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
6349
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
6350
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
6351
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
6352
		#必填寫的參數:
6353
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
6354
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
6355
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
6356
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
6357
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
6358
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
6359
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
6360
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
6361
		#可以省略的參數:
6362
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
6363
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
6364
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
6365
		#$conf["canNotBeEmpty"]=array();
6366
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
6367
		#$conf["canBeEmpty"]=array();
6368
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
6369
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
6370
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
6371
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("disReg");
6372
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
6373
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
6374
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
6375
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false");
6376
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
6377
		#$conf["arrayCountEqualCheck"][]=array();
6378
		#參考資料來源:
6379
		#array_keys=>http://php.net/manual/en/function.array-keys.php
6380
		#建議:
6381
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
6382
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
6383
		unset($conf["variableCheck::checkArguments"]);
6384
 
6385
		#如果檢查參數失敗
6386
		if($checkArguments["status"]==="false"){
6387
 
6388
			#設置執行失敗
6389
			$result["status"]="false";
6390
 
6391
			#設置執行錯誤訊息
6392
			$result["error"]=$checkArguments;
6393
 
6394
			#回傳結果
6395
			return $result;
6396
 
6397
			}#if end
6398
 
6399
		#如果參數檢查不通過
6400
		if($checkArguments["passed"]==="false"){
6401
 
6402
			#設置執行失敗
6403
			$result["status"]="false";
6404
 
6405
			#設置執行錯誤訊息
6406
			$result["error"]=$checkArguments;
6407
 
6408
			#回傳結果
6409
			return $result;
6410
 
6411
			}#if end
6412
 
6413
		#執行到這邊代表是命令列環境
6414
 
6415
		#如果沒有要取消設定 passProxy
6416
		if($conf["disReg"]==="false"){
6417
 
6418
			#確認設定 passProxy
6419
			#函式說明:
6420
			#註冊聊天室範例的 passProxy 設定,本函數會用root帳戶去新增.
6421
			#會在 /etc/httpd/conf/httpd.conf 檔案裡面加上以下內容
6422
			##Enable the mod_proxy modules in the HTTPD
6423
			#LoadModule proxy_module modules/mod_proxy.so
6424
			#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
6425
			#
6426
			##ProxyPass
6427
			##If requeted web address is begin with (ws://hostdns)/wss/chatDemo, then redirect to ws://localhost:8080
6428
			#ProxyPass /wss/chatDemo ws://localhost:8080
6429
			#回傳結果:
6430
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6431
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
6432
			#$result["function"],當前執行的函式名稱.
6433
			#必填參數:
6434
			#$conf["fileArgu"],字串,__FILE__的內容.
6435
			$conf["webSock::registerChatDemo"]["fileArgu"]=$conf["fileArgu"];
6436
			#可省略參數:
6437
			#$conf["rootPasswd"],字串,root帳戶的密碼,預設為"password".
6438
			#$conf["rootPasswd"]="password";
6439
			#$conf["httpd.conf"],字串,apache設定檔的路徑與名稱,預設為"/etc/httpd/conf/httpd.conf".
6440
			#$conf["httpd.conf"]="/etc/httpd/conf/httpd.conf";		
6441
			#備註:
6442
			#僅能在命令列環境下執行.
6443
			#改變暫存檔案權限的功能異常.
6444
			#參考資料:
6445
			#用apache的passProxy來識別服務並轉到正確的port=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
6446
			$registerChatDemo=webSock::registerChatDemo($conf["webSock::registerChatDemo"]);
6447
			unset($conf["webSock::registerChatDemo"]);
6448
 
6449
			#如果註冊 ChatDemo 服務失敗
6450
			if($registerChatDemo["status"]==="false"){
6451
 
6452
				#設置執行失敗
6453
				$result["status"]="false";
6454
 
6455
				#設置執行錯誤訊息
6456
				$result["error"]=$registerChatDemo;
6457
 
6458
				#回傳結果
6459
				return $result;
6460
 
6461
				}#if end
6462
 
6463
			}#if end
6464
 
6465
		#函式說明:
6466
		#擴充過的Ratchet聊天室伺服端範例,port為8080.
6467
		#回傳結果:
6468
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6469
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
6470
		#$result["function"],當前執行的函式名稱.		
6471
		#參考資料:
6472
		#Ratchet官網=>http://socketo.me/
6473
		#聊天室範例=>http://socketo.me/docs/hello-world
6474
		#備註:
6475
		#必須要在命令列環境下執行才行.
6476
		$chatRoomServerDemo=self::chatRoomServerDemo();
6477
 
6478
		#如果運行 chatRoomServerDemo 失敗
6479
		if($chatRoomServerDemo["status"]==="false"){
6480
 
6481
			#設置執行失敗
6482
			$result["status"]="false";
6483
 
6484
			#設置執行錯誤訊息
6485
			$result["error"]=$chatRoomServerDemo;
6486
 
6487
			#回傳結果
6488
			return $result;
6489
 
6490
			}#if end	
6491
 
6492
		#設置執行正常
6493
		$result["status"]="true";
6494
 
6495
		#回傳結果	
6496
		return $result;
6497
 
6498
		}#function chatRoomDemo end
6499
 
6500
	/*
6501
	#函式說明:
6502
	#擴充過的Ratchet的聊天室用戶端與伺服端範例第二版,port為8080.
6503
	#回傳結果:
6504
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6505
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
6506
	#$result["function"],當前執行的函式名稱.		
6507
	#必填參數:
6508
	#$conf["fileArgu"],字串,__FILE__的內容.
6509
	$conf["fileArgu"]=__FILE__;
6510
	#可省略參數:
6511
	#$conf["disReg"],字串,是否要取消apache的passProxy檢查與設定,預設為"false"不取消,"true"為取消.
6512
	#$conf["disReg"]="";
6513
	#參考資料:
6514
	#Ratchet官網=>http://socketo.me/
6515
	#聊天室範例=>http://socketo.me/docs/hello-world
6516
	#備註:
6517
	#必須要在命令列環境下執行一次,建立webSocket Server後,再於網頁端執行即可產生webSocket Client端的code.
6518
	#僅適用於https網頁透過wss連線到web socket server.
6519
	*/
6520
	public static function chatRoomDemoV2(&$conf){
6521
 
6522
		#初始化要回傳的結果
6523
		$result=array();
6524
 
6525
		#取得當前執行的函數名稱
6526
		$result["function"]=__FUNCTION__;
6527
 
6528
		#涵式說明:
6529
		#判斷當前環境為web還是cmd
6530
		#回傳結果:
6531
		#$result,"web"或"cmd"
6532
		if(csInformation::getEnv()==="web"){
6533
 
6534
			#建立 web socket client 的 js 語法
6535
			#函式說明:
6536
			#聊天室用戶端js範例
6537
			#回傳結果:
6538
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6539
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
6540
			#$result["function"],當前執行的函式名稱.		
6541
			#$result["content"],js語法.
6542
			#參考資料:
6543
			#Ratchet官網=>http://socketo.me/
6544
			#聊天室範例=>http://socketo.me/docs/hello-world
6545
			$chatRoomClientDemo=webSock::chatRoomClientDemoV2();
6546
 
6547
			#如果建立聊天室用戶端失敗
6548
			if($chatRoomClientDemo["status"]==="false"){
6549
 
6550
				#設置執行失敗
6551
				$result["status"]="false";
6552
 
6553
				#設置執行錯誤訊息
6554
				$result["error"]=$chatRoomClientDemo;
6555
 
6556
				#回傳結果
6557
				return $result;
6558
 
6559
				}#if end
6560
 
6561
			#取得聊天室的語法
6562
			$result["content"]=$chatRoomClientDemo["content"];
6563
 
6564
			#設置執行正常
6565
			$result["status"]="true";
6566
 
6567
			#回傳結果
6568
			return $result;
6569
 
6570
			}#if end
6571
 
6572
		#如果沒有參數
6573
		if(func_num_args()==0){
6574
 
6575
			#設置執行失敗
6576
			$result["status"]="false";
6577
 
6578
			#設置執行錯誤訊息
6579
			$result["error"]="函數".$result["function"]."需要參數";
6580
 
6581
			#回傳結果
6582
			return $result;
6583
 
6584
			}#if end
6585
 
6586
		#如果沒有參數
6587
		if(func_num_args()==0){
6588
 
6589
			#設置執行失敗
6590
			$result["status"]="false";
6591
 
6592
			#設置執行錯誤訊息
6593
			$result["error"]="函數".$result["function"]."需要參數";
6594
 
6595
			#回傳結果
6596
			return $result;
6597
 
6598
			}#if end
6599
 
6600
		#取得參數
6601
		$result["argu"]=$conf;
6602
 
6603
		#如果 $conf 不為陣列
6604
		if(gettype($conf)!=="array"){
6605
 
6606
			#設置執行失敗
6607
			$result["status"]="false";
6608
 
6609
			#設置執行錯誤訊息
6610
			$result["error"][]="\$conf變數須為陣列形態";
6611
 
6612
			#如果傳入的參數為 null
6613
			if($conf===null){
6614
 
6615
				#設置執行錯誤訊息
6616
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
6617
 
6618
				}#if end
6619
 
6620
			#回傳結果
6621
			return $result;
6622
 
6623
			}#if end
6624
 
6625
		#檢查參數
6626
		#函式說明:
6627
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
6628
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6629
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
6630
		#$result["function"],當前執行的函式名稱.
6631
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
6632
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
6633
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
6634
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
6635
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
6636
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
6637
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
6638
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
6639
		#必填寫的參數:
6640
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
6641
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
6642
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
6643
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
6644
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
6645
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
6646
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
6647
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
6648
		#可以省略的參數:
6649
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
6650
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
6651
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
6652
		#$conf["canNotBeEmpty"]=array();
6653
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
6654
		#$conf["canBeEmpty"]=array();
6655
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
6656
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
6657
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
6658
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("disReg");
6659
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
6660
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
6661
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
6662
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false");
6663
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
6664
		#$conf["arrayCountEqualCheck"][]=array();
6665
		#參考資料來源:
6666
		#array_keys=>http://php.net/manual/en/function.array-keys.php
6667
		#建議:
6668
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
6669
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
6670
		unset($conf["variableCheck::checkArguments"]);
6671
 
6672
		#如果檢查參數失敗
6673
		if($checkArguments["status"]==="false"){
6674
 
6675
			#設置執行失敗
6676
			$result["status"]="false";
6677
 
6678
			#設置執行錯誤訊息
6679
			$result["error"]=$checkArguments;
6680
 
6681
			#回傳結果
6682
			return $result;
6683
 
6684
			}#if end
6685
 
6686
		#如果參數檢查不通過
6687
		if($checkArguments["passed"]==="false"){
6688
 
6689
			#設置執行失敗
6690
			$result["status"]="false";
6691
 
6692
			#設置執行錯誤訊息
6693
			$result["error"]=$checkArguments;
6694
 
6695
			#回傳結果
6696
			return $result;
6697
 
6698
			}#if end
6699
 
6700
		#執行到這邊代表是命令列環境
6701
 
6702
		#如果沒有要取消設定 passProxy
6703
		if($conf["disReg"]==="false"){
6704
 
6705
			#確認設定 passProxy
6706
			#函式說明:
6707
			#註冊聊天室範例的 passProxy 設定,本函數會用root帳戶去新增.
6708
			#會在 /etc/httpd/conf/httpd.conf 檔案裡面加上以下內容
6709
			##Enable the mod_proxy modules in the HTTPD
6710
			#LoadModule proxy_module modules/mod_proxy.so
6711
			#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
6712
			#
6713
			##ProxyPass
6714
			##If requeted web address is begin with (ws://hostdns)/wss/chatDemo, then redirect to ws://localhost:8080
6715
			#ProxyPass /wss/chatDemo ws://localhost:8080
6716
			#回傳結果:
6717
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6718
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
6719
			#$result["function"],當前執行的函式名稱.
6720
			#必填參數:
6721
			#$conf["fileArgu"],字串,__FILE__的內容.
6722
			$conf["webSock::registerChatDemo"]["fileArgu"]=$conf["fileArgu"];
6723
			#可省略參數:
6724
			#$conf["rootPasswd"],字串,root帳戶的密碼,預設為"password".
6725
			#$conf["rootPasswd"]="password";
6726
			#$conf["httpd.conf"],字串,apache設定檔的路徑與名稱,預設為"/etc/httpd/conf/httpd.conf".
6727
			#$conf["httpd.conf"]="/etc/httpd/conf/httpd.conf";		
6728
			#備註:
6729
			#僅能在命令列環境下執行.
6730
			#改變暫存檔案權限的功能異常.
6731
			#參考資料:
6732
			#用apache的passProxy來識別服務並轉到正確的port=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
6733
			$registerChatDemo=webSock::registerChatDemo($conf["webSock::registerChatDemo"]);
6734
			unset($conf["webSock::registerChatDemo"]);
6735
 
6736
			#如果註冊 ChatDemo 服務失敗
6737
			if($registerChatDemo["status"]==="false"){
6738
 
6739
				#設置執行失敗
6740
				$result["status"]="false";
6741
 
6742
				#設置執行錯誤訊息
6743
				$result["error"]=$registerChatDemo;
6744
 
6745
				#回傳結果
6746
				return $result;
6747
 
6748
				}#if end
6749
 
6750
			}#if end
6751
 
6752
		#函式說明:
6753
		#擴充過的Ratchet聊天室伺服端範例,port為8080.
6754
		#回傳結果:
6755
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6756
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
6757
		#$result["function"],當前執行的函式名稱.		
6758
		#參考資料:
6759
		#Ratchet官網=>http://socketo.me/
6760
		#聊天室範例=>http://socketo.me/docs/hello-world
6761
		#備註:
6762
		#必須要在命令列環境下執行才行.
6763
		$chatRoomServerDemo=self::chatRoomServerDemoV2();
6764
 
6765
		#如果運行 chatRoomServerDemo 失敗
6766
		if($chatRoomServerDemo["status"]==="false"){
6767
 
6768
			#設置執行失敗
6769
			$result["status"]="false";
6770
 
6771
			#設置執行錯誤訊息
6772
			$result["error"]=$chatRoomServerDemo;
6773
 
6774
			#回傳結果
6775
			return $result;
6776
 
6777
			}#if end	
6778
 
6779
		#設置執行正常
6780
		$result["status"]="true";
6781
 
6782
		#回傳結果	
6783
		return $result;
6784
 
6785
		}#function chatRoomDemoV2 end
6786
 
6787
	/*
6788
	#函式說明:
6789
	#擴充過的Ratchet的聊天室用戶端與伺服端範例第二版,port為8080.
6790
	#回傳結果:
6791
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6792
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
6793
	#$result["function"],當前執行的函式名稱.		
6794
	#必填參數:
6795
	#$conf["fileArgu"],字串,__FILE__的內容.
6796
	$conf["fileArgu"]=__FILE__;
6797
	#可省略參數:
6798
	#$conf["disReg"],字串,是否要取消apache的passProxy檢查與設定,預設為"false"不取消,"true"為取消.
6799
	#$conf["disReg"]="";
6800
	#參考資料:
6801
	#Ratchet官網=>http://socketo.me/
6802
	#聊天室範例=>http://socketo.me/docs/hello-world
6803
	#備註:
6804
	#必須要在命令列環境下執行一次,建立webSocket Server後,再於網頁端執行即可產生webSocket Client端的code.
6805
	#僅適用於https網頁透過wss連線到web socket server.
6806
	*/
6807
	public static function chatRoomDemoV3(&$conf=array()){
6808
 
6809
		#初始化要回傳的結果
6810
		$result=array();
6811
 
6812
		#取得當前執行的函數名稱
6813
		$result["function"]=__FUNCTION__;
6814
 
6815
		#涵式說明:
6816
		#判斷當前環境為web還是cmd
6817
		#回傳結果:
6818
		#$result,"web"或"cmd"
6819
		if(csInformation::getEnv()==="web"){
6820
 
6821
			#建立 web socket client 的 js 語法
6822
			#函式說明:
6823
			#聊天室用戶端js範例
6824
			#回傳結果:
6825
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6826
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
6827
			#$result["function"],當前執行的函式名稱.		
6828
			#$result["content"],js語法.
6829
			#參考資料:
6830
			#Ratchet官網=>http://socketo.me/
6831
			#聊天室範例=>http://socketo.me/docs/hello-world
6832
			$chatRoomClientDemo=webSock::chatRoomClientDemoV3();
6833
 
6834
			#如果建立聊天室用戶端失敗
6835
			if($chatRoomClientDemo["status"]==="false"){
6836
 
6837
				#設置執行失敗
6838
				$result["status"]="false";
6839
 
6840
				#設置執行錯誤訊息
6841
				$result["error"]=$chatRoomClientDemo;
6842
 
6843
				#回傳結果
6844
				return $result;
6845
 
6846
				}#if end
6847
 
6848
			#取得聊天室的語法
6849
			$result["content"]=$chatRoomClientDemo["content"];
6850
 
6851
			#設置執行正常
6852
			$result["status"]="true";
6853
 
6854
			#回傳結果
6855
			return $result;
6856
 
6857
			}#if end
6858
 
6859
		#如果沒有參數
6860
		if(func_num_args()==0){
6861
 
6862
			#設置執行失敗
6863
			$result["status"]="false";
6864
 
6865
			#設置執行錯誤訊息
6866
			$result["error"]="函數".$result["function"]."需要參數";
6867
 
6868
			#回傳結果
6869
			return $result;
6870
 
6871
			}#if end
6872
 
6873
		#如果沒有參數
6874
		if(func_num_args()==0){
6875
 
6876
			#設置執行失敗
6877
			$result["status"]="false";
6878
 
6879
			#設置執行錯誤訊息
6880
			$result["error"]="函數".$result["function"]."需要參數";
6881
 
6882
			#回傳結果
6883
			return $result;
6884
 
6885
			}#if end
6886
 
6887
		#取得參數
6888
		$result["argu"]=$conf;
6889
 
6890
		#如果 $conf 不為陣列
6891
		if(gettype($conf)!=="array"){
6892
 
6893
			#設置執行失敗
6894
			$result["status"]="false";
6895
 
6896
			#設置執行錯誤訊息
6897
			$result["error"][]="\$conf變數須為陣列形態";
6898
 
6899
			#如果傳入的參數為 null
6900
			if($conf===null){
6901
 
6902
				#設置執行錯誤訊息
6903
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
6904
 
6905
				}#if end
6906
 
6907
			#回傳結果
6908
			return $result;
6909
 
6910
			}#if end
6911
 
6912
		#檢查參數
6913
		#函式說明:
6914
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
6915
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
6916
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
6917
		#$result["function"],當前執行的函式名稱.
6918
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
6919
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
6920
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
6921
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
6922
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
6923
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
6924
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
6925
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
6926
		#必填寫的參數:
6927
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
6928
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
6929
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
6930
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
6931
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
6932
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
6933
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
6934
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
6935
		#可以省略的參數:
6936
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
6937
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
6938
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
6939
		#$conf["canNotBeEmpty"]=array();
6940
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
6941
		#$conf["canBeEmpty"]=array();
6942
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
6943
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
6944
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
6945
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("disReg");
6946
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
6947
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
6948
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
6949
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false");
6950
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
6951
		#$conf["arrayCountEqualCheck"][]=array();
6952
		#參考資料來源:
6953
		#array_keys=>http://php.net/manual/en/function.array-keys.php
6954
		#建議:
6955
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
6956
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
6957
		unset($conf["variableCheck::checkArguments"]);
6958
 
6959
		#如果檢查參數失敗
6960
		if($checkArguments["status"]==="false"){
6961
 
6962
			#設置執行失敗
6963
			$result["status"]="false";
6964
 
6965
			#設置執行錯誤訊息
6966
			$result["error"]=$checkArguments;
6967
 
6968
			#回傳結果
6969
			return $result;
6970
 
6971
			}#if end
6972
 
6973
		#如果參數檢查不通過
6974
		if($checkArguments["passed"]==="false"){
6975
 
6976
			#設置執行失敗
6977
			$result["status"]="false";
6978
 
6979
			#設置執行錯誤訊息
6980
			$result["error"]=$checkArguments;
6981
 
6982
			#回傳結果
6983
			return $result;
6984
 
6985
			}#if end
6986
 
6987
		#執行到這邊代表是命令列環境
6988
 
6989
		#如果沒有要取消設定 passProxy
6990
		if($conf["disReg"]==="false"){
6991
 
6992
			#確認設定 passProxy
6993
			#函式說明:
6994
			#註冊聊天室範例的 passProxy 設定,本函數會用root帳戶去新增.
6995
			#會在 /etc/httpd/conf/httpd.conf 檔案裡面加上以下內容
6996
			##Enable the mod_proxy modules in the HTTPD
6997
			#LoadModule proxy_module modules/mod_proxy.so
6998
			#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
6999
			#
7000
			##ProxyPass
7001
			##If requeted web address is begin with (ws://hostdns)/wss/chatDemo, then redirect to ws://localhost:8080
7002
			#ProxyPass /wss/chatDemo ws://localhost:8080
7003
			#回傳結果:
7004
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7005
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
7006
			#$result["function"],當前執行的函式名稱.
7007
			#必填參數:
7008
			#$conf["fileArgu"],字串,__FILE__的內容.
7009
			$conf["webSock::registerChatDemo"]["fileArgu"]=$conf["fileArgu"];
7010
			#可省略參數:
7011
			#$conf["rootPasswd"],字串,root帳戶的密碼,預設為"password".
7012
			#$conf["rootPasswd"]="password";
7013
			#$conf["httpd.conf"],字串,apache設定檔的路徑與名稱,預設為"/etc/httpd/conf/httpd.conf".
7014
			#$conf["httpd.conf"]="/etc/httpd/conf/httpd.conf";		
7015
			#備註:
7016
			#僅能在命令列環境下執行.
7017
			#改變暫存檔案權限的功能異常.
7018
			#參考資料:
7019
			#用apache的passProxy來識別服務並轉到正確的port=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
7020
			$registerChatDemo=webSock::registerChatDemo($conf["webSock::registerChatDemo"]);
7021
			unset($conf["webSock::registerChatDemo"]);
7022
 
7023
			#如果註冊 ChatDemo 服務失敗
7024
			if($registerChatDemo["status"]==="false"){
7025
 
7026
				#設置執行失敗
7027
				$result["status"]="false";
7028
 
7029
				#設置執行錯誤訊息
7030
				$result["error"]=$registerChatDemo;
7031
 
7032
				#回傳結果
7033
				return $result;
7034
 
7035
				}#if end
7036
 
7037
			}#if end
7038
 
7039
		#函式說明:
7040
		#擴充過的Ratchet聊天室伺服端範例,port為8080.
7041
		#回傳結果:
7042
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7043
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
7044
		#$result["function"],當前執行的函式名稱.
7045
		#必填參數:
7046
		#$conf["fileArgu"],__FILE__的內容.
7047
		$conf["webSock"]["chatRoomServerDemoV3"]["fileArgu"]=$conf["fileArgu"];		
7048
		#參考資料:
7049
		#Ratchet官網=>http://socketo.me/
7050
		#聊天室範例=>http://socketo.me/docs/hello-world
7051
		#備註:
7052
		#必須要在命令列環境下執行才行.
7053
		$chatRoomServerDemo=self::chatRoomServerDemoV3($conf["webSock"]["chatRoomServerDemoV3"]);
7054
		unset($conf["webSock"]["chatRoomServerDemoV3"]);
7055
 
7056
		#如果運行 chatRoomServerDemo 失敗
7057
		if($chatRoomServerDemo["status"]==="false"){
7058
 
7059
			#設置執行失敗
7060
			$result["status"]="false";
7061
 
7062
			#設置執行錯誤訊息
7063
			$result["error"]=$chatRoomServerDemo;
7064
 
7065
			#回傳結果
7066
			return $result;
7067
 
7068
			}#if end	
7069
 
7070
		#設置執行正常
7071
		$result["status"]="true";
7072
 
7073
		#回傳結果	
7074
		return $result;
7075
 
7076
		}#function chatRoomDemoV3 end
7077
 
7078
	/*
7079
	#函式說明:
7080
	#擴充過的Ratchet聊天室伺服端範例,port為8080.
7081
	#回傳結果:
7082
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7083
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
7084
	#$result["function"],當前執行的函式名稱.		
7085
	#必填參數:
7086
	#無.
7087
	#可省略參數:
7088
	#無.
7089
	#參考資料:
7090
	#Ratchet官網=>http://socketo.me/
7091
	#聊天室範例=>http://socketo.me/docs/hello-world
7092
	#備註:
7093
	#必須要在命令列環境下執行才行.
7094
	*/
7095
	public static function chatRoomServerDemo(){
7096
 
7097
		#初始化要回傳的結果
7098
		$result=array();
7099
 
7100
		#取得當前執行的函數名稱
7101
		$result["function"]=__FUNCTION__;
7102
 
7103
		#如果是在網頁環境
7104
		#涵式說明:
7105
		#判斷當前環境為web還是cmd
7106
		#回傳結果:
7107
		#$result,"web"或"cmd"
7108
		if(csInformation::getEnv()==="web"){
7109
 
7110
			#設置執行失敗
7111
			$result["status"]="false";
7112
 
7113
			#設置執行錯誤訊息
7114
			$result["error"][]="函數". __FUNCTION__ ."僅能在命令列環境下執行!";
7115
 
7116
			#回傳結果
7117
			return $result;
7118
 
7119
			}#if end
7120
 
7121
		#建立 Ratchet 提供的聊天室範例(適用於telnet)
7122
		#It stores all the established connections, mediates data sent between each client and our Chat application, and catches errors. 
7123
		#we tell the server to enter an event loop, listening for any incoming requests on port 8080. 
7124
		#$server = IoServer::factory(new Chat(),8080);
7125
 
7126
		#建立 Ratchet 提供的聊天室範例(適用於用webServer)
7127
		$server = IoServer::factory(
7128
			new HttpServer(
7129
				new WsServer(
7130
					new Chat()
7131
					)
7132
				),
7133
			8080
7134
			);
7135
 
7136
		#執行 server 端程式
7137
		$server->run();
7138
 
7139
		#設置執行正常
7140
		$result["status"]="true";
7141
 
7142
		#回傳結果	
7143
		return $result;
7144
 
7145
		}#function chatRoomServerDemo end
7146
 
7147
	/*
7148
	#函式說明:
7149
	#擴充過的Ratchet聊天室伺服端範例第二版,port為8080.
7150
	#回傳結果:
7151
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7152
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
7153
	#$result["function"],當前執行的函式名稱.		
7154
	#必填參數:
7155
	#無.
7156
	#可省略參數:
7157
	#無.
7158
	#參考資料:
7159
	#Ratchet官網=>http://socketo.me/
7160
	#聊天室範例=>http://socketo.me/docs/hello-world
7161
	#備註:
7162
	#必須要在命令列環境下執行才行.
7163
	*/
7164
	public static function chatRoomServerDemoV2(){
7165
 
7166
		#初始化要回傳的結果
7167
		$result=array();
7168
 
7169
		#取得當前執行的函數名稱
7170
		$result["function"]=__FUNCTION__;
7171
 
7172
		#如果是在網頁環境
7173
		#涵式說明:
7174
		#判斷當前環境為web還是cmd
7175
		#回傳結果:
7176
		#$result,"web"或"cmd"
7177
		if(csInformation::getEnv()==="web"){
7178
 
7179
			#設置執行失敗
7180
			$result["status"]="false";
7181
 
7182
			#設置執行錯誤訊息
7183
			$result["error"][]="函數". __FUNCTION__ ."僅能在命令列環境下執行!";
7184
 
7185
			#回傳結果
7186
			return $result;
7187
 
7188
			}#if end
7189
 
7190
		#建立 Ratchet 提供的聊天室範例(適用於telnet)
7191
		#It stores all the established connections, mediates data sent between each client and our Chat application, and catches errors. 
7192
		#we tell the server to enter an event loop, listening for any incoming requests on port 8080. 
7193
		#$server = IoServer::factory(new Chat(),8080);
7194
 
7195
		#建立 Ratchet 提供的聊天室範例(適用於用webServer)
7196
		$server = IoServer::factory(
7197
			new HttpServer(
7198
				new WsServer(
7199
					new ChatV2()
7200
					)
7201
				),
7202
			8080
7203
			);
7204
 
7205
		#執行 server 端程式
7206
		$server->run();
7207
 
7208
		#設置執行正常
7209
		$result["status"]="true";
7210
 
7211
		#回傳結果	
7212
		return $result;
7213
 
7214
		}#function chatRoomServerDemoV2 end	
7215
 
7216
	/*
7217
	#函式說明:
7218
	#擴充過的Ratchet聊天室伺服端範例第三版,port為8080.
7219
	#回傳結果:
7220
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7221
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
7222
	#$result["function"],當前執行的函式名稱.		
7223
	#必填參數:
7224
	#$conf["fileArgu"],__FILE__的內容.
7225
	$conf["fileArgu"]=__FILE__;
7226
	#可省略參數:
7227
	#無.
7228
	#參考資料:
7229
	#Ratchet官網=>http://socketo.me/
7230
	#聊天室範例=>http://socketo.me/docs/hello-world
7231
	#備註:
7232
	#必須要在命令列環境下執行才行.
7233
	*/
7234
	public static function chatRoomServerDemoV3(&$conf=array()){
7235
 
7236
		#初始化要回傳的結果
7237
		$result=array();
7238
 
7239
		#取得當前執行的函數名稱
7240
		$result["function"]=__FUNCTION__;
7241
 
7242
		#如果沒有參數
7243
		if(func_num_args()==0){
7244
 
7245
			#設置執行失敗
7246
			$result["status"]="false";
7247
 
7248
			#設置執行錯誤訊息
7249
			$result["error"]="函數".$result["function"]."需要參數";
7250
 
7251
			#回傳結果
7252
			return $result;
7253
 
7254
			}#if end
7255
 
7256
		#涵式說明:
7257
		#判斷當前環境為web還是cmd
7258
		#回傳結果:
7259
		#$result,"web"或"cmd"
7260
		if(csInformation::getEnv()==="web"){
7261
 
7262
			#設置執行失敗
7263
			$result["status"]="false";
7264
 
7265
			#設置執行錯誤訊息
7266
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
7267
 
7268
			#回傳結果
7269
			return $result;
7270
 
7271
			}#if end
7272
 
7273
		#取得參數
7274
		$result["argu"]=$conf;
7275
 
7276
		#如果 $conf 不為陣列
7277
		if(gettype($conf)!=="array"){
7278
 
7279
			#設置執行失敗
7280
			$result["status"]="false";
7281
 
7282
			#設置執行錯誤訊息
7283
			$result["error"][]="\$conf變數須為陣列形態";
7284
 
7285
			#如果傳入的參數為 null
7286
			if($conf===null){
7287
 
7288
				#設置執行錯誤訊息
7289
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
7290
 
7291
				}#if end
7292
 
7293
			#回傳結果
7294
			return $result;
7295
 
7296
			}#if end
7297
 
7298
		#檢查參數
7299
		#函式說明:
7300
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
7301
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7302
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
7303
		#$result["function"],當前執行的函式名稱.
7304
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
7305
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
7306
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
7307
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
7308
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
7309
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
7310
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
7311
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
7312
		#必填寫的參數:
7313
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
7314
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
7315
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
7316
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
7317
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
7318
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
7319
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
7320
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
7321
		#可以省略的參數:
7322
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
7323
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
7324
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
7325
		#$conf["canNotBeEmpty"]=array();
7326
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
7327
		#$conf["canBeEmpty"]=array();
7328
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
7329
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
7330
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
7331
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("entry","connVar","disReg");
7332
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
7333
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string");
7334
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
7335
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","conn","false");
7336
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
7337
		#$conf["arrayCountEqualCheck"][]=array();
7338
		#參考資料來源:
7339
		#array_keys=>http://php.net/manual/en/function.array-keys.php
7340
		#建議:
7341
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
7342
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
7343
		unset($conf["variableCheck::checkArguments"]);
7344
 
7345
		#如果檢查參數失敗
7346
		if($checkArguments["status"]==="false"){
7347
 
7348
			#設置執行失敗
7349
			$result["status"]="false";
7350
 
7351
			#設置執行錯誤訊息
7352
			$result["error"]=$checkArguments;
7353
 
7354
			#回傳結果
7355
			return $result;
7356
 
7357
			}#if end
7358
 
7359
		#如果參數檢查不通過
7360
		if($checkArguments["passed"]==="false"){
7361
 
7362
			#設置執行失敗
7363
			$result["status"]="false";
7364
 
7365
			#設置執行錯誤訊息
7366
			$result["error"]=$checkArguments;
7367
 
7368
			#回傳結果
7369
			return $result;
7370
 
7371
			}#if end
7372
 
7373
		#物件化ChatV3類別
7374
		$Chat3=new ChatV3();
7375
 
7376
		#設置屬性 fileArgu
7377
		$Chat3::$fileArgu=$conf["fileArgu"];
7378
 
7379
		#建立 Ratchet 提供的聊天室範例(適用於telnet)
7380
		#It stores all the established connections, mediates data sent between each client and our Chat application, and catches errors. 
7381
		#we tell the server to enter an event loop, listening for any incoming requests on port 8080. 
7382
		#$server = IoServer::factory(new Chat(),8080);
7383
 
7384
		#建立 Ratchet 提供的聊天室範例(適用於用webServer)
7385
		$server = IoServer::factory(
7386
			new HttpServer(
7387
				new WsServer(
7388
					$Chat3
7389
					)
7390
				),
7391
			8080
7392
			);
7393
 
7394
		#執行 server 端程式
7395
		$server->run();
7396
 
7397
		#設置執行正常
7398
		$result["status"]="true";
7399
 
7400
		#回傳結果	
7401
		return $result;
7402
 
7403
		}#function chatRoomServerDemoV3 end	
7404
 
7405
	/*
7406
	#函式說明:
7407
	#擴充過的Ratchet聊天室伺服端soldier範例.提供cmd:跟sql:指令支援.
7408
	#回傳結果:
7409
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7410
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
7411
	#$result["function"],當前執行的函式名稱.		
7412
	#必填參數:
7413
	#$conf["fileArgu"],__FILE__的內容.
7414
	$conf["fileArgu"]=__FILE__;
7415
	#可省略參數:
7416
	#$conf["port"],要 listen 的 port
7417
	#$conf["port"]="8080";
7418
	#參考資料:
7419
	#Ratchet官網=>http://socketo.me/
7420
	#聊天室範例=>http://socketo.me/docs/hello-world
7421
	#備註:
7422
	#必須要在命令列環境下執行才行.
7423
	*/
7424
	public static function soldierServerDemo(&$conf){
7425
 
7426
		#初始化要回傳的結果
7427
		$result=array();
7428
 
7429
		#取得當前執行的函數名稱
7430
		$result["function"]=__FUNCTION__;
7431
 
7432
		#如果沒有參數
7433
		if(func_num_args()==0){
7434
 
7435
			#設置執行失敗
7436
			$result["status"]="false";
7437
 
7438
			#設置執行錯誤訊息
7439
			$result["error"]="函數".$result["function"]."需要參數";
7440
 
7441
			#回傳結果
7442
			return $result;
7443
 
7444
			}#if end
7445
 
7446
		#涵式說明:
7447
		#判斷當前環境為web還是cmd
7448
		#回傳結果:
7449
		#$result,"web"或"cmd"
7450
		if(csInformation::getEnv()==="web"){
7451
 
7452
			#設置執行失敗
7453
			$result["status"]="false";
7454
 
7455
			#設置執行錯誤訊息
7456
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
7457
 
7458
			#回傳結果
7459
			return $result;
7460
 
7461
			}#if end
7462
 
7463
		#取得參數
7464
		$result["argu"]=$conf;
7465
 
7466
		#如果 $conf 不為陣列
7467
		if(gettype($conf)!=="array"){
7468
 
7469
			#設置執行失敗
7470
			$result["status"]="false";
7471
 
7472
			#設置執行錯誤訊息
7473
			$result["error"][]="\$conf變數須為陣列形態";
7474
 
7475
			#如果傳入的參數為 null
7476
			if($conf===null){
7477
 
7478
				#設置執行錯誤訊息
7479
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
7480
 
7481
				}#if end
7482
 
7483
			#回傳結果
7484
			return $result;
7485
 
7486
			}#if end
7487
 
7488
		#檢查參數
7489
		#函式說明:
7490
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
7491
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7492
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
7493
		#$result["function"],當前執行的函式名稱.
7494
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
7495
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
7496
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
7497
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
7498
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
7499
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
7500
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
7501
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
7502
		#必填寫的參數:
7503
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
7504
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
7505
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
7506
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
7507
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
7508
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
7509
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
7510
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
7511
		#可以省略的參數:
7512
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
7513
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
7514
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
7515
		#$conf["canNotBeEmpty"]=array();
7516
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
7517
		#$conf["canBeEmpty"]=array();
7518
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
7519
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
7520
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
7521
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("port");
7522
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
7523
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("integer");
7524
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
7525
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(8080);
7526
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
7527
		#$conf["arrayCountEqualCheck"][]=array();
7528
		#參考資料來源:
7529
		#array_keys=>http://php.net/manual/en/function.array-keys.php
7530
		#建議:
7531
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
7532
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
7533
		unset($conf["variableCheck::checkArguments"]);
7534
 
7535
		#如果檢查參數失敗
7536
		if($checkArguments["status"]==="false"){
7537
 
7538
			#設置執行失敗
7539
			$result["status"]="false";
7540
 
7541
			#設置執行錯誤訊息
7542
			$result["error"]=$checkArguments;
7543
 
7544
			#回傳結果
7545
			return $result;
7546
 
7547
			}#if end
7548
 
7549
		#如果參數檢查不通過
7550
		if($checkArguments["passed"]==="false"){
7551
 
7552
			#設置執行失敗
7553
			$result["status"]="false";
7554
 
7555
			#設置執行錯誤訊息
7556
			$result["error"]=$checkArguments;
7557
 
7558
			#回傳結果
7559
			return $result;
7560
 
7561
			}#if end
7562
 
7563
		#建立 Ratchet 提供的聊天室範例(適用於telnet)
7564
		#It stores all the established connections, mediates data sent between each client and our Chat application, and catches errors. 
7565
		#we tell the server to enter an event loop, listening for any incoming requests on port 8080. 
7566
		#$server = IoServer::factory(new Chat(),8080);
7567
 
7568
		#建立 soldier 物件
7569
		$soldier=new soldier();
7570
 
7571
		#設置fileArgu屬性
7572
		$soldier::$fileArgu=$conf["fileArgu"];
7573
 
7574
		#建立 Ratchet 提供的聊天室範例(適用於用webServer)
7575
		$server = IoServer::factory(
7576
			new HttpServer(
7577
				new WsServer(
7578
					$soldier
7579
					)
7580
				),
7581
			$conf["port"]
7582
			);
7583
 
7584
		#執行 server 端程式
7585
		$server->run();
7586
 
7587
		#設置執行正常
7588
		$result["status"]="true";
7589
 
7590
		#回傳結果	
7591
		return $result;
7592
 
7593
		}#function soldierServerDemo end	
7594
 
7595
	/*
7596
	#函式說明:
7597
	#擴充過的Ratchet聊天室用戶端js範例
7598
	#回傳結果:
7599
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7600
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
7601
	#$result["function"],當前執行的函式名稱.		
7602
	#$result["content"],html.
7603
	#必填參數:
7604
	#無.
7605
	#可省略參數:
7606
	#無.
7607
	#參考資料:
7608
	#Ratchet官網=>http://socketo.me/
7609
	#用apache的proxy來判斷為哪個服務,導到對應的port裡面=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
7610
	#聊天室範例=>http://socketo.me/docs/hello-world
7611
	#備註:
7612
	#僅適用於https網頁透過wss連線到web socket server.	
7613
	*/
7614
	public static function chatRoomClientDemo(){
7615
 
7616
		#初始化要回傳的結果
7617
		$result=array();
7618
 
7619
		#初始化儲存html的變數
7620
		$result["content"]="";
7621
 
7622
		#取得當前執行的函數名稱
7623
		$result["function"]=__FUNCTION__;
7624
 
7625
		#初始化帳號密碼
7626
		$ac="";
7627
		$pw="";
7628
 
7629
		#如果存在 $_SESSION["account"]
7630
		if(isset($_SESSION["account"])){
7631
 
7632
			#取得帳戶
7633
			$ac=$_SESSION["account"];
7634
 
7635
			}#if end
7636
 
7637
		#如果 this->$passwordCol 不為 ""
7638
		if(Chat::$passwordCol!==""){
7639
 
7640
			#如果存在 $_SESSION["password"]
7641
			if(isset($_SESSION["password"])){
7642
 
7643
				#取得帳戶
7644
				$pw=$_SESSION["password"];
7645
 
7646
				}#if end
7647
 
7648
			}#if end
7649
 
7650
		#取得 server 的 ip
7651
		#涵式說明:
7652
		#取得伺服器的IP,並回傳。
7653
		#回傳的結果:
7654
		#$result,伺服端的IP
7655
		#備註:
7656
		#伺服端必須被 localhost 以外的網址連結才會出現正確的IP
7657
		$getServerIP=csInformation::getServerIP();
7658
 
7659
		#設置用戶端連線到webSocket的範例
7660
		$script="<script>
7661
 
7662
			//取得帳號密碼
7663
			ac='".$ac."';
7664
			pw='".$pw."';
7665
 
7666
			//設置目前尚為連線到 webSocket Server
7667
			connected='false';
7668
 
7669
			//設置儲存應該要斷線的webSocket,避免太多連線在伺服器.
7670
			//wbClosed='';
7671
 
7672
			//設置儲存webSocket連線的變數
7673
			wb='';
7674
 
7675
			//連線到 web socket
7676
			connWebSock();
7677
 
7678
			//連線到 web socket
7679
			function connWebSock()
7680
			{
7681
				//建立 web socket 連線到 wss://localhost/wss/chatDemo
7682
				var conn = new WebSocket('wss://".$getServerIP."/wss/chatDemo');
7683
 
7684
				//當連線成功後
7685
				conn.onopen = function(e){
7686
 
7687
					//印出連線成功訊息到console
7688
					console.log(\"Connection established!\");
7689
 
7690
					//設置已經連上 webSocket server
7691
					connected='true';
7692
 
7693
					//另存 webSocket 物件
7694
					wb=conn;
7695
 
7696
					/*
7697
					//如果存在前一個連線物件
7698
					if(wbClosed!==''){
7699
 
7700
						//提示關閉前個連線
7701
						console.log(\"close last connection!\");
7702
 
7703
						//關閉之前的連線
7704
						wbClosed.close();
7705
 
7706
						//清空
7707
						wbClosed='';
7708
 
7709
						}
7710
					*/
7711
 
7712
					}
7713
 
7714
				//當有收到訊息時
7715
				conn.onmessage = function(e){
7716
 
7717
					//將訊息顯現在console
7718
					console.log(e.data);
7719
 
7720
					//將訊息寫到文字方框裡面
7721
					$('#history').val(e.data+'\\r\\n'+$('#history').val());
7722
 
7723
					//解析json字串
7724
					data=JSON.parse(e.data);				
7725
 
7726
					//如果有查到帳號
7727
					if(ac!==''){
7728
 
7729
						//如果要求輸入帳號
7730
						if(data==='Please input your account! ex:account:ws1'){
7731
 
7732
							//傳送帳號
7733
							conn.send('account:'+ac);
7734
 
7735
							}
7736
 
7737
						//如果有查到密碼
7738
						if(pw!==''){
7739
 
7740
							//如果要求輸入密碼	
7741
							if(data==='Please input your password! ex:password:ws1'){
7742
 
7743
								//傳送密碼
7744
								conn.send('password:'+pw);
7745
 
7746
								}
7747
 
7748
							}
7749
 
7750
						}
7751
 
7752
					}
7753
 
7754
				//當連線斷開後
7755
				conn.onclose = function(e){
7756
 
7757
					//印出連線斷開的訊息到console
7758
					//console.log(\"Connection end!\");
7759
 
7760
					//設置未連上 webSocket server
7761
					connected='false';
7762
 
7763
					/*
7764
					//如果有之前的連線物件
7765
					if(wb!==''){
7766
 
7767
						//儲存應該要斷線的webSocket,避免太多連線在伺服器.
7768
						wbClosed=wb;
7769
 
7770
						}
7771
					*/
7772
 
7773
					//清空 webSocket 物件
7774
					wb='';
7775
 
7776
					//指定1秒刷新一次
7777
					setTimeout('connWebSock()',1000); 
7778
 
7779
					}
7780
 
7781
				}							
7782
 
7783
			//當按下送出按鈕
7784
			$('#send').on('click',function(){
7785
 
7786
				//如果已經連到 webSocket server 了
7787
				if(connected==='true'){
7788
 
7789
					//傳送訊息
7790
					wb.send($('#input').val());
7791
 
7792
					//清空訊息輸入欄
7793
					$('#input').val('');
7794
 
7795
					}
7796
 
7797
				});
7798
 
7799
			//重新整理頁面
7800
			function myrefresh(){
7801
 
7802
				//重新整理頁面
7803
				window.location.reload();
7804
 
7805
				}
7806
 
7807
			</script>";
7808
 
7809
		#設置存放歷史訊息的方框
7810
		#涵式說明:
7811
		#可以輸入文字的區塊
7812
		#回傳結果:
7813
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7814
		#$result["function"],當前執行的函數.
7815
		#$result["error"],錯誤訊息陣列.
7816
		#$result["content"],按鈕語法. 		
7817
		#必填的參數:
7818
		$conf["form::inputTextArea"]["name"]="history";#爲文字輸入框的名稱,供接收端辨識用。
7819
		$conf["form::inputTextArea"]["readOnly"]="true";#爲是否要爲唯讀,如果爲"true",則爲唯讀。反之則爲"false"。
7820
		#可省略的參數:
7821
		#$conf["id"],字串,文字區塊的id,供javaScript呼叫用.
7822
		$conf["form::inputTextArea"]["id"]="history";
7823
		#$conf["width"]="";#為輸入框的寬度,預設不指定.
7824
		#$conf["cols"]="";#爲文字輸入框的欄位數(寬),預設爲按照瀏覽器設定值。
7825
		#$conf["rows"]="";#爲文字輸入框的列數(高),預設爲按照瀏覽器設定值。
7826
		#$conf["maxInputLength"]="";#爲文字輸入的長度限制,預設無限制。
7827
		#$conf["defaultText"]="";#爲文字輸入框裏面的預設文字內容,預設是空的。
7828
		#$conf["class"]=;#爲要套用的css樣式。如果沒有指定 ,則採用預設的css樣式,"__inputTextAreaCssStyle",其屬性爲 "width:100%","height:120px","font-size:30px"
7829
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)...,須搭配$conf["jsSubmitActionTarget"]參數。
7830
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。
7831
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
7832
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
7833
		#$conf["formName"]="";#爲該表單的名稱
7834
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
7835
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
7836
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
7837
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
7838
		#$conf["comment"]="";
7839
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
7840
		#$conf["required"]="true";
7841
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
7842
		#$conf["placeholder"]="";
7843
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是",也可以看作新的一列開始,預設為"false".
7844
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是",也可以看成列裏面的元素開始,預設為"false".
7845
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是",也可以看成列裏面的元素結束,預設為"false".
7846
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是",也可以看作該列結束,預設為"false".
7847
		#參考資料來源:
7848
		#input=>http://www.w3schools.com/tags/tag_input.asp
7849
		$inputTextArea=form::inputTextArea($conf["form::inputTextArea"]);
7850
		unset($conf["form::inputTextArea"]);
7851
 
7852
		#如果建立文字方框失敗
7853
		if($inputTextArea["status"]==="false"){
7854
 
7855
			#設置執行失敗
7856
			$result["status"]="false";
7857
 
7858
			#設置執行錯誤訊息
7859
			$result["error"]=$inputTextArea;
7860
 
7861
			#回傳結果
7862
			return $result;
7863
 
7864
			}#if end	
7865
 
7866
		#串連文字訊息方框
7867
		$result["content"]=$result["content"].$inputTextArea["content"];
7868
 
7869
		#設置填寫要傳送的訊息輸入方框
7870
		#涵式說明:
7871
		#可以輸入文字的表單
7872
		#回傳的結果:
7873
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7874
		#$result["function"],當前執行的函數.
7875
		#$result["error"],錯誤訊息陣列.
7876
		#$result["content"],按鈕語法. 
7877
		#必填的參數
7878
		$conf["form::inputText"]["name"]="data";#爲該文字輸入框的名稱,用於讓接收頁面讀取的名稱。
7879
		$conf["form::inputText"]["readOnly"]="false";#爲該文字框是否可以填寫資料,若要只能觀看不能填寫,那麼就必須將其值設爲"true",反之要設爲"false"
7880
		#可省略的參數:
7881
		#$conf["width"]="";#爲文字框的外觀長度,預設為"100%".
7882
		#$conf["maxInputLength"]="";#爲可輸入的最大位元長度,預設不限制。
7883
		#$conf["autoFocus"]="true";#是否為將填寫的指標移到該表單,"true"代表要,預設為"false".
7884
		#$conf["value"]="";#爲該文字框預設要顯示的文字,預設爲""。	
7885
		#$conf["class"]="";#爲要套用的css樣式,若省略,則會套用預設的 "__inputTextCssStyle" 樣式,其屬性爲 "width:100%","font-size:30px"
7886
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)、"onClick"(按下按鈕時)、"onkeyup"(當鍵盤按下放開後)、"onmouseover"(當滑鼠移過去的時候)...,須搭配$conf["jsSubmitActionTarget"]參數。
7887
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。		
7888
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
7889
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
7890
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
7891
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
7892
		#$conf["formName"]="";#爲該表單的名稱
7893
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
7894
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
7895
		#$conf["tableStart"]="true";#爲該表單是否要以<table>開始。"true"爲是,預設為"false".
7896
		#$conf["tableClass"]="";#表格要套用的css樣式,若爲"__withoutBorder"的話則套用無框線的預設樣式;若爲"__withBorder"的話,則爲有框線的預設樣式,預設為"__withoutBorder".
7897
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
7898
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
7899
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
7900
		#$conf["tableEnd"]="true";#爲該表單是否要以</table>結尾,"true"爲是,預設為"false".
7901
		#$conf["autocomplete"],字串,是否依據使用者過往輸入的記錄來提示可能要的輸入內容,"on"為啟用,"off"為停用,預設為"on".
7902
		#$conf["autocomplete"]="off";
7903
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
7904
		#$conf["required"]="true";
7905
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
7906
		#$conf["comment"]="";
7907
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
7908
		#$conf["placeholder"]="";
7909
		#$conf["br"],字串,"true"代表最後要換行,預設為"false".
7910
		#$conf["br"]="true";
7911
		#$conf["p"],字串,"true"代表最後要空一行,預設為"false".
7912
		#$conf["p"]="true";
7913
		#$conf["id"],字串,該元素的id,預設不使用.
7914
		$conf["form::inputText"]["id"]="input";
7915
		#參考資料來源:
7916
		#input=>http://www.w3schools.com/tags/tag_input.asp
7917
		$inputText=form::inputText($conf["form::inputText"]);
7918
		unset($conf["form::inputText"]);
7919
 
7920
		#如果輸入文字框失敗
7921
		if($inputText["status"]==="false"){
7922
 
7923
			#設置執行失敗
7924
			$result["status"]="false";
7925
 
7926
			#設置執行錯誤訊息
7927
			$result["error"]=$inputText;
7928
 
7929
			#回傳結果
7930
			return $result;
7931
 
7932
			}#if end	
7933
 
7934
		#文字輸入框
7935
		$result["content"]=$result["content"].$inputText["content"];
7936
 
7937
		#設置觸發的按鈕
7938
		#函式說明:
7939
		#放置按鈕
7940
		#回傳結果:
7941
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7942
		#$result["function"],當前執行的函數.
7943
		#$result["error"],錯誤訊息陣列.
7944
		#$result["content"],按鈕語法. 
7945
		#必要的參數:
7946
		$conf["form::button"]["buttonDisplayValue"]="Send";#爲按鈕上顯示的文字。
7947
		#可省略的參數:
7948
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
7949
			#其屬性爲   "width","height","font-size","text-align"
7950
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
7951
		#$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
7952
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
7953
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
7954
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
7955
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
7956
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
7957
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
7958
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
7959
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
7960
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
7961
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
7962
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
7963
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
7964
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
7965
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
7966
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
7967
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
7968
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
7969
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
7970
		#$conf["formId"],字串,表單的id.
7971
		#$conf["formId"]="";
7972
		#$conf["buttonId"],字串,按鈕的id.
7973
		$conf["form::button"]["buttonId"]="send";
7974
		#參考資料來源:
7975
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
7976
		$button=form::button($conf["form::button"]);
7977
		unset($conf["form::button"]);
7978
 
7979
		#如果建立按鈕失敗
7980
		if($button["status"]==="false"){
7981
 
7982
			#設置執行失敗
7983
			$result["status"]="false";
7984
 
7985
			#設置執行錯誤訊息
7986
			$result["error"]=$button;
7987
 
7988
			#回傳結果
7989
			return $result;
7990
 
7991
			}#if end	
7992
 
7993
		#建立跳到別的頁面的連結
7994
		#涵式說明:
7995
		#放置超鏈結
7996
		#回傳的結果:
7997
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
7998
		#$result["error"],錯誤訊息
7999
		#$result["content"],語法
8000
		#$result["function"],當前執行的函數名稱
8001
		#必填的參數:
8002
		#$conf["position"],字串,爲要連結到的位置,若留空,將回自動變成"#",則可以搭配ajax傳值.	
8003
		$conf["link::show_link"]["position"]="webSocketT/hangFewSecs.php";
8004
		#$conf["linkName",字串,爲連結的顯示名稱
8005
		$conf["link::show_link"]["linkName"]="到別的頁面轉轉";
8006
		#可省略的參數:
8007
		#$conf["method"],字串,爲點選連結後,新畫面要如何呈現,可省略預設爲"_self",可用的選項有 _top(覆蓋目前的視窗來顯現新內容) _parent _self _blank(跳新視窗)
8008
		#$conf["method"]=""; 
8009
		#$conf["class"],字串,爲要套用的css超連節樣式,可省略.
8010
		#$conf["class"]="";
8011
		#$conf["id"],字串,超連結的id.
8012
		#$conf["id"]="";
8013
		#$conf["no_outline"],字串,是否要取消連結的框線,"false為不取消,"true"代表要取消,預設為"false".
8014
		#$conf["no_outline"]="";
8015
		$show_link=link::show_link($conf["link::show_link"]);
8016
		unset($conf["link::show_link"]);
8017
 
8018
		#串接超連結
8019
		$result["content"]=$result["content"].$show_link["content"];
8020
 
8021
		#設置用戶端的html與js語法
8022
		$result["content"]=$result["content"].$button["content"].$script;
8023
 
8024
		#設置執行正常
8025
		$result["status"]="true";
8026
 
8027
		#回傳結果
8028
		return $result;
8029
 
8030
		}#function chatRoomClientDemo end
8031
 
8032
	/*
8033
	#函式說明:
8034
	#擴充過的Ratchet聊天室用戶端js範例第二版
8035
	#回傳結果:
8036
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8037
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
8038
	#$result["function"],當前執行的函式名稱.		
8039
	#$result["content"],html.
8040
	#必填參數:
8041
	#無.
8042
	#可省略參數:
8043
	#無.
8044
	#參考資料:
8045
	#Ratchet官網=>http://socketo.me/
8046
	#用apache的proxy來判斷為哪個服務,導到對應的port裡面=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
8047
	#聊天室範例=>http://socketo.me/docs/hello-world
8048
	#備註:
8049
	#僅適用於https網頁透過wss連線到web socket server.	
8050
	*/
8051
	public static function chatRoomClientDemoV2(){
8052
 
8053
		#初始化要回傳的結果
8054
		$result=array();
8055
 
8056
		#初始化儲存html的變數
8057
		$result["content"]="";
8058
 
8059
		#取得當前執行的函數名稱
8060
		$result["function"]=__FUNCTION__;
8061
 
8062
		#初始化帳號密碼
8063
		$ac="";
8064
		$pw="";
8065
 
8066
		#如果存在 $_SESSION["account"]
8067
		if(isset($_SESSION["account"])){
8068
 
8069
			#取得帳戶
8070
			$ac=$_SESSION["account"];
8071
 
8072
			}#if end
8073
 
8074
		#如果 this->$passwordCol 不為 ""
8075
		if(Chat::$passwordCol!==""){
8076
 
8077
			#如果存在 $_SESSION["password"]
8078
			if(isset($_SESSION["password"])){
8079
 
8080
				#取得帳戶
8081
				$pw=$_SESSION["password"];
8082
 
8083
				}#if end
8084
 
8085
			}#if end
8086
 
8087
		#取得 server 的 ip
8088
		#涵式說明:
8089
		#取得伺服器的IP,並回傳。
8090
		#回傳的結果:
8091
		#$result,伺服端的IP
8092
		#備註:
8093
		#伺服端必須被 localhost 以外的網址連結才會出現正確的IP
8094
		$getServerIP=csInformation::getServerIP();
8095
 
8096
		#設置用戶端連線到webSocket的範例
8097
		$script="<script>
8098
 
8099
			//取得帳號密碼
8100
			ac='".$ac."';
8101
			pw='".$pw."';
8102
 
8103
			//設置目前尚為連線到 webSocket Server
8104
			connected='false';
8105
 
8106
			//設置儲存應該要斷線的webSocket,避免太多連線在伺服器.
8107
			wbClosed='';
8108
 
8109
			//設置儲存webSocket連線的變數
8110
			wb='';
8111
 
8112
			//設置儲存msgId的變數
8113
			msgId='';
8114
 
8115
			//連線到 web socket
8116
			connWebSock();
8117
 
8118
			//連線到 web socket
8119
			function connWebSock()
8120
			{
8121
				//建立 web socket 連線到 wss://localhost/wss/chatDemo
8122
				var conn = new WebSocket('wss://".$getServerIP."/wss/chatDemo');
8123
 
8124
				//當連線成功後
8125
				conn.onopen = function(e){
8126
 
8127
					//印出連線成功訊息到console
8128
					console.log(\"Connection established!\");
8129
 
8130
					//設置已經連上 webSocket server
8131
					connected='true';
8132
 
8133
					//另存 webSocket 物件
8134
					wb=conn;
8135
 
8136
					//如果存在前一個連線物件
8137
					if(wbClosed!==''){
8138
 
8139
						//提示關閉前個連線
8140
						console.log(\"close last connection!\");
8141
 
8142
						//關閉之前的連線
8143
						wbClosed.close();
8144
 
8145
						//清空
8146
						wbClosed='';
8147
 
8148
						}
8149
 
8150
					}
8151
 
8152
				//當有收到訊息時
8153
				conn.onmessage = function(e){
8154
 
8155
					//將訊息顯現在console
8156
					console.log(e.data);
8157
 
8158
					//將訊息寫到文字方框裡面
8159
					$('#history').val(e.data+'\\r\\n'+$('#history').val());
8160
 
8161
					//解析json字串
8162
					data=JSON.parse(e.data);
8163
 
8164
					//如果要要求login的訊息
8165
					if(data.type==='login'){
8166
 
8167
						//如果有查到帳號
8168
						if(ac!==''){
8169
 
8170
							//如果要求輸入帳號
8171
							if(data.data==='Please input your account! ex:account:ws1'){
8172
 
8173
								//傳送帳號
8174
								conn.send('account:'+ac);
8175
 
8176
								}
8177
 
8178
							//如果有查到密碼
8179
							if(pw!==''){
8180
 
8181
								//如果要求輸入密碼	
8182
								if(data.data==='Please input your password! ex:password:ws1'){
8183
 
8184
									//傳送密碼
8185
									conn.send('password:'+pw);
8186
 
8187
									}
8188
 
8189
								}
8190
 
8191
							//如果存在既有的msgId,且剛登入成功
8192
							if(msgId!=='' && data.data==='Login successfully!'){
8193
 
8194
								//設置既有的msgId
8195
								conn.send('msgId:'+msgId);
8196
 
8197
								}
8198
 
8199
							//反之如果登入成功
8200
							else if(data.data==='Login successfully!'){
8201
 
8202
								//查詢自己的msgId
8203
								conn.send('msgId?');
8204
 
8205
								}
8206
 
8207
							}
8208
 
8209
						}
8210
 
8211
					//如果收到的是 'msgId?'
8212
					else if(data.type==='msgId?'){
8213
 
8214
						//設置自己的msgId
8215
						msgId=data.data;
8216
 
8217
						}
8218
 
8219
					//如果收到的是 'msg' 類型
8220
					else if(data.type==='msg'){
8221
 
8222
						//回傳有收到訊息的確認
8223
						conn.send('mIndex:'+data.index);
8224
 
8225
						}
8226
 
8227
					//如果收到的是 'status' 類型	
8228
					else if(data.type==='status'){
8229
 
8230
						//如果內容為設置msgId失敗
8231
						if(data.data==='set msgId failed'){
8232
 
8233
							//查詢自己的msgId
8234
							conn.send('msgId?');
8235
 
8236
							}
8237
 
8238
						}
8239
 
8240
					}
8241
 
8242
				//當連線斷開後
8243
				conn.onclose = function(e){
8244
 
8245
					//設置未連上 webSocket server
8246
					connected='false';
8247
 
8248
					//如果有之前的連線物件
8249
					if(wb!==''){
8250
 
8251
						//儲存應該要斷線的webSocket,避免太多連線在伺服器.
8252
						wbClosed=wb;
8253
 
8254
						}
8255
 
8256
					//清空 webSocket 物件
8257
					wb='';
8258
 
8259
					//指定1秒刷新一次
8260
					setTimeout('connWebSock()',1000); 
8261
 
8262
					}
8263
 
8264
				}							
8265
 
8266
			//當按下送出按鈕
8267
			$('#send').on('click',function(){
8268
 
8269
				//如果已經連到 webSocket server 了
8270
				if(connected==='true'){
8271
 
8272
					//傳送訊息
8273
					wb.send($('#input').val());
8274
 
8275
					//清空訊息輸入欄
8276
					$('#input').val('');
8277
 
8278
					}
8279
 
8280
				});
8281
 
8282
			//重新整理頁面
8283
			function myrefresh(){
8284
 
8285
				//重新整理頁面
8286
				window.location.reload();
8287
 
8288
				}
8289
 
8290
			</script>";
8291
 
8292
		#設置存放歷史訊息的方框
8293
		#涵式說明:
8294
		#可以輸入文字的區塊
8295
		#回傳結果:
8296
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8297
		#$result["function"],當前執行的函數.
8298
		#$result["error"],錯誤訊息陣列.
8299
		#$result["content"],按鈕語法. 		
8300
		#必填的參數:
8301
		$conf["form::inputTextArea"]["name"]="history";#爲文字輸入框的名稱,供接收端辨識用。
8302
		$conf["form::inputTextArea"]["readOnly"]="true";#爲是否要爲唯讀,如果爲"true",則爲唯讀。反之則爲"false"。
8303
		#可省略的參數:
8304
		#$conf["id"],字串,文字區塊的id,供javaScript呼叫用.
8305
		$conf["form::inputTextArea"]["id"]="history";
8306
		#$conf["width"]="";#為輸入框的寬度,預設不指定.
8307
		#$conf["cols"]="";#爲文字輸入框的欄位數(寬),預設爲按照瀏覽器設定值。
8308
		#$conf["rows"]="";#爲文字輸入框的列數(高),預設爲按照瀏覽器設定值。
8309
		#$conf["maxInputLength"]="";#爲文字輸入的長度限制,預設無限制。
8310
		#$conf["defaultText"]="";#爲文字輸入框裏面的預設文字內容,預設是空的。
8311
		#$conf["class"]=;#爲要套用的css樣式。如果沒有指定 ,則採用預設的css樣式,"__inputTextAreaCssStyle",其屬性爲 "width:100%","height:120px","font-size:30px"
8312
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)...,須搭配$conf["jsSubmitActionTarget"]參數。
8313
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。
8314
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
8315
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
8316
		#$conf["formName"]="";#爲該表單的名稱
8317
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
8318
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
8319
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
8320
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
8321
		#$conf["comment"]="";
8322
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
8323
		#$conf["required"]="true";
8324
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
8325
		#$conf["placeholder"]="";
8326
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是",也可以看作新的一列開始,預設為"false".
8327
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是",也可以看成列裏面的元素開始,預設為"false".
8328
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是",也可以看成列裏面的元素結束,預設為"false".
8329
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是",也可以看作該列結束,預設為"false".
8330
		#參考資料來源:
8331
		#input=>http://www.w3schools.com/tags/tag_input.asp
8332
		$inputTextArea=form::inputTextArea($conf["form::inputTextArea"]);
8333
		unset($conf["form::inputTextArea"]);
8334
 
8335
		#如果建立文字方框失敗
8336
		if($inputTextArea["status"]==="false"){
8337
 
8338
			#設置執行失敗
8339
			$result["status"]="false";
8340
 
8341
			#設置執行錯誤訊息
8342
			$result["error"]=$inputTextArea;
8343
 
8344
			#回傳結果
8345
			return $result;
8346
 
8347
			}#if end	
8348
 
8349
		#串連文字訊息方框
8350
		$result["content"]=$result["content"].$inputTextArea["content"];
8351
 
8352
		#設置填寫要傳送的訊息輸入方框
8353
		#涵式說明:
8354
		#可以輸入文字的表單
8355
		#回傳的結果:
8356
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8357
		#$result["function"],當前執行的函數.
8358
		#$result["error"],錯誤訊息陣列.
8359
		#$result["content"],按鈕語法. 
8360
		#必填的參數
8361
		$conf["form::inputText"]["name"]="data";#爲該文字輸入框的名稱,用於讓接收頁面讀取的名稱。
8362
		$conf["form::inputText"]["readOnly"]="false";#爲該文字框是否可以填寫資料,若要只能觀看不能填寫,那麼就必須將其值設爲"true",反之要設爲"false"
8363
		#可省略的參數:
8364
		#$conf["width"]="";#爲文字框的外觀長度,預設為"100%".
8365
		#$conf["maxInputLength"]="";#爲可輸入的最大位元長度,預設不限制。
8366
		#$conf["autoFocus"]="true";#是否為將填寫的指標移到該表單,"true"代表要,預設為"false".
8367
		#$conf["value"]="";#爲該文字框預設要顯示的文字,預設爲""。	
8368
		#$conf["class"]="";#爲要套用的css樣式,若省略,則會套用預設的 "__inputTextCssStyle" 樣式,其屬性爲 "width:100%","font-size:30px"
8369
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)、"onClick"(按下按鈕時)、"onkeyup"(當鍵盤按下放開後)、"onmouseover"(當滑鼠移過去的時候)...,須搭配$conf["jsSubmitActionTarget"]參數。
8370
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。		
8371
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
8372
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
8373
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
8374
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
8375
		#$conf["formName"]="";#爲該表單的名稱
8376
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
8377
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
8378
		#$conf["tableStart"]="true";#爲該表單是否要以<table>開始。"true"爲是,預設為"false".
8379
		#$conf["tableClass"]="";#表格要套用的css樣式,若爲"__withoutBorder"的話則套用無框線的預設樣式;若爲"__withBorder"的話,則爲有框線的預設樣式,預設為"__withoutBorder".
8380
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
8381
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
8382
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
8383
		#$conf["tableEnd"]="true";#爲該表單是否要以</table>結尾,"true"爲是,預設為"false".
8384
		#$conf["autocomplete"],字串,是否依據使用者過往輸入的記錄來提示可能要的輸入內容,"on"為啟用,"off"為停用,預設為"on".
8385
		#$conf["autocomplete"]="off";
8386
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
8387
		#$conf["required"]="true";
8388
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
8389
		#$conf["comment"]="";
8390
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
8391
		#$conf["placeholder"]="";
8392
		#$conf["br"],字串,"true"代表最後要換行,預設為"false".
8393
		#$conf["br"]="true";
8394
		#$conf["p"],字串,"true"代表最後要空一行,預設為"false".
8395
		#$conf["p"]="true";
8396
		#$conf["id"],字串,該元素的id,預設不使用.
8397
		$conf["form::inputText"]["id"]="input";
8398
		#參考資料來源:
8399
		#input=>http://www.w3schools.com/tags/tag_input.asp
8400
		$inputText=form::inputText($conf["form::inputText"]);
8401
		unset($conf["form::inputText"]);
8402
 
8403
		#如果輸入文字框失敗
8404
		if($inputText["status"]==="false"){
8405
 
8406
			#設置執行失敗
8407
			$result["status"]="false";
8408
 
8409
			#設置執行錯誤訊息
8410
			$result["error"]=$inputText;
8411
 
8412
			#回傳結果
8413
			return $result;
8414
 
8415
			}#if end	
8416
 
8417
		#文字輸入框
8418
		$result["content"]=$result["content"].$inputText["content"];
8419
 
8420
		#設置觸發的按鈕
8421
		#函式說明:
8422
		#放置按鈕
8423
		#回傳結果:
8424
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8425
		#$result["function"],當前執行的函數.
8426
		#$result["error"],錯誤訊息陣列.
8427
		#$result["content"],按鈕語法. 
8428
		#必要的參數:
8429
		$conf["form::button"]["buttonDisplayValue"]="Send";#爲按鈕上顯示的文字。
8430
		#可省略的參數:
8431
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
8432
			#其屬性爲   "width","height","font-size","text-align"
8433
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
8434
		#$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
8435
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
8436
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
8437
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
8438
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
8439
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
8440
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
8441
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
8442
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
8443
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
8444
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
8445
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
8446
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
8447
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
8448
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
8449
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
8450
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
8451
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
8452
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
8453
		#$conf["formId"],字串,表單的id.
8454
		#$conf["formId"]="";
8455
		#$conf["buttonId"],字串,按鈕的id.
8456
		$conf["form::button"]["buttonId"]="send";
8457
		#參考資料來源:
8458
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
8459
		$button=form::button($conf["form::button"]);
8460
		unset($conf["form::button"]);
8461
 
8462
		#如果建立按鈕失敗
8463
		if($button["status"]==="false"){
8464
 
8465
			#設置執行失敗
8466
			$result["status"]="false";
8467
 
8468
			#設置執行錯誤訊息
8469
			$result["error"]=$button;
8470
 
8471
			#回傳結果
8472
			return $result;
8473
 
8474
			}#if end	
8475
 
8476
		#建立跳到別的頁面的連結
8477
		#涵式說明:
8478
		#放置超鏈結
8479
		#回傳的結果:
8480
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8481
		#$result["error"],錯誤訊息
8482
		#$result["content"],語法
8483
		#$result["function"],當前執行的函數名稱
8484
		#必填的參數:
8485
		#$conf["position"],字串,爲要連結到的位置,若留空,將回自動變成"#",則可以搭配ajax傳值.	
8486
		$conf["link::show_link"]["position"]="webSocketT/hangFewSecs.php";
8487
		#$conf["linkName",字串,爲連結的顯示名稱
8488
		$conf["link::show_link"]["linkName"]="到別的頁面轉轉";
8489
		#可省略的參數:
8490
		#$conf["method"],字串,爲點選連結後,新畫面要如何呈現,可省略預設爲"_self",可用的選項有 _top(覆蓋目前的視窗來顯現新內容) _parent _self _blank(跳新視窗)
8491
		#$conf["method"]=""; 
8492
		#$conf["class"],字串,爲要套用的css超連節樣式,可省略.
8493
		#$conf["class"]="";
8494
		#$conf["id"],字串,超連結的id.
8495
		#$conf["id"]="";
8496
		#$conf["no_outline"],字串,是否要取消連結的框線,"false為不取消,"true"代表要取消,預設為"false".
8497
		#$conf["no_outline"]="";
8498
		$show_link=link::show_link($conf["link::show_link"]);
8499
		unset($conf["link::show_link"]);
8500
 
8501
		#串接超連結
8502
		$result["content"]=$result["content"].$show_link["content"];
8503
 
8504
		#設置用戶端的html與js語法
8505
		$result["content"]=$result["content"].$button["content"].$script;
8506
 
8507
		#設置執行正常
8508
		$result["status"]="true";
8509
 
8510
		#回傳結果
8511
		return $result;
8512
 
8513
		}#function chatRoomClientDemoV2 end	
8514
 
8515
	/*
8516
	#函式說明:
8517
	#擴充過的Ratchet聊天室用戶端js範例第三版,擁有在伺服器上執行指令的功能.
8518
	#回傳結果:
8519
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8520
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
8521
	#$result["function"],當前執行的函式名稱.		
8522
	#$result["content"],html.
8523
	#必填參數:
8524
	#無.
8525
	#可省略參數:
8526
	#無.
8527
	#參考資料:
8528
	#Ratchet官網=>http://socketo.me/
8529
	#用apache的proxy來判斷為哪個服務,導到對應的port裡面=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
8530
	#聊天室範例=>http://socketo.me/docs/hello-world
8531
	#備註:
8532
	#僅適用於https網頁透過wss連線到web socket server.	
8533
	*/
8534
	public static function chatRoomClientDemoV3(){
8535
 
8536
		#初始化要回傳的結果
8537
		$result=array();
8538
 
8539
		#初始化儲存html的變數
8540
		$result["content"]="";
8541
 
8542
		#取得當前執行的函數名稱
8543
		$result["function"]=__FUNCTION__;
8544
 
8545
		#初始化帳號密碼
8546
		$ac="";
8547
		$pw="";
8548
 
8549
		#如果存在 $_SESSION["account"]
8550
		if(isset($_SESSION["account"])){
8551
 
8552
			#取得帳戶
8553
			$ac=$_SESSION["account"];
8554
 
8555
			}#if end
8556
 
8557
		#如果 this->$passwordCol 不為 ""
8558
		if(Chat::$passwordCol!==""){
8559
 
8560
			#如果存在 $_SESSION["password"]
8561
			if(isset($_SESSION["password"])){
8562
 
8563
				#取得帳戶
8564
				$pw=$_SESSION["password"];
8565
 
8566
				}#if end
8567
 
8568
			}#if end
8569
 
8570
		#取得 server 的 ip
8571
		#涵式說明:
8572
		#取得伺服器的IP,並回傳。
8573
		#回傳的結果:
8574
		#$result,伺服端的IP
8575
		#備註:
8576
		#伺服端必須被 localhost 以外的網址連結才會出現正確的IP
8577
		$getServerIP=csInformation::getServerIP();
8578
 
8579
		#設置用戶端連線到webSocket的範例
8580
		$script="<script>
8581
 
8582
			//ready 後執行
8583
			$(document).ready(function()
8584
			{
8585
 
8586
				//取得帳號密碼
8587
				ac='".$ac."';
8588
				pw='".$pw."';
8589
 
8590
				//設置目前尚為連線到 webSocket Server
8591
				connected='false';
8592
 
8593
				//設置儲存應該要斷線的webSocket,避免太多連線在伺服器.
8594
				wbClosed='';
8595
 
8596
				//設置儲存webSocket連線的變數
8597
				wb='';
8598
 
8599
				//設置儲存msgId的變數
8600
				msgId='';
8601
 
8602
				//連線到 web socket
8603
				connWebSock();
8604
 
8605
			});
8606
 
8607
			//連線到 web socket
8608
			function connWebSock()
8609
			{
8610
				//建立 web socket 連線到 wss://localhost/wss/chatDemo
8611
				var conn = new WebSocket('wss://".$getServerIP."/wss/chatDemo');
8612
 
8613
				//當連線成功後
8614
				conn.onopen = function(e){
8615
 
8616
					//印出連線成功訊息到console
8617
					console.log(\"Connection established!\");
8618
 
8619
					//設置已經連上 webSocket server
8620
					connected='true';
8621
 
8622
					//另存 webSocket 物件
8623
					wb=conn;
8624
 
8625
					//如果存在前一個連線物件
8626
					if(wbClosed!==''){
8627
 
8628
						//提示關閉前個連線
8629
						console.log(\"close last connection!\");
8630
 
8631
						//關閉之前的連線
8632
						wbClosed.close();
8633
 
8634
						//清空
8635
						wbClosed='';
8636
 
8637
						}
8638
 
8639
					}
8640
 
8641
				//當有收到訊息時
8642
				conn.onmessage = function(e){
8643
 
8644
					//將訊息顯現在console
8645
					console.log(e.data);
8646
 
8647
					//將訊息寫到文字方框裡面
8648
					$('#history').val(e.data+'\\r\\n'+$('#history').val());
8649
 
8650
					//解析json字串
8651
					data=JSON.parse(e.data);
8652
 
8653
					//如果要要求login的訊息
8654
					if(data.type==='login'){
8655
 
8656
						//如果有查到帳號
8657
						if(ac!==''){
8658
 
8659
							//如果要求輸入帳號
8660
							if(data.data==='Please input your account! ex:account:ws1'){
8661
 
8662
								//傳送帳號
8663
								conn.send('account:'+ac);
8664
 
8665
								}
8666
 
8667
							//如果有查到密碼
8668
							if(pw!==''){
8669
 
8670
								//如果要求輸入密碼	
8671
								if(data.data==='Please input your password! ex:password:ws1'){
8672
 
8673
									//傳送密碼
8674
									conn.send('password:'+pw);
8675
 
8676
									}
8677
 
8678
								}
8679
 
8680
							//如果存在既有的msgId,且剛登入成功
8681
							if(msgId!=='' && data.data==='Login successfully!'){
8682
 
8683
								//設置既有的msgId
8684
								conn.send('msgId:'+msgId);
8685
 
8686
								}
8687
 
8688
							//反之如果登入成功
8689
							else if(data.data==='Login successfully!'){
8690
 
8691
								//查詢自己的msgId
8692
								conn.send('msgId?');
8693
 
8694
								}
8695
 
8696
							}
8697
 
8698
						}
8699
 
8700
					//如果收到的是 'msgId?'
8701
					else if(data.type==='msgId?'){
8702
 
8703
						//設置自己的msgId
8704
						msgId=data.data;
8705
 
8706
						}
8707
 
8708
					//如果收到的是 'msg' 類型
8709
					else if(data.type==='msg'){
8710
 
8711
						//回傳有收到訊息的確認
8712
						conn.send('mIndex:'+data.index);
8713
 
8714
						}
8715
 
8716
					//如果收到的是 'status' 類型	
8717
					else if(data.type==='status'){
8718
 
8719
						//如果內容為設置msgId失敗
8720
						if(data.data==='set msgId failed'){
8721
 
8722
							//查詢自己的msgId
8723
							conn.send('msgId?');
8724
 
8725
							}
8726
 
8727
						}
8728
 
8729
					//如果收到的是 'cmd' 類型	
8730
					else if(data.type==='cmd'){
8731
 
8732
						//將訊息顯現在console
8733
						//console.log(e.data);
8734
 
8735
						}
8736
 
8737
					}
8738
 
8739
				//當連線斷開後
8740
				conn.onclose = function(e){
8741
 
8742
					//設置未連上 webSocket server
8743
					connected='false';
8744
 
8745
					//如果有之前的連線物件
8746
					if(wb!==''){
8747
 
8748
						//儲存應該要斷線的webSocket,避免太多連線在伺服器.
8749
						wbClosed=wb;
8750
 
8751
						}
8752
 
8753
					//清空 webSocket 物件
8754
					wb='';
8755
 
8756
					//指定1秒刷新一次
8757
					setTimeout('connWebSock()',1000); 
8758
 
8759
					}
8760
 
8761
				}							
8762
 
8763
			//當按下送出按鈕
8764
			$('#send').on('click',function(){
8765
 
8766
				//如果已經連到 webSocket server 了
8767
				if(connected==='true'){
8768
 
8769
					//傳送訊息
8770
					wb.send($('#input').val());
8771
 
8772
					//清空訊息輸入欄
8773
					$('#input').val('');
8774
 
8775
					}
8776
 
8777
				});
8778
 
8779
			//重新整理頁面
8780
			function myrefresh(){
8781
 
8782
				//重新整理頁面
8783
				window.location.reload();
8784
 
8785
				}
8786
 
8787
			</script>";
8788
 
8789
		#設置存放歷史訊息的方框
8790
		#涵式說明:
8791
		#可以輸入文字的區塊
8792
		#回傳結果:
8793
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8794
		#$result["function"],當前執行的函數.
8795
		#$result["error"],錯誤訊息陣列.
8796
		#$result["content"],按鈕語法. 		
8797
		#必填的參數:
8798
		$conf["form::inputTextArea"]["name"]="history";#爲文字輸入框的名稱,供接收端辨識用。
8799
		$conf["form::inputTextArea"]["readOnly"]="true";#爲是否要爲唯讀,如果爲"true",則爲唯讀。反之則爲"false"。
8800
		#可省略的參數:
8801
		#$conf["id"],字串,文字區塊的id,供javaScript呼叫用.
8802
		$conf["form::inputTextArea"]["id"]="history";
8803
		#$conf["width"]="";#為輸入框的寬度,預設不指定.
8804
		#$conf["cols"]="";#爲文字輸入框的欄位數(寬),預設爲按照瀏覽器設定值。
8805
		#$conf["rows"]="";#爲文字輸入框的列數(高),預設爲按照瀏覽器設定值。
8806
		#$conf["maxInputLength"]="";#爲文字輸入的長度限制,預設無限制。
8807
		#$conf["defaultText"]="";#爲文字輸入框裏面的預設文字內容,預設是空的。
8808
		#$conf["class"]=;#爲要套用的css樣式。如果沒有指定 ,則採用預設的css樣式,"__inputTextAreaCssStyle",其屬性爲 "width:100%","height:120px","font-size:30px"
8809
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)...,須搭配$conf["jsSubmitActionTarget"]參數。
8810
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。
8811
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
8812
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
8813
		#$conf["formName"]="";#爲該表單的名稱
8814
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
8815
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
8816
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
8817
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
8818
		#$conf["comment"]="";
8819
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
8820
		#$conf["required"]="true";
8821
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
8822
		#$conf["placeholder"]="";
8823
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是",也可以看作新的一列開始,預設為"false".
8824
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是",也可以看成列裏面的元素開始,預設為"false".
8825
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是",也可以看成列裏面的元素結束,預設為"false".
8826
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是",也可以看作該列結束,預設為"false".
8827
		#參考資料來源:
8828
		#input=>http://www.w3schools.com/tags/tag_input.asp
8829
		$inputTextArea=form::inputTextArea($conf["form::inputTextArea"]);
8830
		unset($conf["form::inputTextArea"]);
8831
 
8832
		#如果建立文字方框失敗
8833
		if($inputTextArea["status"]==="false"){
8834
 
8835
			#設置執行失敗
8836
			$result["status"]="false";
8837
 
8838
			#設置執行錯誤訊息
8839
			$result["error"]=$inputTextArea;
8840
 
8841
			#回傳結果
8842
			return $result;
8843
 
8844
			}#if end	
8845
 
8846
		#串連文字訊息方框
8847
		$result["content"]=$result["content"].$inputTextArea["content"];
8848
 
8849
		#設置填寫要傳送的訊息輸入方框
8850
		#涵式說明:
8851
		#可以輸入文字的表單
8852
		#回傳的結果:
8853
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8854
		#$result["function"],當前執行的函數.
8855
		#$result["error"],錯誤訊息陣列.
8856
		#$result["content"],按鈕語法. 
8857
		#必填的參數
8858
		$conf["form::inputText"]["name"]="data";#爲該文字輸入框的名稱,用於讓接收頁面讀取的名稱。
8859
		$conf["form::inputText"]["readOnly"]="false";#爲該文字框是否可以填寫資料,若要只能觀看不能填寫,那麼就必須將其值設爲"true",反之要設爲"false"
8860
		#可省略的參數:
8861
		#$conf["width"]="";#爲文字框的外觀長度,預設為"100%".
8862
		#$conf["maxInputLength"]="";#爲可輸入的最大位元長度,預設不限制。
8863
		#$conf["autoFocus"]="true";#是否為將填寫的指標移到該表單,"true"代表要,預設為"false".
8864
		#$conf["value"]="";#爲該文字框預設要顯示的文字,預設爲""。	
8865
		#$conf["class"]="";#爲要套用的css樣式,若省略,則會套用預設的 "__inputTextCssStyle" 樣式,其屬性爲 "width:100%","font-size:30px"
8866
		#$conf["jsActivitor"]="";#爲觸發js的條件,可以是"onChange"(已改變內容時)、"onClick"(按下按鈕時)、"onkeyup"(當鍵盤按下放開後)、"onmouseover"(當滑鼠移過去的時候)...,須搭配$conf["jsSubmitActionTarget"]參數。
8867
		#$conf["jsAction"]="";#爲該js是要做什麼,可以是"document.testForm.submit()"(傳送名爲testForm的表單內容)...,須搭配$conf["jsActivitor"]參數。		
8868
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
8869
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
8870
		#$conf["formStart"]="true";#爲是否要以<form>開頭,"true"表示"是",也可以看成表單的開始,預設為"false".
8871
		#$conf["formAction"]="";#表單遞交的目的地,若$conf["formStart"]為"true",則該參數不能省略.
8872
		#$conf["formName"]="";#爲該表單的名稱
8873
		#$conf["formMethod"]="";#爲傳輸的方法,若沒設定則預設爲post,其他可用的參數爲get。
8874
		#$conf["formTarget"]="";#為顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。
8875
		#$conf["tableStart"]="true";#爲該表單是否要以<table>開始。"true"爲是,預設為"false".
8876
		#$conf["tableClass"]="";#表格要套用的css樣式,若爲"__withoutBorder"的話則套用無框線的預設樣式;若爲"__withBorder"的話,則爲有框線的預設樣式,預設為"__withoutBorder".
8877
		#$conf["formEnd"]="true";#爲是否要以<form>結尾,"true"表示"是",也可以看成表單的結束,預設為"false".
8878
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
8879
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
8880
		#$conf["tableEnd"]="true";#爲該表單是否要以</table>結尾,"true"爲是,預設為"false".
8881
		#$conf["autocomplete"],字串,是否依據使用者過往輸入的記錄來提示可能要的輸入內容,"on"為啟用,"off"為停用,預設為"on".
8882
		#$conf["autocomplete"]="off";
8883
		#$conf["required"],字串,該欄位是否必填,"true"為必填,"false"為可留空,預設為"false".
8884
		#$conf["required"]="true";
8885
		#$conf["comment"],字串,輸入方框上面要放哪些註解文字,亦即用label來呈現,同時指定"for"屬性的數值為當前"input"標籤的id,意即參數"name"的內容.
8886
		#$conf["comment"]="";
8887
		#$conf["placeholder"],字串,當沒有內容時要顯示的內容.
8888
		#$conf["placeholder"]="";
8889
		#$conf["br"],字串,"true"代表最後要換行,預設為"false".
8890
		#$conf["br"]="true";
8891
		#$conf["p"],字串,"true"代表最後要空一行,預設為"false".
8892
		#$conf["p"]="true";
8893
		#$conf["id"],字串,該元素的id,預設不使用.
8894
		$conf["form::inputText"]["id"]="input";
8895
		#參考資料來源:
8896
		#input=>http://www.w3schools.com/tags/tag_input.asp
8897
		$inputText=form::inputText($conf["form::inputText"]);
8898
		unset($conf["form::inputText"]);
8899
 
8900
		#如果輸入文字框失敗
8901
		if($inputText["status"]==="false"){
8902
 
8903
			#設置執行失敗
8904
			$result["status"]="false";
8905
 
8906
			#設置執行錯誤訊息
8907
			$result["error"]=$inputText;
8908
 
8909
			#回傳結果
8910
			return $result;
8911
 
8912
			}#if end	
8913
 
8914
		#文字輸入框
8915
		$result["content"]=$result["content"].$inputText["content"];
8916
 
8917
		#設置觸發的按鈕
8918
		#函式說明:
8919
		#放置按鈕
8920
		#回傳結果:
8921
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8922
		#$result["function"],當前執行的函數.
8923
		#$result["error"],錯誤訊息陣列.
8924
		#$result["content"],按鈕語法. 
8925
		#必要的參數:
8926
		$conf["form::button"]["buttonDisplayValue"]="Send";#爲按鈕上顯示的文字。
8927
		#可省略的參數:
8928
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
8929
			#其屬性爲   "width","height","font-size","text-align"
8930
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
8931
		#$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
8932
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
8933
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
8934
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
8935
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
8936
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
8937
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
8938
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
8939
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
8940
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
8941
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
8942
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
8943
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
8944
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
8945
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
8946
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
8947
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
8948
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
8949
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
8950
		#$conf["formId"],字串,表單的id.
8951
		#$conf["formId"]="";
8952
		#$conf["buttonId"],字串,按鈕的id.
8953
		$conf["form::button"]["buttonId"]="send";
8954
		#參考資料來源:
8955
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
8956
		$button=form::button($conf["form::button"]);
8957
		unset($conf["form::button"]);
8958
 
8959
		#如果建立按鈕失敗
8960
		if($button["status"]==="false"){
8961
 
8962
			#設置執行失敗
8963
			$result["status"]="false";
8964
 
8965
			#設置執行錯誤訊息
8966
			$result["error"]=$button;
8967
 
8968
			#回傳結果
8969
			return $result;
8970
 
8971
			}#if end	
8972
 
8973
		#建立跳到別的頁面的連結
8974
		#涵式說明:
8975
		#放置超鏈結
8976
		#回傳的結果:
8977
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
8978
		#$result["error"],錯誤訊息
8979
		#$result["content"],語法
8980
		#$result["function"],當前執行的函數名稱
8981
		#必填的參數:
8982
		#$conf["position"],字串,爲要連結到的位置,若留空,將回自動變成"#",則可以搭配ajax傳值.	
8983
		$conf["link::show_link"]["position"]="webSocketT/hangFewSecs.php";
8984
		#$conf["linkName",字串,爲連結的顯示名稱
8985
		$conf["link::show_link"]["linkName"]="到別的頁面轉轉";
8986
		#可省略的參數:
8987
		#$conf["method"],字串,爲點選連結後,新畫面要如何呈現,可省略預設爲"_self",可用的選項有 _top(覆蓋目前的視窗來顯現新內容) _parent _self _blank(跳新視窗)
8988
		#$conf["method"]=""; 
8989
		#$conf["class"],字串,爲要套用的css超連節樣式,可省略.
8990
		#$conf["class"]="";
8991
		#$conf["id"],字串,超連結的id.
8992
		#$conf["id"]="";
8993
		#$conf["no_outline"],字串,是否要取消連結的框線,"false為不取消,"true"代表要取消,預設為"false".
8994
		#$conf["no_outline"]="";
8995
		$show_link=link::show_link($conf["link::show_link"]);
8996
		unset($conf["link::show_link"]);
8997
 
8998
		#串接超連結
8999
		$result["content"]=$result["content"].$show_link["content"];
9000
 
9001
		#設置用戶端的html與js語法
9002
		$result["content"]=$result["content"].$button["content"].$script;
9003
 
9004
		#設置執行正常
9005
		$result["status"]="true";
9006
 
9007
		#回傳結果
9008
		return $result;
9009
 
9010
		}#function chatRoomClientDemoV3 end	
9011
 
9012
	/*
9013
	#函式說明:
9014
	#擴充過的Ratchet聊天室silder用戶端js範例,可以不跟ajax排隊.
9015
	#回傳結果:
9016
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9017
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
9018
	#$result["function"],當前執行的函式名稱.		
9019
	#$result["content"],html.
9020
	#必填參數:
9021
	#無.
9022
	#可省略參數:
9023
	#無.
9024
	#參考資料:
9025
	#Ratchet官網=>http://socketo.me/
9026
	#用apache的proxy來判斷為哪個服務,導到對應的port裡面=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
9027
	#聊天室範例=>http://socketo.me/docs/hello-world
9028
	#備註:
9029
	#僅適用於https網頁透過wss連線到web socket server.	
9030
	*/
9031
	public static function soldierClientDemo(){
9032
 
9033
		#初始化要回傳的結果
9034
		$result=array();
9035
 
9036
		#初始化儲存html的變數
9037
		$result["content"]="";
9038
 
9039
		#取得當前執行的函數名稱
9040
		$result["function"]=__FUNCTION__;
9041
 
9042
		#初始化帳號密碼
9043
		$ac="";
9044
		$pw="";
9045
 
9046
		#如果存在 $_SESSION["account"]
9047
		if(isset($_SESSION["account"])){
9048
 
9049
			#取得帳戶
9050
			$ac=$_SESSION["account"];
9051
 
9052
			}#if end
9053
 
9054
		#如果 this->$passwordCol 不為 ""
9055
		if(Chat::$passwordCol!==""){
9056
 
9057
			#如果存在 $_SESSION["password"]
9058
			if(isset($_SESSION["password"])){
9059
 
9060
				#取得帳戶
9061
				$pw=$_SESSION["password"];
9062
 
9063
				}#if end
9064
 
9065
			}#if end
9066
 
9067
		#取得 server 的 ip
9068
		#涵式說明:
9069
		#取得伺服器的IP,並回傳。
9070
		#回傳的結果:
9071
		#$result,伺服端的IP
9072
		#備註:
9073
		#伺服端必須被 localhost 以外的網址連結才會出現正確的IP
9074
		$getServerIP=csInformation::getServerIP();
9075
 
9076
		#設置用戶端連線到webSocket的範例
9077
		$script="<script>
9078
 
9079
			//ready 後執行
9080
			$(document).ready(function(){
9081
 
9082
				//取得帳號密碼
9083
				ac='".$ac."';
9084
				pw='".$pw."';
9085
 
9086
				//設置目前尚為連線到 webSocket Server
9087
				connected='false';
9088
 
9089
				//設置儲存應該要斷線的webSocket,避免太多連線在伺服器.
9090
				wbClosed='';
9091
 
9092
				//設置儲存webSocket連線的變數
9093
				wb='';
9094
 
9095
				//告訴server要執行的指令
9096
				cmd='ls -al';
9097
 
9098
				//連線到 web socket
9099
				connWebSock();
9100
 
9101
				//榜定按鈕事件
9102
				buttonEvent();
9103
 
9104
				});
9105
 
9106
			//連線到 web socket
9107
			function connWebSock()
9108
			{
9109
				//建立 web socket 連線到 wss://localhost/wss/chatDemo
9110
				var conn = new WebSocket('wss://".$getServerIP."/wss/chatDemo');
9111
 
9112
				//當連線成功後
9113
				conn.onopen = function(e){
9114
 
9115
					//印出連線成功訊息到console
9116
					console.log(\"Connection established!\");
9117
 
9118
					//設置已經連上 webSocket server
9119
					connected='true';
9120
 
9121
					//另存 webSocket 物件
9122
					wb=conn;
9123
 
9124
					//如果存在前一個連線物件
9125
					if(wbClosed!==''){
9126
 
9127
						//提示關閉前個連線
9128
						console.log(\"close last connection!\");
9129
 
9130
						//關閉之前的連線
9131
						wbClosed.close();
9132
 
9133
						//清空
9134
						wbClosed='';
9135
 
9136
						}
9137
 
9138
					}
9139
 
9140
				//當有收到訊息時
9141
				conn.onmessage = function(e){
9142
 
9143
					//將訊息顯現在console
9144
					console.log(e.data);
9145
 
9146
					//解析json字串
9147
					data=JSON.parse(e.data);
9148
 
9149
					//如果要要求login的訊息
9150
					if(data.type==='login'){
9151
 
9152
						//如果有查到帳號
9153
						if(ac!==''){
9154
 
9155
							//如果要求輸入帳號
9156
							if(data.data==='Please input your account! ex:account:ws1'){
9157
 
9158
								//傳送帳號
9159
								conn.send('account:'+ac);
9160
 
9161
								}
9162
 
9163
							//如果有查到密碼
9164
							if(pw!==''){
9165
 
9166
								//如果要求輸入密碼	
9167
								if(data.data==='Please input your password! ex:password:ws1'){
9168
 
9169
									//傳送密碼
9170
									conn.send('password:'+pw);
9171
 
9172
									}
9173
 
9174
								}
9175
 
9176
							}
9177
 
9178
						//反之如果登入成功
9179
						else if(data.data==='Login successfully!'){
9180
 
9181
							//設置已經驗證成功
9182
							connected='true';
9183
 
9184
							}
9185
 
9186
						}
9187
 
9188
					//如果收到的是 'cmd' 類型	
9189
					else if(data.type==='cmd'){
9190
 
9191
						//將訊息顯現在console
9192
						//console.log(data.data);
9193
 
9194
						}
9195
 
9196
					}
9197
 
9198
				//當連線斷開後
9199
				conn.onclose = function(e){
9200
 
9201
					//設置未連上 webSocket server
9202
					connected='false';
9203
 
9204
					//如果有之前的連線物件
9205
					if(wb!==''){
9206
 
9207
						//儲存應該要斷線的webSocket,避免太多連線在伺服器.
9208
						wbClosed=wb;
9209
 
9210
						}
9211
 
9212
					//清空 webSocket 物件
9213
					wb='';
9214
 
9215
					//指定1秒刷新一次
9216
					setTimeout('connWebSock()',1000); 
9217
 
9218
					}
9219
 
9220
				}							
9221
 
9222
			//榜定下達命令的按鈕事件
9223
			function buttonEvent(){
9224
 
9225
				//當按下送出按鈕
9226
				$('#send').on('click',function(){
9227
 
9228
					//如果已經連到 webSocket server 了
9229
					if(connected==='true'){
9230
 
9231
						//傳送訊息
9232
						wb.send('cmd:'+cmd);
9233
 
9234
						}
9235
 
9236
					});
9237
 
9238
				//榜定ajax要求	
9239
				$('#run').on('click',function(){
9240
 
9241
					$.ajax({
9242
 
9243
						url: 'webSocketT/sleep.php',
9244
						type:'GET',
9245
						async:true,
9246
						data:{},
9247
						success:function(data, status){
9248
 
9249
							console.log(data.toSource());
9250
 
9251
							}
9252
 
9253
						});
9254
 
9255
					});
9256
 
9257
				}
9258
 
9259
			</script>";		
9260
 
9261
		#串接script語法
9262
		$result["content"]=$result["content"].$script;
9263
 
9264
		#設置觸發ajax的按鈕
9265
		#函式說明:
9266
		#放置按鈕
9267
		#回傳結果:
9268
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9269
		#$result["function"],當前執行的函數.
9270
		#$result["error"],錯誤訊息陣列.
9271
		#$result["content"],按鈕語法. 
9272
		#必要的參數:
9273
		$conf["form::button"]["buttonDisplayValue"]="ajax";#爲按鈕上顯示的文字。
9274
		#可省略的參數:
9275
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
9276
			#其屬性爲   "width","height","font-size","text-align"
9277
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
9278
		#$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
9279
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
9280
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
9281
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
9282
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
9283
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
9284
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
9285
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
9286
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
9287
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
9288
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
9289
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
9290
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
9291
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
9292
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
9293
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
9294
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
9295
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
9296
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
9297
		#$conf["formId"],字串,表單的id.
9298
		#$conf["formId"]="";
9299
		#$conf["buttonId"],字串,按鈕的id.
9300
		$conf["form::button"]["buttonId"]="run";
9301
		#參考資料來源:
9302
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
9303
		$button=form::button($conf["form::button"]);
9304
		unset($conf["form::button"]);
9305
 
9306
		#如果建立按鈕失敗
9307
		if($button["status"]==="false"){
9308
 
9309
			#設置執行失敗
9310
			$result["status"]="false";
9311
 
9312
			#設置執行錯誤訊息
9313
			$result["error"]=$button;
9314
 
9315
			#回傳結果
9316
			return $result;
9317
 
9318
			}#if end
9319
 
9320
		#串接按鈕語法
9321
		$result["content"]=$result["content"].$button["content"];
9322
 
9323
		#設置觸發命令的按鈕
9324
		#函式說明:
9325
		#放置按鈕
9326
		#回傳結果:
9327
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9328
		#$result["function"],當前執行的函數.
9329
		#$result["error"],錯誤訊息陣列.
9330
		#$result["content"],按鈕語法. 
9331
		#必要的參數:
9332
		$conf["form::button"]["buttonDisplayValue"]="Send cmd";#爲按鈕上顯示的文字。
9333
		#可省略的參數:
9334
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
9335
			#其屬性爲   "width","height","font-size","text-align"
9336
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
9337
		#$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
9338
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
9339
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
9340
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
9341
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
9342
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
9343
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
9344
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
9345
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
9346
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
9347
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
9348
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
9349
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
9350
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
9351
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
9352
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
9353
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
9354
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
9355
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
9356
		#$conf["formId"],字串,表單的id.
9357
		#$conf["formId"]="";
9358
		#$conf["buttonId"],字串,按鈕的id.
9359
		$conf["form::button"]["buttonId"]="send";
9360
		#參考資料來源:
9361
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
9362
		$button=form::button($conf["form::button"]);
9363
		unset($conf["form::button"]);
9364
 
9365
		#如果建立按鈕失敗
9366
		if($button["status"]==="false"){
9367
 
9368
			#設置執行失敗
9369
			$result["status"]="false";
9370
 
9371
			#設置執行錯誤訊息
9372
			$result["error"]=$button;
9373
 
9374
			#回傳結果
9375
			return $result;
9376
 
9377
			}#if end
9378
 
9379
		#串接按鈕語法
9380
		$result["content"]=$result["content"].$button["content"];
9381
 
9382
		#設置執行正常
9383
		$result["status"]="true";
9384
 
9385
		#回傳結果
9386
		return $result;
9387
 
9388
		}#function soldierClientDemo end
9389
 
9390
	/*
9391
	#函式說明:
9392
	#擴充過的Ratchet的聊天室soilier用戶端與伺服端範例,port為8080.
9393
	#回傳結果:
9394
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9395
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
9396
	#$result["function"],當前執行的函式名稱.		
9397
	#必填參數:
9398
	#$conf["fileArgu"],字串,__FILE__的內容.
9399
	$conf["fileArgu"]=__FILE__;
9400
	#可省略參數:
9401
	#$conf["disReg"],字串,是否要取消apache的passProxy檢查與設定,預設為"false"不取消,"true"為取消.
9402
	#$conf["disReg"]="";
9403
	#參考資料:
9404
	#Ratchet官網=>http://socketo.me/
9405
	#聊天室範例=>http://socketo.me/docs/hello-world
9406
	#備註:
9407
	#必須要在命令列環境下執行一次,建立webSocket Server後,再於網頁端執行即可產生webSocket Client端的code.
9408
	#僅適用於https網頁透過wss連線到web socket server.
9409
	*/
9410
	public static function soldierDemo(&$conf){
9411
 
9412
		#初始化要回傳的結果
9413
		$result=array();
9414
 
9415
		#取得當前執行的函數名稱
9416
		$result["function"]=__FUNCTION__;
9417
 
9418
		#涵式說明:
9419
		#判斷當前環境為web還是cmd
9420
		#回傳結果:
9421
		#$result,"web"或"cmd"
9422
		if(csInformation::getEnv()==="web"){
9423
 
9424
			#建立 web socket client 的 js 語法
9425
			#函式說明:
9426
			#聊天室用戶端js範例
9427
			#回傳結果:
9428
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9429
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
9430
			#$result["function"],當前執行的函式名稱.		
9431
			#$result["content"],js語法.
9432
			#參考資料:
9433
			#Ratchet官網=>http://socketo.me/
9434
			#聊天室範例=>http://socketo.me/docs/hello-world
9435
			$soldierClientDemo=webSock::soldierClientDemo();
9436
 
9437
			#如果建立聊天室用戶端失敗
9438
			if($soldierClientDemo["status"]==="false"){
9439
 
9440
				#設置執行失敗
9441
				$result["status"]="false";
9442
 
9443
				#設置執行錯誤訊息
9444
				$result["error"]=$soldierClientDemo;
9445
 
9446
				#回傳結果
9447
				return $result;
9448
 
9449
				}#if end
9450
 
9451
			#取得聊天室的語法
9452
			$result["content"]=$soldierClientDemo["content"];
9453
 
9454
			#設置執行正常
9455
			$result["status"]="true";
9456
 
9457
			#回傳結果
9458
			return $result;
9459
 
9460
			}#if end
9461
 
9462
		#如果沒有參數
9463
		if(func_num_args()==0){
9464
 
9465
			#設置執行失敗
9466
			$result["status"]="false";
9467
 
9468
			#設置執行錯誤訊息
9469
			$result["error"]="函數".$result["function"]."需要參數";
9470
 
9471
			#回傳結果
9472
			return $result;
9473
 
9474
			}#if end
9475
 
9476
		#如果沒有參數
9477
		if(func_num_args()==0){
9478
 
9479
			#設置執行失敗
9480
			$result["status"]="false";
9481
 
9482
			#設置執行錯誤訊息
9483
			$result["error"]="函數".$result["function"]."需要參數";
9484
 
9485
			#回傳結果
9486
			return $result;
9487
 
9488
			}#if end
9489
 
9490
		#取得參數
9491
		$result["argu"]=$conf;
9492
 
9493
		#如果 $conf 不為陣列
9494
		if(gettype($conf)!=="array"){
9495
 
9496
			#設置執行失敗
9497
			$result["status"]="false";
9498
 
9499
			#設置執行錯誤訊息
9500
			$result["error"][]="\$conf變數須為陣列形態";
9501
 
9502
			#如果傳入的參數為 null
9503
			if($conf===null){
9504
 
9505
				#設置執行錯誤訊息
9506
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
9507
 
9508
				}#if end
9509
 
9510
			#回傳結果
9511
			return $result;
9512
 
9513
			}#if end
9514
 
9515
		#檢查參數
9516
		#函式說明:
9517
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
9518
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9519
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
9520
		#$result["function"],當前執行的函式名稱.
9521
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
9522
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
9523
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
9524
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
9525
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
9526
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
9527
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
9528
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
9529
		#必填寫的參數:
9530
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
9531
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
9532
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
9533
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
9534
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
9535
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
9536
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
9537
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
9538
		#可以省略的參數:
9539
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
9540
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
9541
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
9542
		#$conf["canNotBeEmpty"]=array();
9543
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
9544
		#$conf["canBeEmpty"]=array();
9545
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
9546
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
9547
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
9548
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("disReg");
9549
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
9550
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
9551
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
9552
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false");
9553
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
9554
		#$conf["arrayCountEqualCheck"][]=array();
9555
		#參考資料來源:
9556
		#array_keys=>http://php.net/manual/en/function.array-keys.php
9557
		#建議:
9558
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
9559
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
9560
		unset($conf["variableCheck::checkArguments"]);
9561
 
9562
		#如果檢查參數失敗
9563
		if($checkArguments["status"]==="false"){
9564
 
9565
			#設置執行失敗
9566
			$result["status"]="false";
9567
 
9568
			#設置執行錯誤訊息
9569
			$result["error"]=$checkArguments;
9570
 
9571
			#回傳結果
9572
			return $result;
9573
 
9574
			}#if end
9575
 
9576
		#如果參數檢查不通過
9577
		if($checkArguments["passed"]==="false"){
9578
 
9579
			#設置執行失敗
9580
			$result["status"]="false";
9581
 
9582
			#設置執行錯誤訊息
9583
			$result["error"]=$checkArguments;
9584
 
9585
			#回傳結果
9586
			return $result;
9587
 
9588
			}#if end
9589
 
9590
		#執行到這邊代表是命令列環境
9591
 
9592
		#如果沒有要取消設定 passProxy
9593
		if($conf["disReg"]==="false"){
9594
 
9595
			#確認設定 passProxy
9596
			#函式說明:
9597
			#註冊聊天室範例的 passProxy 設定,本函數會用root帳戶去新增.
9598
			#會在 /etc/httpd/conf/httpd.conf 檔案裡面加上以下內容
9599
			##Enable the mod_proxy modules in the HTTPD
9600
			#LoadModule proxy_module modules/mod_proxy.so
9601
			#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
9602
			#
9603
			##ProxyPass
9604
			##If requeted web address is begin with (ws://hostdns)/wss/chatDemo, then redirect to ws://localhost:8080
9605
			#ProxyPass /wss/chatDemo ws://localhost:8080
9606
			#回傳結果:
9607
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9608
			#$reuslt["error"],執行不正常結束的錯訊息陣列.
9609
			#$result["function"],當前執行的函式名稱.
9610
			#必填參數:
9611
			#$conf["fileArgu"],字串,__FILE__的內容.
9612
			$conf["webSock::registerChatDemo"]["fileArgu"]=$conf["fileArgu"];
9613
			#可省略參數:
9614
			#$conf["rootPasswd"],字串,root帳戶的密碼,預設為"password".
9615
			#$conf["rootPasswd"]="password";
9616
			#$conf["httpd.conf"],字串,apache設定檔的路徑與名稱,預設為"/etc/httpd/conf/httpd.conf".
9617
			#$conf["httpd.conf"]="/etc/httpd/conf/httpd.conf";		
9618
			#備註:
9619
			#僅能在命令列環境下執行.
9620
			#改變暫存檔案權限的功能異常.
9621
			#參考資料:
9622
			#用apache的passProxy來識別服務並轉到正確的port=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
9623
			$registerChatDemo=webSock::registerChatDemo($conf["webSock::registerChatDemo"]);
9624
			unset($conf["webSock::registerChatDemo"]);
9625
 
9626
			#如果註冊 ChatDemo 服務失敗
9627
			if($registerChatDemo["status"]==="false"){
9628
 
9629
				#設置執行失敗
9630
				$result["status"]="false";
9631
 
9632
				#設置執行錯誤訊息
9633
				$result["error"]=$registerChatDemo;
9634
 
9635
				#回傳結果
9636
				return $result;
9637
 
9638
				}#if end
9639
 
9640
			}#if end
9641
 
9642
		#函式說明:
9643
		#擴充過的Ratchet聊天室伺服端範例,port為8080.
9644
		#回傳結果:
9645
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9646
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
9647
		#$result["function"],當前執行的函式名稱.		
9648
		#參考資料:
9649
		#Ratchet官網=>http://socketo.me/
9650
		#聊天室範例=>http://socketo.me/docs/hello-world
9651
		#備註:
9652
		#必須要在命令列環境下執行才行.
9653
		$conf["webSock"]["soldierServerDemo"]["fileArgu"]=$conf["fileArgu"];
9654
		$soldierServerDemo=webSock::soldierServerDemo($conf["webSock"]["soldierServerDemo"]);
9655
		unset($conf["webSock"]["soldierServerDemo"]);	
9656
 
9657
		#如果運行 chatRoomServerDemo 失敗
9658
		if($soldierServerDemo["status"]==="false"){
9659
 
9660
			#設置執行失敗
9661
			$result["status"]="false";
9662
 
9663
			#設置執行錯誤訊息
9664
			$result["error"]=$soldierServerDemo;
9665
 
9666
			#回傳結果
9667
			return $result;
9668
 
9669
			}#if end	
9670
 
9671
		#設置執行正常
9672
		$result["status"]="true";
9673
 
9674
		#回傳結果	
9675
		return $result;
9676
 
9677
		}#function soldierDemo end
9678
 
9679
	/*
9680
	#函式說明:
9681
	#註冊Ratchet聊天室範例的 passProxy 設定,本函數會用root帳戶去新增.
9682
	#會在 /etc/httpd/conf/httpd.conf 檔案裡面加上以下內容
9683
	##Enable the mod_proxy modules in the HTTPD
9684
	#LoadModule proxy_module modules/mod_proxy.so
9685
	#LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
9686
	#
9687
	##ProxyPass
9688
	##If requeted web address is begin with (ws://hostdns)/wss/chatDemo, then redirect to ws://localhost:8080
9689
	#ProxyPass /wss/chatDemo ws://localhost:8080
9690
	#回傳結果:
9691
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9692
	#$reuslt["error"],執行不正常結束的錯訊息陣列.
9693
	#$result["function"],當前執行的函式名稱.
9694
	#必填參數:
9695
	#$conf["fileArgu"],字串,__FILE__的內容.
9696
	$conf["fileArgu"]=__FILE__;
9697
	#可省略參數:
9698
	#$conf["rootPasswd"],字串,root帳戶的密碼,預設為"password".
9699
	#$conf["rootPasswd"]="password";
9700
	#$conf["httpd.conf"],字串,apache設定檔的路徑與名稱,預設為"/etc/httpd/conf/httpd.conf".
9701
	#$conf["httpd.conf"]="/etc/httpd/conf/httpd.conf";	
9702
	#備註:
9703
	#僅能在命令列環境下執行.
9704
	#改變暫存檔案權限的功能異常.
9705
	#參考資料:
9706
	#用apache的passProxy來識別服務並轉到正確的port=>https://groups.google.com/forum/#!topic/ratchet-php/dj-PgPPO_J0
9707
	*/
9708
	public static function registerChatDemo(&$conf){
9709
 
9710
		#初始化要回傳的結果
9711
		$result=array();
9712
 
9713
		#取得當前執行的函數名稱
9714
		$result["function"]=__FUNCTION__;
9715
 
9716
		#涵式說明:
9717
		#判斷當前環境為web還是cmd
9718
		#回傳結果:
9719
		#$result,"web"或"cmd"
9720
		if(csInformation::getEnv()=="web"){
9721
 
9722
			#設置執行失敗
9723
			$result["status"]="false";
9724
 
9725
			#設置執行錯誤訊息
9726
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
9727
 
9728
			#回傳結果
9729
			return $result;
9730
 
9731
			}#if end
9732
 
9733
		#取得參數
9734
		$result["argu"]=$conf;
9735
 
9736
		#如果 $conf 不為陣列
9737
		if(gettype($conf)!="array"){
9738
 
9739
			#設置執行失敗
9740
			$result["status"]="false";
9741
 
9742
			#設置執行錯誤訊息
9743
			$result["error"][]="\$conf變數須為陣列形態";
9744
 
9745
			#如果傳入的參數為 null
9746
			if($conf==null){
9747
 
9748
				#設置執行錯誤訊息
9749
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
9750
 
9751
				}#if end
9752
 
9753
			#回傳結果
9754
			return $result;
9755
 
9756
			}#if end
9757
 
9758
		#檢查參數
9759
		#函式說明:
9760
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
9761
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9762
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
9763
		#$result["function"],當前執行的函式名稱.
9764
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
9765
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
9766
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
9767
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
9768
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
9769
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
9770
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
9771
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
9772
		#必填寫的參數:
9773
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
9774
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
9775
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
9776
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
9777
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
9778
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
9779
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
9780
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
9781
		#可以省略的參數:
9782
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
9783
		#$conf["canBeEmptyString"]="false";
9784
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
9785
		#$conf["canNotBeEmpty"]=array();
9786
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
9787
		#$conf["canBeEmpty"]=array();
9788
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
9789
		#$conf["skipableVariableCanNotBeEmpty"]=array();
9790
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
9791
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("httpd.conf","rootPasswd");
9792
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
9793
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
9794
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
9795
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("/etc/httpd/conf/httpd.conf","password");
9796
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
9797
		#$conf["arrayCountEqualCheck"][]=array();
9798
		#參考資料來源:
9799
		#array_keys=>http://php.net/manual/en/function.array-keys.php
9800
		#建議:
9801
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
9802
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
9803
		unset($conf["variableCheck::checkArguments"]);
9804
 
9805
		#如果檢查參數失敗
9806
		if($checkArguments["status"]==="false"){
9807
 
9808
			#設置執行失敗
9809
			$result["status"]="false";
9810
 
9811
			#設置執行錯誤訊息
9812
			$result["error"]=$checkArguments;
9813
 
9814
			#回傳結果
9815
			return $result;
9816
 
9817
			}#if end
9818
 
9819
		#如果參數檢查不通過
9820
		if($checkArguments["passed"]==="false"){
9821
 
9822
			#設置執行失敗
9823
			$result["status"]="false";
9824
 
9825
			#設置執行錯誤訊息
9826
			$result["error"]=$checkArguments;
9827
 
9828
			#回傳結果
9829
			return $result;
9830
 
9831
			}#if end
9832
 
9833
		#取得root密碼
9834
		#函式說明:
9835
		#藉由使用者的輸入來確認root使用者密碼是否正確.
9836
		#回傳結果:
9837
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
9838
		#$result["function"],當前執行的函數名稱.
9839
		#$result["error"],錯誤訊息陣列.
9840
		#$result["content"],root密碼.		
9841
		#必填參數:
9842
		#$conf["fileArgu"],字串,__FILE__的內容.
9843
		$conf["cmd::validRootPasswd"]["fileArgu"]=$conf["fileArgu"];
9844
		#可省略參數:
9845
		#$conf["password"],字串,用於驗證root使用者的密碼,若未設定則預設為"rootPasswd".
9846
		$conf["cmd::validRootPasswd"]["password"]=$conf["rootPasswd"];
9847
		#備註:
9848
		#建構中
9849
		$validRootPasswd=cmd::validRootPasswd($conf["cmd::validRootPasswd"]);
9850
		unset($conf["cmd::validRootPasswd"]);
9851
 
9852
		#如果取得root密碼失敗
9853
		if($validRootPasswd["status"]==="false"){
9854
 
9855
			#設置執行失敗
9856
			$result["status"]="false";
9857
 
9858
			#設置執行錯誤訊息
9859
			$result["error"]=$validRootPasswd;
9860
 
9861
			#回傳結果
9862
			return $result;
9863
 
9864
			}#if end
9865
 
9866
		#取得root密碼
9867
		$conf["rootPasswd"]=$validRootPasswd["content"];
9868
 
9869
		#檢查httpd設定檔案有無設定載入 proxy 模組與設定 ProxyPass
9870
		#函式說明:
9871
		#取得檔的內容並以列為單位搜尋多個關鍵字.
9872
		#回傳結果:
9873
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9874
		#$result["error"],錯誤訊息.
9875
		#$result["function"],當前執行的函數名稱.
9876
		#$result["content"],取得讀取到的檔案內容.
9877
		#$result["founded"],每個關鍵字串尋找的結果,"true"代表有找到,"false"代表沒有找到.
9878
		#$result["foundedLine"],每個找到的關鍵字是在第幾列找到的,key值與$result["founded"]的key值一樣.
9879
		#必填的參數:
9880
		#$conf["file"],字串,檔案的位置與名稱.
9881
		$conf["cmd::checkFileKeyStrLBL"]["file"]=$conf["httpd.conf"];
9882
		#$conf["keyStr"],陣列字串,要搜尋每列有哪些關鍵字串.
9883
		$conf["cmd::checkFileKeyStrLBL"]["keyStr"]=array("LoadModule proxy_module modules/mod_proxy.so","LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so","ProxyPass /wss/chatDemo ws://localhost:8080");	
9884
		#可省略參數:
9885
		#$conf["username"],字串,要以哪個使用者來執行,預設為執行該php程式的使用者.
9886
		$conf["cmd::checkFileKeyStrLBL"]["username"]="root";
9887
		#$conf["password"],字串,使用者對應的密碼,預設不使用.
9888
		$conf["cmd::checkFileKeyStrLBL"]["password"]=$conf["rootPasswd"];
9889
		#$conf["fileArgu"],字串,__FILE__的內容,預設為當前檔案的位置.
9890
		$conf["cmd::checkFileKeyStrLBL"]["fileArgu"]=$conf["fileArgu"];
9891
		#$conf["tempDir"],字串,暫存資料的目錄位置,預設為".cmd/checkFileKeyStrLBL".
9892
		#$conf["tempDir"]="";
9893
		$checkFileKeyStrLBL=cmd::checkFileKeyStrLBL($conf["cmd::checkFileKeyStrLBL"]);
9894
		unset($conf["cmd::checkFileKeyStrLBL"]);
9895
 
9896
		#如果檢查設定值失敗
9897
		if($checkFileKeyStrLBL["status"]==="false"){
9898
 
9899
			#設置執行失敗
9900
			$result["status"]="false";
9901
 
9902
			#設置執行錯誤訊息
9903
			$result["error"]=$checkFileKeyStrLBL;
9904
 
9905
			#回傳結果
9906
			return $result;
9907
 
9908
			}#if end
9909
 
9910
		#初始化要加入的設定
9911
		$settingStr=array("LoadModule proxy_module modules/mod_proxy.so","LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so","ProxyPass /wss/chatDemo ws://localhost:8080");
9912
 
9913
		#針對每個關鍵字串列
9914
		foreach($checkFileKeyStrLBL["founded"] as $index=>$status){
9915
 
9916
			#如果沒有找到符合的設定
9917
			if($status==="true"){
9918
 
9919
				#移除要增加到設定檔的變數
9920
				unset($settingStr[$index]);
9921
 
9922
				}#if end
9923
 
9924
			}#foreach end		
9925
 
9926
		#如果有要增加的設定
9927
		if(count($settingStr)>0){
9928
 
9929
			#加入設定到 httpd 設定檔裡面
9930
			#函式說明:
9931
			#新增文字內容到檔案裡面
9932
			#回傳結果:
9933
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9934
			#$result["error"],錯誤訊息.
9935
			#$result["function"],當前執行的函數名稱.
9936
			#$result["content"],新增好後的檔案內容.
9937
			#必填的參數:
9938
			#$conf["file"],字串,檔案的位置與名稱.
9939
			$conf["cmd::addTextToFile"]["file"]=$conf["httpd.conf"];
9940
			#$conf["addStr"],陣列字串,要新增的字串內容.
9941
			$conf["cmd::addTextToFile"]["addStr"]=$settingStr;	
9942
			#可省略參數:
9943
			#$conf["username"],字串,要以哪個使用者來執行,預設為執行該php程式的使用者.
9944
			$conf["cmd::addTextToFile"]["username"]="root";
9945
			#$conf["password"],字串,使用者對應的密碼,預設為"password".
9946
			$conf["cmd::addTextToFile"]["password"]=$conf["rootPasswd"];
9947
			#$conf["fileArgu"],字串,__FILE__的內容,預設為當前檔案的位置.
9948
			$conf["cmd::addTextToFile"]["fileArgu"]=$conf["fileArgu"];
9949
			$addTextToFile=cmd::addTextToFile($conf["cmd::addTextToFile"]);
9950
			unset($conf["cmd::addTextToFile"]);
9951
 
9952
			#如果新增內容失敗
9953
			if($addTextToFile["status"]==="false"){
9954
 
9955
				#設置執行失敗
9956
				$result["status"]="false";
9957
 
9958
				#設置執行錯誤訊息
9959
				$result["error"]=$addTextToFile;
9960
 
9961
				#回傳結果
9962
				return $result;
9963
 
9964
				}#if end
9965
 
9966
			#檢查是否增加成功
9967
			#檢查httpd設定檔案有無設定載入 proxy 模組與設定 ProxyPass
9968
			#函式說明:
9969
			#取得檔的內容並以列為單位搜尋多個關鍵字.
9970
			#回傳結果:
9971
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
9972
			#$result["error"],錯誤訊息.
9973
			#$result["function"],當前執行的函數名稱.
9974
			#$result["content"],取得讀取到的檔案內容.
9975
			#$result["founded"],每個關鍵字串尋找的結果,"true"代表有找到,"false"代表沒有找到.
9976
			#$result["foundedLine"],每個找到的關鍵字是在第幾列找到的,key值與$result["founded"]的key值一樣.
9977
			#必填的參數:
9978
			#$conf["file"],字串,檔案的位置與名稱.
9979
			$conf["cmd::checkFileKeyStrLBL"]["file"]=$conf["httpd.conf"];
9980
			#$conf["keyStr"],陣列字串,要搜尋每列有哪些關鍵字串.
9981
			$conf["cmd::checkFileKeyStrLBL"]["keyStr"]=$settingStr;
9982
			#可省略參數:
9983
			#$conf["username"],字串,要以哪個使用者來執行,預設為執行該php程式的使用者.
9984
			$conf["cmd::checkFileKeyStrLBL"]["username"]="root";
9985
			#$conf["password"],字串,使用者對應的密碼,預設不使用.
9986
			$conf["cmd::checkFileKeyStrLBL"]["password"]=$conf["rootPasswd"];
9987
			#$conf["fileArgu"],字串,__FILE__的內容,預設為當前檔案的位置.
9988
			$conf["cmd::checkFileKeyStrLBL"]["fileArgu"]=$conf["fileArgu"];
9989
			#$conf["tempDir"],字串,暫存資料的目錄位置,預設為".cmd/checkFileKeyStrLBL".
9990
			#$conf["tempDir"]="";
9991
			$checkFileKeyStrLBL=cmd::checkFileKeyStrLBL($conf["cmd::checkFileKeyStrLBL"]);
9992
			unset($conf["cmd::checkFileKeyStrLBL"]);
9993
 
9994
			#如果檢查設定值失敗
9995
			if($checkFileKeyStrLBL["status"]==="false"){
9996
 
9997
				#設置執行失敗
9998
				$result["status"]="false";
9999
 
10000
				#設置執行錯誤訊息
10001
				$result["error"]=$checkFileKeyStrLBL;
10002
 
10003
				#回傳結果
10004
				return $result;
10005
 
10006
				}#if end
10007
 
10008
			#如果沒有找到該有設定字串
10009
			if($checkFileKeyStrLBL["founded"]==="false"){
10010
 
10011
				#設置執行失敗
10012
				$result["status"]="false";
10013
 
10014
				#設置執行錯誤訊息
10015
				$result["error"]=$checkFileKeyStrLBL;
10016
 
10017
				#設置錯誤訊息
10018
				$result["error"][]="寫入設定值失敗";
10019
 
10020
				#回傳結果
10021
				return $result;
10022
 
10023
				}#if end
10024
 
10025
			#重新啟動 httpd 伺服器
10026
			#函式說明:
10027
			#呼叫shell執行系統命令,並取得回傳的內容.
10028
			#回傳的結果:
10029
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10030
			#$result["error"],錯誤訊息陣列.
10031
			#$result["function"],當前執行的函數名稱.
10032
			#$result["cmd"],執行的指令內容.
10033
			#$result["output"],爲執行完二元碼後的輸出陣列.
10034
			#必填的參數
10035
			#$conf["command"],字串,要執行的指令與.
10036
			$conf["external::callShell"]["command"]="systemctl";
10037
			#$conf["fileArgu"],字串,變數__FILE__的內容.
66 liveuser 10038
			$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];
3 liveuser 10039
			#可省略參數:
10040
			#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
10041
			$conf["external::callShell"]["argu"]=array("restart","httpd");
10042
			#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").
10043
			#$conf["arguIsAddr"]=array();
10044
			#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".
10045
			#$conf["enablePrintDescription"]="true";
10046
			#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容.
10047
			#$conf["printDescription"]="";
10048
			#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".
10049
			$conf["external::callShell"]["escapeshellarg"]="true";
10050
			#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.
10051
			$conf["external::callShell"]["username"]="root";
10052
			#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.
10053
			$conf["external::callShell"]["password"]=$conf["rootPasswd"];
10054
			#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要;"false"代表不要,預設為"false".
10055
			#$conf["useScript"]="";
10056
			#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 ".qbpwcf_tmp/external/callShell/".
10057
			#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";
10058
			#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.
10059
			#$conf["inBackGround"]="";
10060
			#備註:
10061
			#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.
10062
			#參考資料:
10063
			#exec=>http://php.net/manual/en/function.exec.php
10064
			#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php
10065
			#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php
10066
			$callShell=external::callShell($conf["external::callShell"]);
10067
			unset($conf["external::callShell"]);
10068
 
10069
			#如果重新啟動apache失敗
10070
			if($callShell["status"]==="false"){
10071
 
10072
				#設置執行失敗
10073
				$result["status"]="false";
10074
 
10075
				#設置執行錯誤訊息
10076
				$result["error"]=$callShell;
10077
 
10078
				#回傳結果
10079
				return $result;
10080
 
10081
				}#if end
10082
 
10083
			}#if end
10084
 
10085
		#設置執行正常
10086
		$result["status"]="true";
10087
 
10088
		#回傳結果
10089
		return $result;
10090
 
10091
		}#function registerChatDemo end
10092
 
10093
	/*
10094
	#函式說明:
10095
	#建立php原生的socket tcp/ip server,提供webSocket server支援.
10096
	#回傳結果:
10097
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
10098
	#$result["error"],錯誤訊息陣列.
10099
	#$resutl["function"],當前執行的涵式名稱.
10100
	#$result["argu"],所使用的參數.
10101
	#必填參數:
10102
	#$conf["fileArgu"],字串,變數__FILE__的內容.
10103
	$conf["fileArgu"]=__FILE__;
10104
	#可省略參數:
10105
	#$conf["listenIp"],字串,要接聽的主機ip,預設為本機的ip.
10106
	#$conf["listenIp"]="";
10107
	#$conf["listenPort"],字串,要接聽的port,預設為已使用port+1.
10108
	#$conf["listenPort"]="";
10109
	#$conf["wsMode"],字串,是否要用webSocket模式,預設為"false",不使用,若為"true"則要使用.
10110
	#$conf["wsMode"]="false";
66 liveuser 10111
	#$conf["processFuncs"],陣列,針對收到的訊息要呼叫的函式,會帶入一個參數陣列,array("data"=>收到的資料,"serverSock"=>serverSock,"clientSock"=>clientSock,"clientInfo"=>用戶端的資訊,"clientIndex"=>用戶端的索引,"allConn"=>所有連線的用戶端的連線資訊),回傳的結果若為陣列$result,其$result["status"]為"true"時,會結束執行(等待下個訊息);為"false"時,會var_dump結果,然後交給下一個函式執行;為"continue"時,代表交給下一個函式執行;預設的數值為array("noAuth");
3 liveuser 10112
	#$conf["processFuncs"]=array();
66 liveuser 10113
	#$conf["idleFunc"],陣列,當沒有收到訊息時,要執行的函式順序,預設不指定.
10114
	#$conf["idleFunc"]=array();
3 liveuser 10115
	#參考資料:
10116
	#http://php.net/manual/en/sockets.examples.php
10117
	#http://us3.php.net/manual/en/function.socket-select.php
10118
	#response should at least end with "\r"=>http://stackoverflow.com/questions/25739768/websocket-communication-between-chromeclient-and-hotspotserver-status-line
10119
	#response status code should be 101=>http://stackoverflow.com/questions/29829597/i-get-a-status-200-when-connecting-to-the-websocket-but-it-is-an-error
10120
	#webSocket實做=>http://srchea.com/build-a-real-time-application-using-html5-websockets
10121
	#webSocketServer實做=>http://www.cuelogic.com/blog/php-and-html5-websocket-server-and-client-communication/
10122
	#備註:
10123
	#僅能在命令列執行.
71 liveuser 10124
	#runPhpWhenIdle的功能尚未實作.
3 liveuser 10125
	*/
10126
	public static function nativeSocketTcpIpServer(&$conf){
10127
 
10128
		#初始化要回傳的結果
10129
		$result=array();
10130
 
10131
		#取得當前執行的函數名稱
10132
		$result["function"]=__FUNCTION__;
10133
 
10134
		#涵式說明:
10135
		#判斷當前環境為web還是cmd
10136
		#回傳結果:
10137
		#$result,"web"或"cmd"
10138
		if(csInformation::getEnv()==="web"){
10139
 
10140
			#設置執行失敗
10141
			$result["status"]="false";
10142
 
10143
			#設置執行錯誤訊息
10144
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
10145
 
10146
			#回傳結果
10147
			return $result;
10148
 
10149
			}#if end
10150
 
10151
		#取得參數
10152
		$result["argu"]=$conf;
10153
 
10154
		#如果 $conf 不為陣列
10155
		if(gettype($conf)!="array"){
10156
 
10157
			#設置執行失敗
10158
			$result["status"]="false";
10159
 
10160
			#設置執行錯誤訊息
10161
			$result["error"][]="\$conf變數須為陣列形態";
10162
 
10163
			#如果傳入的參數為 null
10164
			if($conf==null){
10165
 
10166
				#設置執行錯誤訊息
10167
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
10168
 
10169
				}#if end
10170
 
10171
			#回傳結果
10172
			return $result;
10173
 
10174
			}#if end
10175
 
10176
		#檢查參數
10177
		#函式說明:
10178
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
10179
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10180
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
10181
		#$result["function"],當前執行的函式名稱.
10182
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
10183
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
10184
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
10185
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
10186
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
10187
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
10188
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
10189
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
10190
		#必填寫的參數:
10191
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
10192
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
10193
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
10194
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
10195
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
10196
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
10197
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
10198
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
10199
		#可以省略的參數:
10200
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
10201
		#$conf["canBeEmptyString"]="false";
10202
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
10203
		#$conf["canNotBeEmpty"]=array();
10204
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
10205
		#$conf["canBeEmpty"]=array();
10206
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
10207
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
10208
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
66 liveuser 10209
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("listenIp","listenPort","wsMode","processFuncs","idleFunc");
3 liveuser 10210
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
66 liveuser 10211
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","array");
3 liveuser 10212
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
68 liveuser 10213
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",null,"false",array("noAuth"),array());
3 liveuser 10214
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
10215
		#$conf["arrayCountEqualCheck"][]=array();
10216
		#參考資料來源:
10217
		#array_keys=>http://php.net/manual/en/function.array-keys.php
10218
		#建議:
10219
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
10220
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
10221
		unset($conf["variableCheck::checkArguments"]);
10222
 
10223
		#如果檢查參數失敗
10224
		if($checkArguments["status"]==="false"){
10225
 
10226
			#設置執行失敗
10227
			$result["status"]="false";
10228
 
10229
			#設置執行錯誤訊息
10230
			$result["error"]=$checkArguments;
10231
 
10232
			#回傳結果
10233
			return $result;
10234
 
10235
			}#if end
10236
 
10237
		#如果檢查參數不通過
10238
		if($checkArguments["passed"]==="false"){
10239
 
10240
			#設置執行失敗
10241
			$result["status"]="false";
10242
 
10243
			#設置執行錯誤訊息
10244
			$result["error"]=$checkArguments;
10245
 
10246
			#回傳結果
10247
			return $result;
10248
 
66 liveuser 10249
			}#if end
3 liveuser 10250
 
10251
		#如果 $conf["listenPort"] 不存在
10252
		if(!isset($conf["listenPort"])){
10253
 
10254
			#用nmap掃port
10255
			#函式說明:
10256
			#掃port的程式
10257
			#回傳結果:
10258
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10259
			#$result["error"],錯誤訊息.
10260
			#$result["function"],當前執行的函數名稱.
10261
			#$result["argu"],使用的參數.
10262
			#$result["content"],掃好可能可以使用的port資訊.
10263
			#必填參數
10264
			#無:
10265
			#可省略參數:
10266
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10267
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10268
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10269
			#$conf["-Pn"]="false";
10270
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10271
			unset($conf["cmd::nmap"]);
10272
 
10273
			#如果掃port失敗
10274
			if($nmap["status"]==="false"){
10275
 
10276
				#設置執行失敗
10277
				$result["status"]="false";
10278
 
10279
				#設置執行錯誤訊息
10280
				$result["error"]=$nmap;
10281
 
10282
				#回傳結果
10283
				return $result;
10284
 
10285
				}#if end
10286
 
10287
			#如果有掃到port
10288
			if(count($nmap["content"])>0){
10289
 
10290
				#找最大的port
10291
				#涵式說明:
10292
				#找最大值,結果會回傳最大值.
10293
				#回傳的結果:
10294
				#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10295
				#$result["error"],錯誤訊息陣列.
10296
				#$result["function"],當前執行的函數名稱.
10297
				#$result["key"],最大值原先的key.
10298
				#$result["value"],最大值的數字.
10299
				#必填的參數:
10300
				$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10301
				$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10302
				unset($conf["math::getMaxValue"]);
10303
 
10304
				#如果找最大port失敗
10305
				if($getMaxValue["status"]==="false"){
10306
 
10307
					#設置執行失敗
10308
					$result["status"]="false";
10309
 
10310
					#設置執行錯誤訊息
10311
					$result["error"]=$getMaxValue;
10312
 
10313
					#回傳結果
10314
					return $result;
10315
 
10316
					}#if end
10317
 
10318
				#設置 $conf["listenPort"] 為最大 port+1
10319
				$conf["listenPort"]=$getMaxValue["value"]+1;
10320
 
10321
				#如果port小於4000,會無法讓nmap偵測到有使用
10322
				if($conf["listenPort"]<4000){
10323
 
10324
					#設為4000
10325
					$conf["listenPort"]="4000";
10326
 
10327
					}#if end
10328
 
66 liveuser 10329
				}#if end
3 liveuser 10330
 
10331
			}#if end
10332
 
10333
		#反之
10334
		else{
10335
 
10336
			#用nmap掃port
10337
			#函式說明:
10338
			#掃port的程式
10339
			#回傳結果:
10340
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10341
			#$result["error"],錯誤訊息.
10342
			#$result["function"],當前執行的函數名稱.
10343
			#$result["argu"],使用的參數.
10344
			#$result["content"],掃好可能可以使用的port資訊.
10345
			#必填參數
10346
			#無:
10347
			#可省略參數:
10348
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10349
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10350
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10351
			#$conf["-Pn"]="false";
10352
			#$conf["fileArgu"],字串,變數__FILE__的內容.
10353
			$conf["cmd::nmap"]["fileArgu"]=$conf["fileArgu"];
10354
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10355
			unset($conf["cmd::nmap"]);
10356
 
10357
			#如果掃port失敗
10358
			if($nmap["status"]==="false"){
10359
 
10360
				#設置執行失敗
10361
				$result["status"]="false";
10362
 
10363
				#設置執行錯誤訊息
10364
				$result["error"]=$nmap;
10365
 
10366
				#回傳結果
10367
				return $result;
10368
 
10369
				}#if end
10370
 
10371
			#如果有掃到port
10372
			if(count($nmap["content"])>0){
10373
 
10374
				#如果要用來建立socket的port已被使用
10375
				if(in_array($conf["listenPort"],$nmap["content"])){
10376
 
10377
					#找最大的port
10378
					#涵式說明:
10379
					#找最大值,結果會回傳最大值.
10380
					#回傳的結果:
10381
					#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10382
					#$result["error"],錯誤訊息陣列.
10383
					#$result["function"],當前執行的函數名稱.
10384
					#$result["key"],最大值原先的key.
10385
					#$result["value"],最大值的數字.
10386
					#必填的參數:
10387
					$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10388
					$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10389
					unset($conf["math::getMaxValue"]);
10390
 
10391
					#如果找最大port失敗
10392
					if($getMaxValue["status"]==="false"){
10393
 
10394
						#設置執行失敗
10395
						$result["status"]="false";
10396
 
10397
						#設置執行錯誤訊息
10398
						$result["error"]=$getMaxValue;
10399
 
10400
						#回傳結果
10401
						return $result;
10402
 
10403
						}#if end
10404
 
10405
					#設置 $conf["listenPort"] 為最大 port+1
10406
					$conf["listenPort"]=$getMaxValue["value"]+1;
10407
 
10408
					#如果port小於4000,會無法讓nmap偵測到有使用
10409
					if($conf["listenPort"]<4000){
10410
 
10411
						#設為4000
10412
						$conf["listenPort"]="4000";
10413
 
10414
						}#if end
10415
 
10416
					}#if end
10417
 
10418
				}#if end
10419
 
10420
			}#else end
10421
 
10422
		#回報任何錯誤
10423
		#error_reporting(E_ALL);
10424
 
10425
		/* Allow the script to hang around waiting for connections. */
10426
		set_time_limit(0);
10427
 
10428
		/* Turn on implicit output flushing so we see what we're getting as it comes in. */
10429
		#ob_implicit_flush();
10430
 
10431
		#設定要listen的主機ip
10432
		$address = $conf["listenIp"];
10433
 
10434
		#設定要listen的port
10435
		$port = $conf["listenPort"];
10436
 
10437
		#重複做,讓socket服務不會結束.
10438
		do{
10439
 
10440
			#如果建立 socket 失敗
10441
			if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){
10442
 
10443
				#印出錯誤訊息
10444
				echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
10445
 
10446
				}#if end
10447
 
10448
			#設置不等待連線與訊息的到來,變成不會卡位
10449
			socket_set_nonblock($sock);
10450
 
10451
			#SOL_SOCKET => socket level
10452
			#SO_REUSEADDR => Reports whether local addresses can be reused. 
10453
			socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
66 liveuser 10454
 
3 liveuser 10455
			#如果 Binds a name to a socket 失敗
10456
			if (@socket_bind($sock, $address, $port) === false){
10457
 
10458
				#儲存錯誤訊息
10459
				$error=socket_strerror(socket_last_error($sock));
10460
 
10461
				#印出錯誤訊息
10462
				echo "socket_bind() failed: reason: " .$error. PHP_EOL;
10463
 
10464
				#判斷錯誤訊息的是否有 "Address already in use"
10465
				#函式說明:
10466
				#檢查字串裡面有無指定的關鍵字
10467
				#回傳的結果:
10468
				#$result["status"],"true"代表執行成功,"false"代表執行失敗。
10469
				#$result["error"],錯誤訊息
10470
				#$result["function"],當前執行的函數名稱.
10471
				#$result["founded"],是否找到關鍵字,"true"代表有找到關鍵字;"false"代表沒有找到關鍵字。
10472
				#$result["keyWordCount"],找到的關鍵字數量.
10473
				#必填的參數:
10474
				$conf["search::findKeyWord"]["keyWord"]="Address already in use";#想要搜尋的關鍵字
10475
				$conf["search::findKeyWord"]["string"]=$error;#要被搜尋的字串內容
10476
				#可省略的參數:
10477
				#$conf["completeEqual"]="true";#是否內容要完全符合,不能多出任何不符合的內容,預設為不需要完全符合。
10478
				$findKeyWord=search::findKeyWord($conf["search::findKeyWord"]);
10479
				unset($conf["search::findKeyWord"]);
10480
 
10481
				#如果解析錯誤訊息失敗
10482
				if($findKeyWord["status"]==="false"){
10483
 
10484
					#設置執行失敗
10485
					$result["status"]="false";
10486
 
10487
					#設置執行錯誤訊息
10488
					$result["error"]=$getMeetConditionsString;
10489
 
10490
					#回傳結果
10491
					return $result;
10492
 
10493
					}#if end
10494
 
10495
				#如果錯誤原因為socket的port已經被使用了.
10496
				if($findKeyWord["founded"]==="true"){
10497
 
10498
					#port加1
10499
					$port++;
10500
 
10501
					#再次建立socket服務
10502
					continue;
10503
 
10504
					}#if end
10505
 
10506
				#反之
10507
				else{
10508
 
10509
					#結束程式
10510
					exit;
10511
 
10512
					}#else 
10513
 
10514
				}#if end
10515
 
10516
			#如果 listen socket 經過嘗試5次後仍然失敗
10517
			if (socket_listen($sock, 5) === false) {
10518
 
10519
				#印出錯誤訊息
10520
				echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;
10521
 
10522
				}#if end
10523
 
10524
			#初始化儲存已經連線到 socket service 的服務
10525
			$connections=array();
10526
 
66 liveuser 10527
			#初始化 idle 時要呼叫的函式名稱陣列
10528
			$idleFunc=array();
10529
 
3 liveuser 10530
			#提示 listen 的 ip 與 port
10531
			echo "Listen to:".$address.":".$port.PHP_EOL;
10532
 
10533
			#重複做,等待別人連線.
10534
			do{
10535
 
10536
				#初始化儲存有需要處理的socket連線
10537
				$read = array();
10538
 
10539
				#初始化一開始建立的socket為要處理的項目
10540
				$read[] = $sock;
10541
 
10542
				#有幾個連線就執行幾次
10543
				foreach($connections as $conForSockSelect){
10544
 
10545
					#產生要合併的陣列
10546
					$arrayToMerage=array($conForSockSelect["connect"]);
10547
 
10548
					#合併陣列
10549
					$read = array_merge($read,$arrayToMerage);
10550
 
10551
					}#foreach end
10552
 
10553
				#從socket物件陣列($read)裡面取出有需要處理連線的socket物件.
10554
				#Set up a blocking call to socket_select
10555
				$write=array();
10556
				$except=array();
10557
				$tv_sec = 1;
10558
				if(socket_select($read, $write, $except, $tv_sec) < 1){
10559
 
10560
					#沒有事情發生
10561
					echo ".";
10562
 
10563
					#函式說明:
10564
					#加密 handshake 後要傳送的訊息 
10565
					#回傳結果:
10566
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10567
					#$result["error"],執行不正常結束的錯訊息陣列.
10568
					#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
10569
					#$result["argu"],陣列,使用的參數.
10570
					#必填參數:
10571
					#$conf["text"],字串,要加密的訊息.
10572
					$conf["webSock::encode"]["text"]=""; 
10573
					#可省略參數:
10574
					#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
10575
					$conf["webSock::encode"]["ping"]="true";
10576
					#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
10577
					#$conf["frames"]=array();
10578
					#參考資料:
10579
					#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
10580
					#備註:
10581
					#無.
10582
					$encode=webSock::encode($conf["webSock::encode"]);
10583
					unset($conf["webSock::encode"]);
10584
 
10585
					#debug
10586
					#var_dump(__LINE__,$encode);
10587
 
10588
					#如果執行失敗
10589
					if($encode["status"]==="false"){
10590
 
10591
						#設置執行失敗
10592
						$result["status"]="false";
10593
 
10594
						#設置執行錯誤訊息
10595
						$result["error"]=$encode;
66 liveuser 10596
 
3 liveuser 10597
						#回傳結果
10598
						return $result;
10599
 
10600
						}#if end
10601
 
10602
					#針對每個連線的 client
10603
					foreach($connections as $client){
10604
 
10605
						#如果有 last ping time
10606
						if(isset($client["lastPongTime"])){
10607
 
10608
							#如果小於5秒沒有收到pong
10609
							if(time()-$client["lastPongTime"]<5){
10610
 
66 liveuser 10611
								#看下一個連線,亦即視為用戶已經斷線.
3 liveuser 10612
								continue;
10613
 
10614
								}#if end
10615
 
10616
							}#if end
10617
 
10618
						#取得用戶socket
10619
						$clientSock=$client["connect"];
10620
 
10621
						#傳送ping給client
10622
						$socket_write=socket_write($clientSock, $encode["content"][0], strlen($encode["content"][0]));
10623
 
10624
						#debug
10625
						#var_dump(__LINE__,"send ping",$socket_write,socket_strerror(socket_last_error($clientSock)));
10626
 
10627
						}#foreach end
10628
 
66 liveuser 10629
					#如果有idle時要做的事情
10630
					if(count($conf["idleFunc"])>0){
10631
 
10632
						#取得idleFunc設定
10633
						$idleFunc=$conf["idleFunc"];
10634
 
10635
						#移除初始的idelFunc設定
10636
						unset($conf["idleFunc"]);
10637
 
10638
						}#if end
10639
 
10640
					#如果有idle時要做的事情
10641
					if(count($idleFunc)>0){
10642
 
10643
						#針對每個要執行的函式
10644
						foreach($idleFunc as $if){
10645
 
10646
							#設置要給予函式的參數陣列
10647
							$param=array("idleFunc"=>&$idleFunc,"serverSock"=>&$sock,"allConn"=>&$connections);
10648
 
10649
							#初始化給予 call_user_func_array 的第2個參數
10650
							$params=array();
10651
 
10652
							#設置呼叫函式 $if 時要傳遞的參數為一個 $param
10653
							$params[]=&$param;
10654
 
10655
							#呼叫函式 $if 與要傳遞的參數.
10656
							$result=call_user_func_array($if,$params);
10657
 
10658
							}#foreach end
10659
 
10660
						}#if end
10661
 
71 liveuser 10662
					#如果有 $php2runWhenIdle
10663
					if(isset($php2runWhenIdle)){
66 liveuser 10664
 
71 liveuser 10665
						#如果有php程式要於idle時執行
10666
						while(count($php2runWhenIdle)>0){
10667
 
10668
							#取得要執行的 php code
10669
							$phpCode=array_shift($php2runWhenIdle);
10670
 
10671
							#...
10672
 
10673
							}#while end
66 liveuser 10674
 
71 liveuser 10675
						}#if end
10676
 
3 liveuser 10677
					#下一輪
10678
					continue;
10679
 
10680
					}#if end
10681
 
10682
				#有事情發生
10683
				echo "something happen".PHP_EOL;
66 liveuser 10684
 
3 liveuser 10685
				#如果有socket要處理
10686
				if(in_array($sock,$read)){
10687
 
10688
					#如果有接收到 socket 連線
10689
					if (($msgsock = socket_accept($sock)) !== false) {
66 liveuser 10690
 
3 liveuser 10691
						#初始化不是既有的 sock
10692
						$existSock=false;
66 liveuser 10693
 
3 liveuser 10694
						#尋找是哪個 socket
10695
						for($i=0;$i<count($connections);$i++){
10696
 
10697
							#如果是既有的 sock
10698
							if($connections[$i]["connect"]===$msgsock){
10699
 
10700
								#設置是既有的 sock
10701
								$existSock=true;
10702
 
10703
								}#if end
10704
 
10705
							}#for end
10706
 
10707
						#如果該 socket 是新的
10708
						if(!$existSock){
10709
 
10710
							#重複做
10711
							do{
66 liveuser 10712
 
3 liveuser 10713
								#亂數產生連線id
10714
								#涵式說明:
10715
								#建立以圖片(PNG格式)呈現的驗證碼.
10716
								#回傳的解果:
10717
								#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
10718
								#$result["error"],錯誤訊息.
10719
								#$result["function"],檔前執行的函數名稱.
10720
								#$result["randNumberWord"],傳驗證碼的內容.
10721
								#$result["imgAddress"],圖片的位置與名稱.
10722
								#必填的參數:
10723
								#$conf["imgAddressAndName"],字串,爲驗證碼圖片儲存的位置與名稱,副檔名程式會自動產生
10724
								$conf["authenticate::validationCode"]["imgAddressAndName"]="no used!";
10725
								#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
10726
								$conf["authenticate::validationCode"]["fileArgu"]=$conf["fileArgu"];
10727
								#可省略的參數:
10728
								#$conf["num"],字串,爲驗證碼的位數,請輸入阿拉伯數字,預設為"8"位數.
10729
								#$conf["num"]="8";
10730
								#$conf["disableImg"],字串,是否要取消驗證碼圖片的輸出,"true"為要取消,預設為"false"為不取消
10731
								$conf["authenticate::validationCode"]["disableImg"]="true";
10732
								#$conf["imgToData"],字串,預設為"true"代表將圖片轉存成base64圖片,並將原始圖片移除;反之為"false"
10733
								#$conf["authenticate::validationCode"]["imgToData"]="true";
10734
								$validationCode=authenticate::validationCode($conf["authenticate::validationCode"]);
10735
								unset($conf["authenticate::validationCode"]);
10736
 
10737
								#如果產生亂數失敗
10738
								if($validationCode["status"]==="false"){
10739
 
10740
									#設置執行失敗
10741
									$result["status"]="false";
10742
 
10743
									#設置執行錯誤訊息
10744
									$result["error"]=$validationCode;
10745
 
10746
									#回傳結果
10747
									return $result;
10748
 
10749
									}#if end
10750
 
10751
								#如果不存在既有的連線資訊
10752
								if(count($connections)<1){
10753
 
10754
									#跳出迴圈
10755
									break;
10756
 
10757
									}#if end
10758
 
10759
								#初始化連線id的陣列
10760
								$idArray=array();
10761
 
10762
								#針對既有的連線
10763
								foreach($connections as $exist_conn){
10764
 
10765
									#儲存連線id
10766
									$idArray[]=$exist_conn["id"];
10767
 
10768
									}#foreach end
10769
 
10770
								}#do end
10771
 
10772
							#檢查id有無重複
10773
							while(in_array($validationCode["randNumberWord"],$idArray));
66 liveuser 10774
 
10775
							#如果不是 ws 模式
3 liveuser 10776
							if($conf["wsMode"]==="false"){
66 liveuser 10777
 
3 liveuser 10778
								#儲存連線到陣列裡面
10779
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array());
66 liveuser 10780
 
3 liveuser 10781
								}#if end
66 liveuser 10782
 
3 liveuser 10783
							#如果是 ws 模式
10784
							if($conf["wsMode"]==="true"){
66 liveuser 10785
 
3 liveuser 10786
								#儲存連線到陣列裡面
10787
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array(),"handshaked"=>"false","unmask"=>"false","userAgent"=>"false","3rn"=>0,"receivedMsgFromServer"=>array());
66 liveuser 10788
 
3 liveuser 10789
								}#if end
66 liveuser 10790
 
3 liveuser 10791
							#debug,提示 Server 給予的新 Id
10792
							echo "new connection:".PHP_EOL;
10793
 
10794
							#初始化連線後要回傳的訊息
10795
							$msg="";
66 liveuser 10796
 
3 liveuser 10797
							#如果不是 ws 模式
10798
							if($conf["wsMode"]!=="true"){
10799
 
10800
								#提示client連上線後得到的訊息
10801
								$msg = $msg.PHP_EOL."Welcome to the PHP Test Server.".PHP_EOL;
10802
								$msg = $msg."To quit, type 'quit'. To shut down the server type 'shutdown'.".PHP_EOL;
10803
								socket_write($msgsock, $msg, strlen($msg));
10804
 
10805
								}#if end
10806
 
10807
							}#if end
10808
 
10809
						}#if end
10810
 
10811
					}#if end
10812
 
10813
				#重新排序 $connections
10814
				#函式說明:
10815
				#將陣列的key重新排序,然後回傳,以便後續存取,也可以指定key的內容,但一定要跟元素數量相同。
10816
				#回傳的解果:
10817
				#$result["status"],執行是否成功,"true"代表成功,"false"代表失敗.
10818
				#$result["error"],執行錯誤的訊息.
10819
				#$result["function"],當前執行的函數名稱.
10820
				#$result["dataContent"],儲存陣列元素的內容.
10821
				#若指定了key的名稱,則 $result["dataContent"] 會變成 $result["dataContent"]["指定的key名稱"]
10822
				#$result["dataCount"],儲存陣列元素的數量。
10823
				#必填的參數:
10824
				$conf["arrays::createV2"]["arrayContent"]=$connections;#陣列變數
10825
				#可省略的參數:
10826
				#$conf["specifiesKeyArray"]=array();#指定key的名稱,須與$conf["arrayContent"]的元素數量相同
10827
				$createV2=arrays::createV2($conf["arrays::createV2"]);
10828
				unset($conf["arrays::createV2"]);
10829
 
10830
				#如果重新排序失敗
10831
				if($createV2["status"]==="false"){
10832
 
10833
					#設置執行失敗
10834
					$result["status"]="false";
10835
 
10836
					#設置執行錯誤訊息
10837
					$result["error"]=$createV2;
10838
 
10839
					#回傳結果
10840
					return $result;
10841
 
10842
					}#if end
10843
 
10844
				#取得重新排序好的陣列
10845
				$connections=$createV2["dataContent"];
10846
 
10847
				#依據每個 client 的連線
10848
				foreach($connections as $conIndex => $con){
10849
 
10850
					#如果有要處理的socket連線項目
10851
					if(in_array($con["connect"], $read)){
10852
 
10853
						#如果不存在 handshaked
10854
						if(!isset($con["handshaked"])){
10855
 
10856
							#預設為 "false"
10857
							$con["handshaked"]="false";
10858
 
10859
							}#if end
10860
 
10861
						#如果有 handshaked
10862
						if($con["handshaked"]==="true"){
66 liveuser 10863
 
10864
							#讀取內容
3 liveuser 10865
							$buf = @socket_read($con["connect"], 2048, PHP_BINARY_READ);
10866
 
10867
							#設置要 unmask
10868
							$connections[$conIndex]["unmask"]="true";
66 liveuser 10869
 
10870
							#設置尚未 auth
10871
							$connections[$conIndex]["auth"]="false";
3 liveuser 10872
 
10873
							}#if end
66 liveuser 10874
 
3 liveuser 10875
						#反之
10876
						else{
10877
 
10878
							#讀取內容
10879
							$buf = @socket_read($con["connect"], 2048, PHP_NORMAL_READ);
10880
 
10881
							}#else end
10882
 
10883
						#如果讀取出錯
10884
						if($buf===false){
10885
 
10886
							#印出錯誤訊息
10887
							echo "socket_recv() failed: reason: " . socket_strerror(socket_last_error($con["connect"])) . PHP_EOL;
10888
 
10889
							#移除該連線的資料
10890
							unset($connections[$conIndex]);	
10891
 
10892
							#跳到下一輪
10893
							continue;
10894
 
10895
							}#if end
10896
 
10897
						#如果收到的資料長度為 0 bytes
10898
						if($buf===""){
10899
 
10900
							#關閉 socket msg
10901
							socket_close($con["connect"]);	
10902
 
10903
							#移除該連線的資料
10904
							unset($connections[$conIndex]);
10905
 
10906
							#跳到下一輪
10907
							continue;
10908
 
10909
							}#if end
10910
 
10911
						#印出接受的非換行符號內容
10912
						if($buf!==PHP_EOL){
10913
 
10914
							#debug
10915
							echo "received:".$buf.PHP_EOL;
66 liveuser 10916
 
3 liveuser 10917
							}#if end
10918
 
10919
						#如果無 handshaked
10920
						if($con["handshaked"]!=="true"){
10921
 
10922
							#清除換行字元
10923
							$buf=trim($buf);
10924
 
10925
							}#if end
10926
 
10927
						#web socket mode
10928
						if($conf["wsMode"]==="true"){
10929
 
10930
							#如果不需要 unmask
10931
							if($connections[$conIndex]["unmask"]==="false"){
66 liveuser 10932
 
3 liveuser 10933
								#提示還不用 unmask
10934
								echo "don't need unmask now".PHP_EOL;
66 liveuser 10935
 
3 liveuser 10936
								#重新計數 \r\n
10937
								$connections[$conIndex]["3rn"]=0;
66 liveuser 10938
 
3 liveuser 10939
								}#if end
10940
 
10941
							}#if end
66 liveuser 10942
 
3 liveuser 10943
						#如果有內容(不是換行符號)
10944
						$st=trim($buf);
10945
 
10946
						#如果是 ws 模式
10947
						if($conf["wsMode"]==="true"){
10948
 
10949
							#如果尚未 handshake
10950
							if($connections[$conIndex]["handshaked"]==="false"){
66 liveuser 10951
 
3 liveuser 10952
								#提示 server 在檢查 handshake 用的 key 是否存在.
10953
								echo "check Sec-WebSocket-Key ..".PHP_EOL;
66 liveuser 10954
 
3 liveuser 10955
								#handshake
10956
								#如果收到的內容$buf含有 Sec-WebSocket-Key: 字串開頭,擷取後面的內容存到$matchs裡面.
10957
								if(preg_match("/Sec-WebSocket-Key: (.*)/",$buf,$matchs)){
66 liveuser 10958
 
3 liveuser 10959
									#提示serve在handshake
10960
									echo "do handshake...".PHP_EOL.PHP_EOL;
66 liveuser 10961
 
3 liveuser 10962
									#handshake
10963
									$key = $matchs[1].'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
10964
									$key =  base64_encode(sha1($key, true)); 
66 liveuser 10965
 
3 liveuser 10966
									#設置 handshake 的 header
10967
									$headers = 
10968
									"HTTP/1.1 101 Switching Protocols".PHP_EOL.
10969
									"Upgrade: websocket".PHP_EOL.
10970
									"Connection: Upgrade".PHP_EOL.
10971
									"Sec-WebSocket-Accept: ".$key.PHP_EOL.
10972
									"X-Powered-By: qbpwcf".PHP_EOL.
10973
									PHP_EOL;
66 liveuser 10974
 
3 liveuser 10975
									#傳送header給client
10976
									socket_write($con["connect"], $headers);
66 liveuser 10977
 
3 liveuser 10978
									#儲存server傳送給client的訊息
10979
									#$connections[$conIndex]["receivedMsgFromServer"][]=$headers;
66 liveuser 10980
 
3 liveuser 10981
									#提示serve handshake 完畢
10982
									echo "handshak done...".PHP_EOL;
66 liveuser 10983
 
3 liveuser 10984
									#設置已經 handshake
10985
									$connections[$conIndex]["handshaked"]="true";
66 liveuser 10986
 
3 liveuser 10987
									}#if end
10988
 
10989
								}#if end
10990
 
10991
							}#if end
10992
 
10993
						#如果是 ws 模式
10994
						if($conf["wsMode"]==="true"){
66 liveuser 10995
 
3 liveuser 10996
							#如果尚未 handshake 過
10997
							if($connections[$conIndex]["handshaked"]==="false"){
10998
 
10999
								#跳過
11000
								continue;
11001
 
11002
								}#if end
66 liveuser 11003
 
11004
							#如果還不用要 unmask
3 liveuser 11005
							if($connections[$conIndex]["unmask"]==="false"){
11006
 
11007
								#跳過
11008
								continue;
11009
 
11010
								}#if end
11011
 
11012
							}#if end
11013
 
11014
						#如果是 ws 模式
11015
						if($conf["wsMode"]==="true"){
66 liveuser 11016
 
3 liveuser 11017
							#debug
11018
							#var_dump(__LINE__,$connections[$conIndex]);
66 liveuser 11019
 
3 liveuser 11020
							#如果已經 handshake 過
11021
							if($connections[$conIndex]["handshaked"]==="true"){
11022
 
11023
								#如果要 unmask	
11024
								if($connections[$conIndex]["unmask"]==="true"){
11025
 
11026
									#如果收到的訊息不為空
11027
									if(!empty($buf)){
66 liveuser 11028
 
3 liveuser 11029
										echo "start unmask...".PHP_EOL;
11030
 
11031
										#debug
11032
										#var_dump(__LINE__,$buf);
11033
 
11034
										#解密 $buf
11035
										#回傳結果:
11036
										#$result["function"],當前函式的名稱.
11037
										#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
11038
										#$result["content"],unmask後的內容.
11039
										#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong.
11040
										#$result["error"],錯誤訊息陣列.
11041
										$conf["self::unmask"]["payload"]=$buf;
11042
										#$conf["self::unmask"]["debug"]="true";
11043
										$buf=webSock::unmask($conf["self::unmask"]);
11044
										unset($conf["self::unmask"]);
11045
 
11046
										#如果執行失敗
11047
										if($buf["status"]==="false"){
66 liveuser 11048
 
3 liveuser 11049
											#印出結果
11050
											var_dump($buf);
11051
 
11052
											#結束執行
11053
											exit;
66 liveuser 11054
 
3 liveuser 11055
											}#if end
11056
 
11057
										#如果是 ping 的回應 pong
11058
										if($buf["type"]==="pong"){
66 liveuser 11059
 
3 liveuser 11060
											#提示收到 pong
11061
											echo "got pong".PHP_EOL;
11062
 
11063
											#更新的連線的 last pong time
11064
											$connections[$conIndex]["lastPongTime"]=time();
11065
 
11066
											#換處理下一則訊息
11067
											continue;
66 liveuser 11068
 
3 liveuser 11069
											}#if end
11070
 
11071
										#如果不是 web socket frame
11072
										if($buf["type"]==="invalid"){
11073
 
11074
											#提示收到非 web socket frame
11075
											echo "not web socket frame".PHP_EOL;
11076
 
11077
											#debug
11078
											#var_dump(__LINE__,$buf);
11079
 
11080
											#換處理下一則訊息
11081
											continue;
11082
 
11083
											}#if end
11084
 
11085
										#取得umask後的內容
11086
										$buf=$buf["content"];
11087
 
11088
										#提示 unmask 結束
11089
										echo "end unmask()".PHP_EOL;
11090
 
11091
										#提示 web socket server 收到訊息的長度(bytes)
11092
										echo "Server receviced plain content(".strlen($buf)."):".PHP_EOL;
11093
 
11094
										#提示 web socket server 收到的訊息內容
11095
										echo $buf.PHP_EOL;
11096
 
11097
										}#if end
11098
 
11099
									}#if end
11100
 
11101
								}#if end
11102
 
11103
							}#if end
66 liveuser 11104
 
11105
						/*
11106
 
3 liveuser 11107
						#如果收到的是 id?
11108
						if($buf === 'id?'){
11109
 
66 liveuser 11110
							#如果尚未認證
11111
							if($connections[$conIndex]["auth"]==="false"){
11112
 
11113
								#設置要回傳的訊息
11114
								$talkback="permission denied";
11115
 
11116
								}#if end
11117
 
11118
							else{
11119
 
11120
								#設置要回傳的訊息
11121
								$talkback=$connections[$conIndex]["id"];
11122
 
11123
								}#else end
3 liveuser 11124
 
11125
							#debug
11126
							#var_dump(__LINE__,$talkback);
11127
 
11128
							#json encode 要回傳的訊息
11129
							$talkback=json_encode($talkback);
11130
 
11131
							#debug
11132
							#var_dump(__LINE__,$talkback);
11133
 
11134
							#如果是 ws 模式
11135
							if($conf["wsMode"]==="true"){
11136
 
11137
								#如果已經 handshake 過
11138
								if($connections[$conIndex]["handshaked"]==="true"){
11139
 
11140
									#如果要 unmask	
11141
									if($connections[$conIndex]["unmask"]==="true"){
11142
 
11143
										#函式說明:
11144
										#加密 handshake 後要傳送的訊息 
11145
										#回傳結果:
11146
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11147
										#$result["error"],執行不正常結束的錯訊息陣列.
11148
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11149
										#$result["argu"],陣列,使用的參數.
11150
										#必填參數:
11151
										#$conf["text"],字串,要加密的訊息.
11152
										$conf["webSock::encode"]["text"]=$talkback; 
11153
										#可省略參數:
11154
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11155
										#$conf["payloadIsBin"]="false";
11156
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11157
										#$conf["ping"]="false";
11158
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11159
										#$conf["pong"]="false";
11160
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11161
										#$conf["frames"]=array();
11162
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11163
										#$conf["mask"]="false";
11164
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11165
										#$conf["debug"]="false";
11166
										#參考資料:
11167
										#無.
11168
										#備註:
11169
										#目前$conf["text"]長度超過125會出錯.
11170
										$talkback=webSock::encode($conf["webSock::encode"]);
11171
										unset($conf["webSock::encode"]);
11172
 
11173
										#如果執行失敗
11174
										if($talkback["status"]==="false"){
11175
 
11176
											#印出結果
11177
											var_dump($talkback);
11178
 
11179
											#結束執行
11180
											exit;
11181
 
11182
											}#if end
11183
 
11184
										#debug
11185
										#var_dump(__LINE__,$talkback);
11186
 
11187
										}#if end
11188
 
11189
									}#if end
11190
 
11191
								}#if end
11192
 
11193
							#反之不為 web socket 訊息
11194
							else{
11195
 
11196
								#儲存成只有一個訊息
11197
								$talkback["content"][]=$talkback;
11198
 
11199
								}#else
11200
 
11201
							#針對每個訊息的分段
11202
							foreach($talkback["content"] as $msg){
11203
 
11204
								#debug
11205
								var_dump(__LINE__,$msg);
11206
 
11207
								#回傳訊息
11208
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11209
 
11210
								#debug
11211
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11212
 
11213
								}#foreach end
11214
 
11215
							#跳到下一輪
11216
							continue;
11217
 
11218
							}#if end
11219
 
66 liveuser 11220
						*/	
11221
 
11222
						/*
11223
 
3 liveuser 11224
						#如果收到的是 ids?
11225
						if($buf === 'ids?'){
11226
 
66 liveuser 11227
							#如果尚未認證
11228
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11229
 
66 liveuser 11230
								#設置要回傳的訊息
11231
								$talkback=json_encode("permission denied");
11232
 
11233
								}#if end
3 liveuser 11234
 
66 liveuser 11235
							#反之
11236
							else{
3 liveuser 11237
 
66 liveuser 11238
								#設置要回傳的訊息
11239
								$talkback=array();
3 liveuser 11240
 
66 liveuser 11241
								#針對每個連線
11242
								foreach($connections as $conIndex_ids => $con_ids){
11243
 
11244
									#如果不是自己
11245
									if($con_ids["connect"]!==$connections[$conIndex]["connect"]){
11246
 
11247
										#記錄其他人的id
11248
										$talkback[]=$con_ids["id"];
11249
 
11250
										}#if end
11251
 
11252
									}#foreach end
11253
 
11254
								#json encode要回傳的id陣列
11255
								$talkback=json_encode($talkback);
3 liveuser 11256
 
66 liveuser 11257
								}#else end
11258
 
3 liveuser 11259
							#如果是 ws 模式
11260
							if($conf["wsMode"]==="true"){
11261
 
11262
								#如果已經 handshake 過
11263
								if($connections[$conIndex]["handshaked"]==="true"){
11264
 
66 liveuser 11265
									#如果要 unmask
3 liveuser 11266
									if($connections[$conIndex]["unmask"]==="true"){
11267
 
11268
										#函式說明:
11269
										#加密 handshake 後要傳送的訊息 
11270
										#回傳結果:
11271
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11272
										#$result["error"],執行不正常結束的錯訊息陣列.
11273
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11274
										#$result["argu"],陣列,使用的參數.
11275
										#必填參數:
11276
										#$conf["text"],字串,要加密的訊息.
11277
										$conf["webSock::encode"]["text"]=$talkback; 
11278
										#可省略參數:
11279
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11280
										#$conf["payloadIsBin"]="false";
11281
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11282
										#$conf["ping"]="false";
11283
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11284
										#$conf["pong"]="false";
11285
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11286
										#$conf["frames"]=array();
11287
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11288
										#$conf["mask"]="false";
11289
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11290
										#$conf["debug"]="false";
11291
										#參考資料:
11292
										#無.
11293
										#備註:
11294
										#目前$conf["text"]長度超過125會出錯.
11295
										$talkback=webSock::encode($conf["webSock::encode"]);
11296
										unset($conf["webSock::encode"]);
11297
 
11298
										#如果執行失敗
11299
										if($talkback["status"]==="false"){
11300
 
11301
											#印出結果
11302
											var_dump($talkback);
11303
 
11304
											#結束執行
11305
											exit;
11306
 
11307
											}#if end
11308
 
11309
										#debug
11310
										#var_dump(__LINE__,$talkback);
11311
 
11312
										}#if end
11313
 
11314
									}#if end
11315
 
11316
								}#if end
11317
 
11318
							#反之不為 web socket 訊息
11319
							else{
11320
 
11321
								#儲存成只有一個訊息
11322
								$talkback["content"][]=$talkback;
11323
 
11324
								}#else
11325
 
11326
							#針對每個訊息的分段
11327
							foreach($talkback["content"] as $msg){
11328
 
11329
								#回傳訊息
11330
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11331
 
11332
								#debug
11333
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11334
 
11335
								}#foreach end
11336
 
11337
							#跳到下一輪
11338
							continue;
11339
 
11340
							}#if end
11341
 
11342
						#如果收到 "talkTo?"
11343
						if($buf==="talkTo?"){
11344
 
66 liveuser 11345
							#如果尚未認證
11346
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11347
 
66 liveuser 11348
								#設置要回傳的訊息
11349
								$talkback=json_encode("permission denied");
11350
 
11351
								}#if end
11352
 
11353
							#反之
11354
							else{
11355
 
11356
								#初始化要講話的id陣列
11357
								$talkback=array();
3 liveuser 11358
 
66 liveuser 11359
								#有幾個要講話的人就執行幾次
11360
								foreach($connections[$conIndex]["talkTo"] as $to){
11361
 
11362
									#串街要講話的人
11363
									$talkback[]=$to;
11364
 
11365
									}#foreach end
3 liveuser 11366
 
66 liveuser 11367
								#設置要回傳的訊息
11368
								$talkback=json_encode($talkback).PHP_EOL;
3 liveuser 11369
 
66 liveuser 11370
								}#else end
3 liveuser 11371
 
11372
							#如果是 ws 模式
11373
							if($conf["wsMode"]==="true"){
11374
 
11375
								#如果已經 handshake 過
11376
								if($connections[$conIndex]["handshaked"]==="true"){
11377
 
11378
									#如果要 unmask	
11379
									if($connections[$conIndex]["unmask"]==="true"){
11380
 
11381
										#函式說明:
11382
										#加密 handshake 後要傳送的訊息 
11383
										#回傳結果:
11384
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11385
										#$result["error"],執行不正常結束的錯訊息陣列.
11386
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11387
										#$result["argu"],陣列,使用的參數.
11388
										#必填參數:
11389
										#$conf["text"],字串,要加密的訊息.
11390
										$conf["webSock::encode"]["text"]=$talkback; 
11391
										#可省略參數:
11392
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11393
										#$conf["payloadIsBin"]="false";
11394
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11395
										#$conf["ping"]="false";
11396
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11397
										#$conf["pong"]="false";
11398
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11399
										#$conf["frames"]=array();
11400
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11401
										#$conf["mask"]="false";
11402
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11403
										#$conf["debug"]="false";
11404
										#參考資料:
11405
										#無.
11406
										#備註:
11407
										#目前$conf["text"]長度超過125會出錯.
11408
										$talkback=webSock::encode($conf["webSock::encode"]);
11409
										unset($conf["webSock::encode"]);
11410
 
11411
										#如果執行失敗
11412
										if($talkback["status"]==="false"){
11413
 
11414
											#印出結果
11415
											var_dump($talkback);
11416
 
11417
											#結束執行
11418
											exit;
11419
 
11420
											}#if end
11421
 
11422
										#debug
11423
										#var_dump(__LINE__,$talkback);
11424
 
11425
										}#if end
11426
 
11427
									}#if end
11428
 
11429
								}#if end
11430
 
11431
							#反之不為 web socket 訊息
11432
							else{
11433
 
11434
								#儲存成只有一個訊息
11435
								$talkback["content"][]=$talkback;
11436
 
11437
								}#else
11438
 
11439
							#針對每個訊息的分段
11440
							foreach($talkback["content"] as $msg){
11441
 
11442
								#回傳訊息
11443
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11444
 
11445
								#debug
11446
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11447
 
11448
								}#foreach end
11449
 
11450
							#跳到下一輪
11451
							continue;
11452
 
11453
							}#if end
11454
 
11455
						#如果收到的$buf長度大於 "talkTo:"
11456
						if(strlen($buf)>strlen("talkTo:")){
11457
 
11458
							#如果收到開頭為 "talkTo:"
11459
							#涵式說明:
11460
							#取得符合特定字首與字尾的字串
11461
							#回傳的結果:
11462
							#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
11463
							#$result["function"],當前執行的函數名稱.
11464
							#$result["error"],錯誤訊息陣列.
11465
							#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
11466
							#$result["returnString"],爲符合字首條件的字串內容。
11467
							#必填參數:
11468
							#$conf["checkString"],字串,要檢查的字串.
11469
							$conf["search::getMeetConditionsString"]["checkString"]=$buf;
11470
							#可省略參數:
11471
							#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
11472
							$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
11473
							#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
11474
							#$conf["tailWord"]="";
11475
							#參考資料:
11476
							#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
11477
							$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
11478
							unset($conf["search::getMeetConditionsString"]);
11479
 
11480
							#如果選找前置字串 "talkTo:" 失敗
11481
							if($getMeetConditionsString["status"]==="false"){
11482
 
11483
								#設置執行失敗
11484
								$result["status"]="false";
11485
 
11486
								#設置執行錯誤訊息
11487
								$result["error"]=$getMeetConditionsString;
11488
 
11489
								#回傳結果
11490
								return $result;
11491
 
11492
								}#if end
11493
 
11494
							#如果存在 "talkTo:" 前置字串
11495
							if($getMeetConditionsString["founded"]==="true"){
11496
 
66 liveuser 11497
								#如果尚未認證
11498
								if($connections[$conIndex]["auth"]==="false"){
11499
 
11500
									#設置要回傳的訊息
11501
									$talkback=json_encode("permission denied");
11502
 
11503
									#如果是 ws 模式
11504
									if($conf["wsMode"]==="true"){
11505
 
11506
										#如果已經 handshake 過
11507
										if($connections[$conIndex]["handshaked"]==="true"){
11508
 
11509
											#如果要 unmask	
11510
											if($connections[$conIndex]["unmask"]==="true"){
11511
 
11512
												#函式說明:
11513
												#加密 handshake 後要傳送的訊息 
11514
												#回傳結果:
11515
												#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11516
												#$result["error"],執行不正常結束的錯訊息陣列.
11517
												#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11518
												#$result["argu"],陣列,使用的參數.
11519
												#必填參數:
11520
												#$conf["text"],字串,要加密的訊息.
11521
												$conf["webSock::encode"]["text"]=$talkback; 
11522
												#可省略參數:
11523
												#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11524
												#$conf["payloadIsBin"]="false";
11525
												#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11526
												#$conf["ping"]="false";
11527
												#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11528
												#$conf["pong"]="false";
11529
												#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11530
												#$conf["frames"]=array();
11531
												#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11532
												#$conf["mask"]="false";
11533
												#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11534
												#$conf["debug"]="false";
11535
												#參考資料:
11536
												#無.
11537
												#備註:
11538
												#目前$conf["text"]長度超過125會出錯.
11539
												$talkback=webSock::encode($conf["webSock::encode"]);
11540
												unset($conf["webSock::encode"]);
11541
 
11542
												#如果執行失敗
11543
												if($talkback["status"]==="false"){
11544
 
11545
													#印出結果
11546
													var_dump($talkback);
11547
 
11548
													#結束執行
11549
													exit;
11550
 
11551
													}#if end
11552
 
11553
												#debug
11554
												#var_dump(__LINE__,$talkback);
11555
 
11556
												}#if end
11557
 
11558
											}#if end
11559
 
11560
										}#if end
11561
 
11562
									#反之不為 web socket 訊息
11563
									else{
11564
 
11565
										#儲存成只有一個訊息
11566
										$talkback["content"][]=$talkback;
11567
 
11568
										}#else
11569
 
11570
									#針對每個訊息的分段
11571
									foreach($talkback["content"] as $msg){
11572
 
11573
										#回傳訊息
11574
										$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11575
 
11576
										#debug
11577
										#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11578
 
11579
										}#foreach end
11580
 
11581
									#跳到下一輪
11582
									continue;
11583
 
11584
									}#if end
11585
 
3 liveuser 11586
								#用 "talkTo:" 分割 $buf
11587
								#涵式說明:
11588
								#將固定格式的字串分開,並回傳分開的結果。
11589
								#回傳結果:
11590
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11591
								#$result["error"],錯誤訊息陣列
11592
								#$result["function"],當前執行的函數名稱.
11593
								#$result["oriStr"],要分割的原始字串內容
11594
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
11595
								#$result["dataCounts"],爲總共分成幾段
11596
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
11597
								#必填的參數:
11598
								$conf["stringProcess::spiltString"]["stringIn"]=$buf;#要處理的字串。
11599
								$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
11600
								#可省略參數:
11601
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
11602
								$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
11603
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
11604
								unset($conf["stringProcess::spiltString"]);
11605
 
11606
								#如果分割字串失敗
11607
								if($spiltString["status"]==="false"){
11608
 
11609
									#設置執行失敗
11610
									$result["status"]="false";
11611
 
11612
									#設置執行錯誤訊息
11613
									$result["error"]=$spiltString;
11614
 
11615
									#回傳結果
11616
									return $result;
11617
 
11618
									}#if end
11619
 
11620
								#如果剛好分割出一筆資料
11621
								if($spiltString["dataCounts"]===1){
11622
 
11623
									#取得自己的id
11624
									$myId=$connections[$conIndex]["id"];
11625
 
11626
									#取得講話對象的id
11627
									$toId=$spiltString["dataArray"][0];
11628
 
11629
									#設置對象不存在的識別
11630
									$targetExist=false;
11631
 
11632
									#設置通話對象的key
11633
									$targetKey="";
11634
 
11635
									#取得除了自己的id以外的所有連線
11636
									foreach($connections as $index=>$talkInfo){
11637
 
11638
										#除了自己的id
11639
										if($talkInfo["id"]!==$myId){
11640
 
11641
											#如果存在要對話的對象
11642
											if($talkInfo["id"]===$toId){
11643
 
11644
												#設置對象存在的識別
11645
												$targetExist=true;
11646
 
11647
												#通話對象的key
11648
												$targetKey=$index;
11649
 
11650
												}#if end
11651
 
11652
											}#if end
11653
 
11654
										}#for each end
11655
 
11656
									#如果通話對象存在
11657
									if($targetExist){
11658
 
11659
										#保存自己的通話對象
11660
										$connections[$conIndex]["talkTo"][]=$toId;
11661
 
11662
										#設置要給自己看的訊息
11663
										$talkback="您與 ".$toId." 展開對話";
11664
 
11665
										#json encode 要給自己看的訊息
11666
										$talkback=json_encode($talkback).PHP_EOL;
11667
 
11668
										#如果是 ws 模式
11669
										if($conf["wsMode"]==="true"){
11670
 
11671
											#如果已經 handshake 過
11672
											if($connections[$conIndex]["handshaked"]==="true"){
11673
 
11674
												#如果要 unmask	
11675
												if($connections[$conIndex]["unmask"]==="true"){
11676
 
11677
													#函式說明:
11678
													#加密 handshake 後要傳送的訊息 
11679
													#回傳結果:
11680
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11681
													#$result["error"],執行不正常結束的錯訊息陣列.
11682
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11683
													#$result["argu"],陣列,使用的參數.
11684
													#必填參數:
11685
													#$conf["text"],字串,要加密的訊息.
11686
													$conf["webSock::encode"]["text"]=$talkback; 
11687
													#可省略參數:
11688
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11689
													#$conf["payloadIsBin"]="false";
11690
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11691
													#$conf["ping"]="false";
11692
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11693
													#$conf["pong"]="false";
11694
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11695
													#$conf["frames"]=array();
11696
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11697
													#$conf["mask"]="false";
11698
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11699
													#$conf["debug"]="false";
11700
													#參考資料:
11701
													#無.
11702
													#備註:
11703
													#目前$conf["text"]長度超過125會出錯.
11704
													$talkback=webSock::encode($conf["webSock::encode"]);
11705
													unset($conf["webSock::encode"]);
11706
 
11707
													#如果執行失敗
11708
													if($talkback["status"]==="false"){
11709
 
11710
														#印出結果
11711
														var_dump($talkback);
11712
 
11713
														#結束執行
11714
														exit;
11715
 
11716
														}#if end
11717
 
11718
													#debug
11719
													#var_dump(__LINE__,$talkback);
11720
 
11721
													}#if end
66 liveuser 11722
 
3 liveuser 11723
												}#if end
11724
 
11725
											}#if end
11726
 
11727
										#反之不為 web socket 訊息
11728
										else{
11729
 
11730
											#儲存成只有一個訊息
11731
											$talkback["content"][]=$talkback;
11732
 
11733
											}#else
11734
 
11735
										#針對每個訊息的分段
11736
										foreach($talkback["content"] as $msg){
11737
 
11738
											#回傳訊息
11739
											$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11740
 
11741
											#debug
11742
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
66 liveuser 11743
 
3 liveuser 11744
											}#foreach end
11745
 
11746
										#讓對方可以跟自己對話
11747
										$connections[$targetKey]["talkTo"][]=$myId;
11748
 
11749
										#設置要給對方看的訊息
11750
										$talkback=$connections[$conIndex]["id"]." 與您展開對話";
11751
 
11752
										#json encode 設置要給對方看的訊息
11753
										$talkback=json_encode($talkback);
11754
 
11755
										#如果是 ws 模式
11756
										if($conf["wsMode"]==="true"){
11757
 
11758
											#如果已經 handshake 過
11759
											if($connections[$conIndex]["handshaked"]==="true"){
11760
 
11761
												#如果要 unmask	
11762
												if($connections[$conIndex]["unmask"]==="true"){
11763
 
11764
													#函式說明:
11765
													#加密 handshake 後要傳送的訊息 
11766
													#回傳結果:
11767
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11768
													#$result["error"],執行不正常結束的錯訊息陣列.
11769
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11770
													#$result["argu"],陣列,使用的參數.
11771
													#必填參數:
11772
													#$conf["text"],字串,要加密的訊息.
11773
													$conf["webSock::encode"]["text"]=$talkback; 
11774
													#可省略參數:
11775
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11776
													#$conf["payloadIsBin"]="false";
11777
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11778
													#$conf["ping"]="false";
11779
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11780
													#$conf["pong"]="false";
11781
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11782
													#$conf["frames"]=array();
11783
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11784
													#$conf["mask"]="false";
11785
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11786
													#$conf["debug"]="false";
11787
													#參考資料:
11788
													#無.
11789
													#備註:
11790
													#目前$conf["text"]長度超過125會出錯.
11791
													$talkback=webSock::encode($conf["webSock::encode"]);
11792
													unset($conf["webSock::encode"]);
11793
 
11794
													#如果執行失敗
11795
													if($talkback["status"]==="false"){
11796
 
11797
														#印出結果
11798
														var_dump($talkback);
11799
 
11800
														#結束執行
11801
														exit;
11802
 
11803
														}#if end
11804
 
11805
													#debug
11806
													#var_dump(__LINE__,$talkback);
11807
 
11808
													}#if end
66 liveuser 11809
 
3 liveuser 11810
												}#if end
11811
 
11812
											}#if end
11813
 
11814
										#反之不為 web socket 訊息
11815
										else{
11816
 
11817
											#儲存成只有一個訊息
11818
											$talkback["content"][]=$talkback;
11819
 
11820
											}#else
11821
 
11822
										#針對每個訊息的分段
11823
										foreach($talkback["content"] as $msg){
11824
 
11825
											#給對方看的訊息
11826
											$socket_write=socket_write($connections[$targetKey]["connect"], $msg, strlen($msg));
11827
 
11828
											#debug
11829
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11830
 
11831
											}#foreach end
11832
 
11833
										#換一個連線
11834
										continue;
11835
 
11836
										}#if end
11837
 
11838
									}#if end
11839
 
11840
								}#if end
11841
 
11842
							}#if end
66 liveuser 11843
 
11844
						*/
11845
 
11846
						#如果收到的訊息是 runPhpWhenIdle: 開頭
11847
						if(strpos($buf,"runPhpWhenIdle:")===0){
11848
 
11849
							#如果尚未認證
11850
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11851
 
66 liveuser 11852
								#設置要回傳的訊息
11853
								$talkback=json_encode("permission denied");
11854
 
11855
								#如果是 ws 模式
11856
								if($conf["wsMode"]==="true"){
11857
 
11858
									#如果已經 handshake 過
11859
									if($connections[$conIndex]["handshaked"]==="true"){
11860
 
11861
										#如果要 unmask	
11862
										if($connections[$conIndex]["unmask"]==="true"){
11863
 
11864
											#函式說明:
11865
											#加密 handshake 後要傳送的訊息 
11866
											#回傳結果:
11867
											#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11868
											#$result["error"],執行不正常結束的錯訊息陣列.
11869
											#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11870
											#$result["argu"],陣列,使用的參數.
11871
											#必填參數:
11872
											#$conf["text"],字串,要加密的訊息.
11873
											$conf["webSock::encode"]["text"]=$talkback; 
11874
											#可省略參數:
11875
											#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11876
											#$conf["payloadIsBin"]="false";
11877
											#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11878
											#$conf["ping"]="false";
11879
											#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11880
											#$conf["pong"]="false";
11881
											#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11882
											#$conf["frames"]=array();
11883
											#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11884
											#$conf["mask"]="false";
11885
											#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11886
											#$conf["debug"]="false";
11887
											#參考資料:
11888
											#無.
11889
											#備註:
11890
											#目前$conf["text"]長度超過125會出錯.
11891
											$talkback=webSock::encode($conf["webSock::encode"]);
11892
											unset($conf["webSock::encode"]);
11893
 
11894
											#如果執行失敗
11895
											if($talkback["status"]==="false"){
11896
 
11897
												#印出結果
11898
												var_dump($talkback);
11899
 
11900
												#結束執行
11901
												exit;
11902
 
11903
												}#if end
11904
 
11905
											#debug
11906
											#var_dump(__LINE__,$talkback);
11907
 
11908
											}#if end
11909
 
11910
										}#if end
11911
 
11912
									}#if end
11913
 
11914
								#反之不為 web socket 訊息
11915
								else{
11916
 
11917
									#儲存成只有一個訊息
11918
									$talkback["content"][]=$talkback;
11919
 
11920
									}#else
11921
 
11922
								#針對每個訊息的分段
11923
								foreach($talkback["content"] as $msg){
11924
 
11925
									#回傳訊息
11926
									$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11927
 
11928
									#debug
11929
									#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11930
 
11931
									}#foreach end
11932
 
11933
								#跳到下一輪
11934
								continue;
11935
 
11936
								}#if end
11937
 
11938
							#剔除開頭的 "runPhpWhenIdle:"
11939
							#函式說明:
11940
							#將字串特定關鍵字與其前面的內容剔除
11941
							#回傳結果:
11942
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11943
							#$result["error"],錯誤訊息陣列.
11944
							#$result["warning"],警告訊息鎮列.
11945
							#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
11946
							#$result["function"],當前執行的函數名稱.
11947
							#$result["argu"],使用的參數.
11948
							#$result["oriStr"],要處理的原始字串內容.
11949
							#$result["content"],處理好的的字串內容.
11950
							#$result["deleted"],被移除的內容.
11951
							#必填參數:
11952
							#$conf["stringIn"],字串,要處理的字串.
11953
							$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$buf;
11954
							#$conf["keyWord"],字串,特定字串.
11955
							$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="runPhpWhenIdle:";
11956
							#可省略參數:
11957
							#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
11958
							#$conf["recursive"]="true";
11959
							#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
11960
							#$conf["lastResult"]=$delStrBeforeKeyWord;
11961
							#參考資料:
11962
							#無.
11963
							#備註:
11964
							#無.
11965
							$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
11966
							unset($conf["stringProcess::delStrBeforeKeyWord"]);
11967
 
11968
							#如果執行失敗
11969
							if($delStrBeforeKeyWord["status"]==="false"){
11970
 
11971
								#印出結果
11972
								var_dump($delStrBeforeKeyWord);
11973
 
11974
								#結束執行
11975
								exit;
11976
 
11977
								}#if end
11978
 
11979
							#設置要執行的php程式
11980
							$php2runWhenIdle[]=$delStrBeforeKeyWord["content"];
11981
 
11982
							#跳到下一輪
11983
							continue;
11984
 
11985
							}#if end
11986
 
11987
						/* 舊的寫法
11988
 
3 liveuser 11989
						#如果收到的是 quit
11990
						if ($buf === 'quit' ) {
11991
 
11992
							#設置要回傳的訊息
11993
							$talkback="結束與 server 的連線";
11994
 
11995
							#json encode 要回傳的訊息
11996
							$talkback=json_encode($talkback).PHP_EOL;
11997
 
11998
							#如果是 ws 模式
11999
							if($conf["wsMode"]==="true"){
12000
 
12001
								#如果已經 handshake 過
12002
								if($connections[$conIndex]["handshaked"]==="true"){
12003
 
12004
									#如果要 unmask	
12005
									if($connections[$conIndex]["unmask"]==="true"){
12006
 
12007
										#函式說明:
12008
										#加密 handshake 後要傳送的訊息 
12009
										#回傳結果:
12010
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12011
										#$result["error"],執行不正常結束的錯訊息陣列.
12012
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12013
										#$result["argu"],陣列,使用的參數.
12014
										#必填參數:
12015
										#$conf["text"],字串,要加密的訊息.
12016
										$conf["webSock::encode"]["text"]=$talkback; 
12017
										#可省略參數:
12018
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12019
										#$conf["payloadIsBin"]="false";
12020
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12021
										#$conf["ping"]="false";
12022
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12023
										#$conf["pong"]="false";
12024
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12025
										#$conf["frames"]=array();
12026
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12027
										#$conf["mask"]="false";
12028
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12029
										#$conf["debug"]="false";
12030
										#參考資料:
12031
										#無.
12032
										#備註:
12033
										#目前$conf["text"]長度超過125會出錯.
12034
										$talkback=webSock::encode($conf["webSock::encode"]);
12035
										unset($conf["webSock::encode"]);
12036
 
12037
										#如果執行失敗
12038
										if($talkback["status"]==="false"){
12039
 
12040
											#印出結果
12041
											var_dump($talkback);
12042
 
12043
											#結束執行
12044
											exit;
12045
 
12046
											}#if end
12047
 
12048
										#debug
12049
										#var_dump(__LINE__,$talkback);
12050
 
12051
										}#if end
12052
 
12053
									}#if end
12054
 
12055
								}#if end
12056
 
12057
							#反之不為 web socket 訊息
12058
							else{
12059
 
12060
								#儲存成只有一個訊息
12061
								$talkback["content"][]=$talkback;
12062
 
12063
								}#else
12064
 
12065
							#針對每個訊息的分段
12066
							foreach($talkback["content"] as $msg){
12067
 
12068
								#回傳訊息
12069
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
12070
 
12071
								#debug
12072
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12073
 
12074
								}#foreach end
12075
 
12076
							#關閉被 client 的連線	
12077
							socket_close($con["connect"]);
12078
 
12079
							#清理連線的陣列
12080
							unset($connections[$conIndex]);
12081
 
12082
							#跳到下一輪
12083
							continue;
12084
 
12085
							}#if end
12086
 
66 liveuser 12087
						*/
12088
 
12089
						/* 舊的寫法
12090
 
3 liveuser 12091
						#如果收到的是 shutdown	
12092
						if ($buf === 'shutdown') {
12093
 
66 liveuser 12094
							#如果尚未認證
12095
							if($connections[$conIndex]["auth"]==="false"){
12096
 
12097
								#設置要回傳的訊息
12098
								$talkback=json_encode("permission denied");
12099
 
12100
								#如果是 ws 模式
12101
								if($conf["wsMode"]==="true"){
12102
 
12103
									#如果已經 handshake 過
12104
									if($connections[$conIndex]["handshaked"]==="true"){
12105
 
12106
										#如果要 unmask	
12107
										if($connections[$conIndex]["unmask"]==="true"){
12108
 
12109
											#函式說明:
12110
											#加密 handshake 後要傳送的訊息 
12111
											#回傳結果:
12112
											#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12113
											#$result["error"],執行不正常結束的錯訊息陣列.
12114
											#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12115
											#$result["argu"],陣列,使用的參數.
12116
											#必填參數:
12117
											#$conf["text"],字串,要加密的訊息.
12118
											$conf["webSock::encode"]["text"]=$talkback; 
12119
											#可省略參數:
12120
											#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12121
											#$conf["payloadIsBin"]="false";
12122
											#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12123
											#$conf["ping"]="false";
12124
											#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12125
											#$conf["pong"]="false";
12126
											#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12127
											#$conf["frames"]=array();
12128
											#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12129
											#$conf["mask"]="false";
12130
											#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12131
											#$conf["debug"]="false";
12132
											#參考資料:
12133
											#無.
12134
											#備註:
12135
											#目前$conf["text"]長度超過125會出錯.
12136
											$talkback=webSock::encode($conf["webSock::encode"]);
12137
											unset($conf["webSock::encode"]);
12138
 
12139
											#如果執行失敗
12140
											if($talkback["status"]==="false"){
12141
 
12142
												#印出結果
12143
												var_dump($talkback);
12144
 
12145
												#結束執行
12146
												exit;
12147
 
12148
												}#if end
12149
 
12150
											#debug
12151
											#var_dump(__LINE__,$talkback);
12152
 
12153
											}#if end
12154
 
12155
										}#if end
12156
 
12157
									}#if end
12158
 
12159
								#反之不為 web socket 訊息
12160
								else{
12161
 
12162
									#儲存成只有一個訊息
12163
									$talkback["content"][]=$talkback;
12164
 
12165
									}#else
12166
 
12167
								#針對每個訊息的分段
12168
								foreach($talkback["content"] as $msg){
12169
 
12170
									#回傳訊息
12171
									$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
12172
 
12173
									#debug
12174
									#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12175
 
12176
									}#foreach end
12177
 
12178
								#跳到下一輪
12179
								continue;
12180
 
12181
								}#if end
12182
 
3 liveuser 12183
							#設置要回傳的訊息
12184
							$talkback="Server 即將關閉";
12185
 
12186
							#json encode 要回傳的訊息
12187
							$talkback=json_encode($talkback);
12188
 
12189
							#如果是 ws 模式
12190
							if($conf["wsMode"]==="true"){
12191
 
12192
								#如果已經 handshake 過
12193
								if($connections[$conIndex]["handshaked"]==="true"){
12194
 
12195
									#如果要 unmask	
12196
									if($connections[$conIndex]["unmask"]==="true"){
12197
 
12198
										#函式說明:
12199
										#加密 handshake 後要傳送的訊息 
12200
										#回傳結果:
12201
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12202
										#$result["error"],執行不正常結束的錯訊息陣列.
12203
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12204
										#$result["argu"],陣列,使用的參數.
12205
										#必填參數:
12206
										#$conf["text"],字串,要加密的訊息.
12207
										$conf["webSock::encode"]["text"]=$talkback; 
12208
										#可省略參數:
12209
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12210
										#$conf["payloadIsBin"]="false";
12211
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12212
										#$conf["ping"]="false";
12213
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12214
										#$conf["pong"]="false";
12215
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12216
										#$conf["frames"]=array();
12217
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12218
										#$conf["mask"]="false";
12219
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12220
										#$conf["debug"]="false";
12221
										#參考資料:
12222
										#無.
12223
										#備註:
12224
										#無.
12225
										$talkback=webSock::encode($conf["webSock::encode"]);
12226
										unset($conf["webSock::encode"]);
12227
 
12228
										#如果執行失敗
12229
										if($talkback["status"]==="false"){
12230
 
12231
											#印出結果
12232
											var_dump($talkback);
12233
 
12234
											#結束執行
12235
											exit;
12236
 
12237
											}#if end
12238
 
12239
										#debug
12240
										#var_dump(__LINE__,$talkback);
12241
 
12242
										}#if end
12243
 
12244
									}#if end
12245
 
12246
								}#if end
12247
 
12248
							#反之不為 web socket 訊息
12249
							else{
12250
 
12251
								#儲存成只有一個訊息
12252
								$talkback["content"][]=$talkback;
12253
 
12254
								}#else
12255
 
12256
							#針對每個訊息的分段
12257
							foreach($talkback["content"] as $msg){
12258
 
12259
								#回傳訊息
12260
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
12261
 
12262
								#debug
12263
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12264
 
12265
								}#foreach end
12266
 
12267
							#關閉用戶的連線
12268
							socket_close($con["connect"]);
12269
 
12270
							#跳到最外層,結束webSocket server
12271
							break 2;
12272
 
12273
							}#if end
12274
 
66 liveuser 12275
						*/
12276
 
12277
						/* 舊的寫法
12278
 
12279
						#如果收到的訊息為"auth:"開頭
12280
						if(strpos($buf,"auth:")){
12281
 
12282
							#剔除 "auth:" 前面的內容
12283
							#函式說明:
12284
							#將字串特定關鍵字與其前面的內容剔除
12285
							#回傳結果:
12286
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12287
							#$result["error"],錯誤訊息陣列.
12288
							#$result["warning"],警告訊息鎮列.
12289
							#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
12290
							#$result["function"],當前執行的函數名稱.
12291
							#$result["argu"],使用的參數.
12292
							#$result["oriStr"],要處理的原始字串內容.
12293
							#$result["content"],處理好的的字串內容.
12294
							#$result["deleted"],被移除的內容.
12295
							#必填參數:
12296
							#$conf["stringIn"],字串,要處理的字串.
12297
							$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$buf;
12298
							#$conf["keyWord"],字串,特定字串.
12299
							$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="auth:";
12300
							#可省略參數:
12301
							#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
12302
							#$conf["recursive"]="true";
12303
							#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
12304
							#$conf["lastResult"]=$delStrBeforeKeyWord;
12305
							#參考資料:
12306
							#無.
12307
							#備註:
12308
							#無.
12309
							$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
12310
							unset($conf["stringProcess::delStrBeforeKeyWord"]);
12311
 
12312
							#如果執行失敗
12313
							if($delStrBeforeKeyWord["status"]==="false"){
12314
 
12315
								#印出結果
12316
								var_dump($delStrBeforeKeyWord);
12317
 
12318
								#結束執行
12319
								exit;
12320
 
12321
								}#if end
12322
 
12323
							#還原編碼
12324
							#$delStrBeforeKeyWord["content"];
12325
 
12326
							#gpg解密
12327
							#...
12328
 
12329
							#檢查賬號密碼
12330
							#...
12331
 
12332
							}#if end
12333
 
12334
						*/
12335
 
12336
						#以下為其他收到的訊息內容
12337
 
12338
						/* 舊的寫法
12339
 
12340
						#如果尚未認證
12341
						if($connections[$conIndex]["auth"]==="false"){
12342
 
12343
							#設置要回傳的訊息
12344
							$talkback=json_encode("permission denied");
12345
 
12346
							#如果是 ws 模式
12347
							if($conf["wsMode"]==="true"){
12348
 
12349
								#如果已經 handshake 過
12350
								if($connections[$conIndex]["handshaked"]==="true"){
12351
 
12352
									#如果要 unmask	
12353
									if($connections[$conIndex]["unmask"]==="true"){
12354
 
12355
										#函式說明:
12356
										#加密 handshake 後要傳送的訊息 
12357
										#回傳結果:
12358
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12359
										#$result["error"],執行不正常結束的錯訊息陣列.
12360
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12361
										#$result["argu"],陣列,使用的參數.
12362
										#必填參數:
12363
										#$conf["text"],字串,要加密的訊息.
12364
										$conf["webSock::encode"]["text"]=$talkback; 
12365
										#可省略參數:
12366
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12367
										#$conf["payloadIsBin"]="false";
12368
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12369
										#$conf["ping"]="false";
12370
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12371
										#$conf["pong"]="false";
12372
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12373
										#$conf["frames"]=array();
12374
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12375
										#$conf["mask"]="false";
12376
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12377
										#$conf["debug"]="false";
12378
										#參考資料:
12379
										#無.
12380
										#備註:
12381
										#目前$conf["text"]長度超過125會出錯.
12382
										$talkback=webSock::encode($conf["webSock::encode"]);
12383
										unset($conf["webSock::encode"]);
12384
 
12385
										#如果執行失敗
12386
										if($talkback["status"]==="false"){
12387
 
12388
											#印出結果
12389
											var_dump($talkback);
12390
 
12391
											#結束執行
12392
											exit;
12393
 
12394
											}#if end
12395
 
12396
										#debug
12397
										#var_dump(__LINE__,$talkback);
12398
 
12399
										}#if end
12400
 
12401
									}#if end
12402
 
12403
								}#if end
12404
 
12405
							#反之不為 web socket 訊息
12406
							else{
12407
 
12408
								#儲存成只有一個訊息
12409
								$talkback["content"][]=$talkback;
12410
 
12411
								}#else
12412
 
12413
							#針對每個訊息的分段
12414
							foreach($talkback["content"] as $msg){
12415
 
12416
								#回傳訊息
12417
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
12418
 
12419
								#debug
12420
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12421
 
12422
								}#foreach end
12423
 
12424
							#跳到下一輪
12425
							continue;
12426
 
12427
							}#if end
12428
 
12429
						*/
12430
 
3 liveuser 12431
						#如果有指定的外掛函式
12432
						if(isset($conf["processFuncs"])){
12433
 
12434
							#針對每個用來處理輸入字串的函式
12435
							foreach($conf["processFuncs"] as $proFunc){
66 liveuser 12436
 
3 liveuser 12437
								#debug
12438
								#var_dump(__LINE__,$proFunc);
66 liveuser 12439
 
12440
								#函式說明:
12441
								#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
12442
								#回傳結果:
12443
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12444
								#$result["error"],執行不正常結束的錯訊息陣列.
12445
								#$result["argu"],陣列,使用的參數.
12446
								#必填參數:
12447
								#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
12448
								$conf["webSocket::checkAuth"]["data"]=&$buf;
12449
								#$conf["serverSock"],resource,web socket server socket
12450
								$conf["webSocket::checkAuth"]["serverSock"]=&$sock;
12451
								#$conf["clientSock"],$resource,web socket client socket
12452
								$conf["webSocket::checkAuth"]["clientSock"]=&$con["connect"];
12453
								#$conf["clientInfo"],陣列,web socket client info.
12454
								$conf["webSocket::checkAuth"]["clientInfo"]=&$connections[$conIndex];
12455
								#$conf["clientIndex"],整數.web socket client index.
12456
								$conf["webSocket::checkAuth"]["clientIndex"]=&$conIndex;
12457
								#$conf["allConn"],陣列,all web socket client info.
12458
								$conf["webSocket::checkAuth"]["allConn"]=&$connections;
12459
								#$conf["func"],字串,要檢查的是否具備權限的函式.
12460
								$conf["webSocket::checkAuth"]["func"]=$proFunc;
12461
								#可省略參數:
12462
								#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
12463
								#$conf["wsMode"]="true";
12464
								#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
12465
								#$conf["gpgId"]=gnupgId;
12466
								#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
12467
								#$conf["falseAllowFuncPlus"]=array();
12468
								#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
12469
								#$conf["publicAllowFuncPlus"]=array();
12470
								#參考資料:
12471
								#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
12472
								#備註:
12473
								#無.
12474
								$checkAuth=webSocket::checkAuth($conf["webSocket::checkAuth"]);
12475
								unset($conf["webSocket::checkAuth"]);
3 liveuser 12476
 
66 liveuser 12477
								#如果沒有權限
12478
								if($checkAuth["status"]==="false"){
12479
 
12480
									#換看下個 $proFunc
12481
									continue;
12482
 
12483
									}#if end
12484
 
3 liveuser 12485
								#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket
12486
								#https://www.php.net/manual/en/function.call-user-func.php
12487
								$param=array("data"=>&$buf,"serverSock"=>&$sock,"clientSock"=>&$con["connect"],"clientInfo"=>&$connections[$conIndex],"clientIndex"=>&$conIndex,"allConn"=>&$connections);
12488
								$params=array();
66 liveuser 12489
								$params[]=&$param;
12490
								$result=call_user_func_array($proFunc,$params);
3 liveuser 12491
 
12492
								#debug
12493
								#var_dump(__LINE__,$result);
12494
 
12495
								#如果有回傳結果
12496
								if($result!==NULL){
12497
 
12498
									#如果回傳的形態為陣列
12499
									if(gettype($result)==="array"){
12500
 
12501
										#如果執行出錯
12502
										if($result["status"]==="false"){
12503
 
12504
											#提示錯誤
12505
											echo "run function ".$proFunc." with params:".print_r($params,true)." failed!".PHP_EOL;
12506
 
12507
											#提示會往後面執行
12508
											echo "go next function.".PHP_EOL;
12509
 
12510
											#跳到下一輪
12511
											#continue;
12512
 
12513
											}#if end
12514
 
12515
										#如果結果為跳下一輪
12516
										else if($result["status"]==="continue"){
12517
 
12518
											#提示成功
12519
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
12520
 
12521
											#提示會往後面執行
12522
											echo "go next function.".PHP_EOL;
12523
 
12524
											#跳下一輪
12525
											#continue;
12526
 
12527
											}#if end
12528
 
12529
										#如果已經被處理好了且不准移交給後面的處理
12530
										else if($result["status"]==="true"){
12531
 
12532
											#提示成功
12533
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
12534
 
12535
											#提示在此打住.
12536
											echo "end process,".PHP_EOL;
12537
 
12538
											#後面就不做了
12539
											break;
12540
 
12541
											}#if end
12542
 
12543
										}#if end
12544
 
12545
									#反之回傳形態錯誤
12546
									else{
12547
 
12548
										#提示錯誤
12549
										echo "run function ".$proFunc." with params:".print_r($params,true)." success, but format of return is incorrect!".PHP_EOL;
12550
 
12551
										#提示會往後面執行
12552
										echo "go next function.".PHP_EOL;
12553
 
12554
										}#else end
12555
 
12556
									}#if end
12557
 
12558
								#如果沒有回傳結果
12559
								else{
12560
 
12561
									#提示錯誤
12562
									echo "run function ".$proFunc." with params:".print_r($params,true)." success, but there is no return!".PHP_EOL;
12563
 
12564
									#跳下一輪
12565
									#continue;
12566
 
12567
									}#else end
12568
 
12569
								}#foreach end
12570
 
12571
							}#if end
12572
 
12573
						#如果有要接收訊息的id
12574
						if(count($connections[$conIndex]["talkTo"])>0){
12575
 
12576
							#初始化要傳送給哪些id
12577
							$broadcastId=array();
12578
 
12579
							#依據每個連線資訊
12580
							foreach($connections as $index=>$broadcast){
12581
 
12582
								#儲存每個
12583
								$broadcastId[$index]=$broadcast["id"];
12584
 
12585
								}#foreach end
12586
 
12587
							#檢查哪些人是要接收到訊息的	
12588
							#涵式說明:
12589
							#檢查多個數值,是否與陣列裏面的某些元素相同。
12590
							#回傳的結果:
12591
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12592
							#$result["function"],當前執行的函數
12593
							#$result["error"],涵式錯誤訊息,若爲""則表示沒有錯誤 
12594
							#$result["founded"][$i],若爲"false"代表沒有相同的元素;反之"true"代表有相同的元素,$i爲第i+1個$conf["inputElement"]參數判斷後的結果.
12595
							#$result["key"][$i],為找到$conf["inputElement"]第$i+1個元素的值是在$conf["blackBoxElement"]中的哪個元素.
12596
							#必填的參數:
12597
							$conf["search::checkEquality"]["inputElement"]=$connections[$conIndex]["talkTo"];#想要找到的變數/數值.
12598
							$conf["search::checkEquality"]["blackBoxElement"]=$broadcastId;#要從哪些變數/數值去尋找.
12599
							$checkEquality=search::checkEquality($conf["search::checkEquality"]);
12600
							unset($conf["search::checkEquality"]);
12601
 
12602
							#如果檢查失敗
12603
							if($checkEquality["status"]==="false"){
12604
 
12605
								#設置執行失敗
12606
								$result["status"]="false";
12607
 
12608
								#設置執行錯誤訊息
12609
								$result["error"]=$checkEquality;
12610
 
12611
								#回傳結果
12612
								return $result;
12613
 
12614
								}#if end
12615
 
12616
							#針對每個搜尋的結果
12617
							foreach($checkEquality["founded"] as $key=>$found){
12618
 
12619
								#如果有找到
12620
								if($found==="true"){
12621
 
12622
									#取得要接收訊息的msgSock
12623
									$receiveMsgSock=$connections[$checkEquality["key"][$key]]["connect"];
12624
 
12625
									#設置要傳送的訊息
12626
									$talkback = $connections[$conIndex]["id"]." said ".$buf;
12627
 
12628
									#json encode 要傳送的訊息
12629
									$talkback=json_encode($talkback).PHP_EOL;
12630
 
12631
									#如果是 ws 模式
12632
									if($conf["wsMode"]==="true"){
12633
 
12634
										#如果已經 handshake 過
12635
										if($connections[$conIndex]["handshaked"]==="true"){
12636
 
12637
											#如果要 unmask	
12638
											if($connections[$conIndex]["unmask"]==="true"){
12639
 
12640
												#加密
12641
												$conf["webSock::encode"]["text"]=$talkback;
12642
												$talkback=webSock::encode($conf["webSock::encode"]);
12643
												unset($conf["webSock::encode"]);
12644
 
12645
												}#if end
12646
 
12647
											}#if end
12648
 
12649
										}#if end
12650
 
12651
									#反之不為 web socket 訊息
12652
									else{
12653
 
12654
										#儲存成只有一個訊息
12655
										$talkback["content"][]=$talkback;
12656
 
12657
										}#else
12658
 
12659
 
12660
									#針對每個訊息的分段
12661
									foreach($talkback["content"] as $msg){
12662
 
12663
										#回傳訊息
12664
										$socket_write=socket_write($receiveMsgSock, $msg, strlen($msg));
12665
 
12666
										#debug
12667
										#var_dump(__LINE__,$receiveMsgSock,socket_strerror(socket_last_error($receiveMsgSock)));
12668
 
12669
										}#foreach end
12670
 
12671
									}#if end
12672
 
12673
								}#foreach end
12674
 
12675
							}#if end
12676
 
12677
						}#if end
12678
 
12679
					}#foreach end
12680
 
12681
				#do end 
12682
				}while(true);
12683
 
12684
			#提示關閉 server socket
12685
			echo "關閉 server socket".PHP_EOL;
12686
 
12687
			#關閉 socket
12688
			socket_close($sock);
12689
 
12690
			#do end
12691
			}while(true);
12692
 
12693
		#設置執行正常
12694
		$result["status"]="true";
12695
 
12696
		#回傳結果
12697
		return $result;
12698
 
12699
		}#function nativeSocketTcpIpServer end
12700
 
12701
	/*	
12702
	#函式說明:
12703
	#連線到webSocket,會印出建立好的unixDomainSocket位置與名稱.
12704
	#回傳結果:
12705
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
12706
	#$result["error"],錯誤訊息陣列.
12707
	#$resutl["function"],當前執行的涵式名稱.
12708
	#$result["content"],取得的回應.
12709
	#$result["argu"],所使用的參數.
12710
	#$result["Sec-WebSocket-Accept"],所得到的Sec-WebSocket-Accept.
12711
	#必填參數:
12712
	#無.
12713
	#可省略參數:
12714
	#$conf["targetServr"],字串,要連線的目標,預設為"localhost".
12715
	#$conf["targetServr"]="";
12716
	#$conf["targetPort"],字串,要連線的目標port.
12717
	#$conf["targetPort"]="";
12718
	#$conf["ssl"],字串,是否要走wss,預設為"false",不走wss;反之為"true".
12719
	#$conf["ssl"]="false";
12720
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12721
	#$conf["debug"]="false";
12722
	#參考資料:
12723
	#https://www.php.net/manual/en/function.stream-socket-client.php
12724
	#https://www.php.net/manual/en/function.stream-context-create.php
12725
	#https://www.php.net/manual/en/context.ssl.php
12726
	#備註:
12727
	#建構中...
12728
	*/
12729
	public static function clientDaemon(&$conf){
12730
 
12731
		#初始化要回傳的結果
12732
		$result=array();
12733
 
12734
		#取得當前執行的函數名稱
12735
		$result["function"]=__FUNCTION__;
12736
 
12737
		#涵式說明:
12738
		#判斷當前環境為web還是cmd
12739
		#回傳結果:
12740
		#$result,"web"或"cmd"
12741
		if(csInformation::getEnv()==="web"){
12742
 
12743
			#設置執行失敗
12744
			$result["status"]="false";
12745
 
12746
			#設置執行錯誤訊息
12747
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
12748
 
12749
			#回傳結果
12750
			return $result;
12751
 
12752
			}#if end
12753
 
12754
		#取得參數
12755
		$result["argu"]=$conf;
12756
 
12757
		#如果 $conf 不為陣列
12758
		if(gettype($conf)!="array"){
12759
 
12760
			#設置執行失敗
12761
			$result["status"]="false";
12762
 
12763
			#設置執行錯誤訊息
12764
			$result["error"][]="\$conf變數須為陣列形態";
12765
 
12766
			#如果傳入的參數為 null
12767
			if($conf==null){
12768
 
12769
				#設置執行錯誤訊息
12770
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
12771
 
12772
				}#if end
12773
 
12774
			#回傳結果
12775
			return $result;
12776
 
12777
			}#if end
12778
 
12779
		#檢查參數
12780
		#函式說明:
12781
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
12782
		#回傳結果:
12783
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12784
		#$result["error"],執行不正常結束的錯訊息陣列.
12785
		#$result["simpleError"],簡單表示的錯誤訊息.
12786
		#$result["function"],當前執行的函式名稱.
12787
		#$result["argu"],設置給予的參數.
12788
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
12789
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
12790
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
12791
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
12792
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
12793
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
12794
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
12795
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
12796
		#必填參數:
12797
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
12798
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
12799
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
12800
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
12801
		#可省略參數:
12802
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
12803
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array();
12804
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
12805
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array();
12806
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
12807
		#$conf["canBeEmptyString"]="false";
12808
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
12809
		#$conf["canNotBeEmpty"]=array();
12810
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
12811
		#$conf["canBeEmpty"]=array();
12812
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
12813
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("targetServr","targetPort","ssl","debug");
12814
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
12815
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("targetServr","targetPort","ssl","debug");
12816
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
12817
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","string");
12818
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
12819
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("localhost",null,"false","false");
12820
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
12821
		#$conf["disallowAllSkipableVarIsEmpty"]="";
12822
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
12823
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
12824
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
12825
		#$conf["disallowAllSkipableVarNotExist"]="";
12826
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
12827
		#$conf["arrayCountEqualCheck"][]=array();
12828
		#參考資料:
12829
		#array_keys=>http://php.net/manual/en/function.array-keys.php
12830
		#備註:
12831
		#無.
12832
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
12833
		unset($conf["variableCheck::checkArguments"]);
12834
 
12835
		#如果檢查參數失敗
12836
		if($checkArguments["status"]==="false"){
12837
 
12838
			#設置執行失敗
12839
			$result["status"]="false";
12840
 
12841
			#設置執行錯誤訊息
12842
			$result["error"]=$checkArguments;
12843
 
12844
			#回傳結果
12845
			return $result;
12846
 
12847
			}#if end
12848
 
12849
		#如果檢查參數不通過
12850
		if($checkArguments["passed"]==="false"){
12851
 
12852
			#設置執行失敗
12853
			$result["status"]="false";
12854
 
12855
			#設置執行錯誤訊息
12856
			$result["error"]=$checkArguments;
12857
 
12858
			#回傳結果
12859
			return $result;
12860
 
12861
			}#if end
12862
 
12863
		#如果targetPort沒有設置
12864
		if(!isset($conf["targetPort"])){
12865
 
12866
			#port預設為80
12867
			$conf["targetPort"]="80";
12868
 
12869
			#如果有啟用 ssl
12870
			if($conf["ssl"]==="true"){
12871
 
12872
				#port預設為443
12873
				$conf["targetPort"]="443";
12874
 
12875
				}#if end
12876
 
12877
			}#if end
12878
 
12879
		#回報任何錯誤
12880
		#error_reporting(E_ALL);
12881
 
12882
		#如果要使用 ssl
12883
		if($conf["ssl"]==="true"){
12884
 
12885
			#預設的path
12886
			$path="/";
12887
 
12888
			#分割出server位置與對應GET的path
12889
			#函式說明:
12890
			#將固定格式的字串分開,並回傳分開的結果.
12891
			#回傳結果:
12892
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12893
			#$result["error"],錯誤訊息陣列
12894
			#$result["function"],當前執行的函數名稱.
12895
			#$result["argu"],使用的參數.
12896
			#$result["oriStr"],要分割的原始字串內容
12897
			#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
12898
			#$result["dataCounts"],爲總共分成幾段
12899
			#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
12900
			#必填參數:
12901
			#$conf["stringIn"],字串,要處理的字串.
12902
			$conf["stringProcess::spiltString"]["stringIn"]=$conf["targetServr"];
12903
			#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
12904
			$conf["stringProcess::spiltString"]["spiltSymbol"]="/";
12905
			#可省略參數:
12906
			#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
12907
			$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
12908
			#參考資料:
12909
			#無.
12910
			#備註:
12911
			#無.
12912
			$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
12913
			unset($conf["stringProcess::spiltString"]);
12914
 
12915
			#如果檢查執行失敗
12916
			if($spiltString["status"]==="false"){
12917
 
12918
				#設置執行失敗
12919
				$result["status"]="false";
12920
 
12921
				#設置執行錯誤訊息
12922
				$result["error"]=$spiltString;
12923
 
12924
				#回傳結果
12925
				return $result;
12926
 
12927
				}#if end
12928
 
12929
			#如果含有 /
12930
			if($spiltString["found"]==="true"){
12931
 
12932
				#函式說明:
12933
				#將字串特定關鍵字與其前面的內容剔除
12934
				#回傳結果:
12935
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12936
				#$result["error"],錯誤訊息陣列.
12937
				#$result["warning"],警告訊息鎮列.
12938
				#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
12939
				#$result["function"],當前執行的函數名稱.
12940
				#$result["argu"],使用的參數.
12941
				#$result["oriStr"],要處理的原始字串內容.
12942
				#$result["content"],處理好的的字串內容.	
12943
				#必填參數:
12944
				#$conf["stringIn"],字串,要處理的字串.
12945
				$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$conf["targetServr"];
12946
				#$conf["keyWord"],字串,特定字串.
12947
				$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="/";
12948
				#可省略參數:
12949
				#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
12950
				#$conf["recursive"]="true";
12951
				#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
12952
				#$conf["lastResult"]=$delStrBeforeKeyWord;
12953
				#參考資料:
12954
				#無.
12955
				#備註:
12956
				#無.
12957
				$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
12958
				unset($conf["stringProcess::delStrBeforeKeyWord"]);
12959
 
12960
				#如果檢查執行失敗
12961
				if($delStrBeforeKeyWord["status"]==="false"){
12962
 
12963
					#設置執行失敗
12964
					$result["status"]="false";
12965
 
12966
					#設置執行錯誤訊息
12967
					$result["error"]=$delStrBeforeKeyWord;
12968
 
12969
					#回傳結果
12970
					return $result;
12971
 
12972
					}#if end
12973
 
12974
				#如果該存在的 / 不存在
12975
				if($delStrBeforeKeyWord["founded"]==="false"){
12976
 
12977
					#設置執行失敗
12978
					$result["status"]="false";
12979
 
12980
					#設置執行錯誤訊息
12981
					$result["error"]=$delStrBeforeKeyWord;
12982
 
12983
					#回傳結果
12984
					return $result;
12985
 
12986
					}#if end
12987
 
12988
				#設置 path
12989
				$path="/".$delStrBeforeKeyWord["content"];
12990
 
12991
				#如果有切出 path
12992
				if($spiltString["dataCounts"]>=2){
12993
 
12994
					#另存peer host name
12995
					$peerHostName=$spiltString["dataArray"][0];
12996
 
12997
					#更新 targetServr
12998
					$conf["targetServr"]=$peerHostName;
12999
 
13000
					}#if end
13001
 
13002
				}#if end
13003
 
13004
			#初始化給 stream_context_create 用的參數
13005
			$paramsForStream_context_create=array();
13006
 
13007
			#設置為http相關的參數
13008
			#$paramsForStream_context_create["http"]=array();
13009
 
13010
			#method為HEAD
13011
			#$paramsForStream_context_create["http"]["method"]="HEAD ".$path;
13012
 
13013
			#HTTP/1.1
13014
			#$paramsForStream_context_create["http"]["protocol_version"]="1.1";
13015
 
13016
			#初始化header
13017
			#$paramsForStream_context_create["http"]["header"]=array();
13018
 
13019
			#設置header Host
13020
			#$paramsForStream_context_create["http"]["header"][]="Host: ".$conf["targetServr"];
13021
 
13022
			#設置header Upgrade
13023
			#$paramsForStream_context_create["http"]["header"][]="Upgrade: websocket";
13024
 
13025
			#設置header Connection
13026
			#$paramsForStream_context_create["http"]["header"][]="Connection: Upgrade";
13027
 
13028
			#設置header Sec-WebSocket-Version
13029
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Version: 13";
13030
 
13031
			#設置header Sec-WebSocket-Key
13032
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==";
13033
 
13034
			#body content
13035
			#$paramsForStream_context_create["http"]["content"]="";
13036
 
13037
			#設置為ssl相關的參數
13038
			$paramsForStream_context_create["ssl"]=array();
13039
 
13040
			#被連線端的網域名稱
13041
			#$paramsForStream_context_create["ssl"]["peer_name"]=$conf["targetServr"];
13042
 
13043
			#verify_peer
13044
			#$paramsForStream_context_create["ssl"]["verify_peer"]=true;
13045
			#$paramsForStream_context_create["ssl"]["verify_peer"]=false;
13046
 
13047
			#verify_peer_name
13048
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=true;
13049
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=false;
13050
 
13051
			#allow_self_signed,允許沒有受到認可的憑證
13052
			#$paramsForStream_context_create["ssl"]["allow_self_signed"]=false; 
13053
 
13054
			#cafile
13055
			$paramsForStream_context_create["ssl"]["cafile"]="/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
13056
 
13057
			#capath
13058
			#$paramsForStream_context_create["ssl"]["capath"]="/etc/pki/ca-trust/extracted/pem/directory-hash/";
13059
 
13060
			#local_cert
13061
			#$paramsForStream_context_create["ssl"]["local_cert"]="/etc/pki/tls/certs/php-selfsigned-and-key.crt";
13062
 
13063
			#local_pk
13064
			#$paramsForStream_context_create["ssl"]["local_pk"]="/etc/pki/tls/private/php-selfsigned.key";
13065
 
13066
			#capture_peer_cert
13067
			$paramsForStream_context_create["ssl"]["capture_peer_cert"]=true;
13068
 
13069
			#capture_peer_cert_chain
13070
			$paramsForStream_context_create["ssl"]["capture_peer_cert_chain"]=true;
13071
 
13072
			#security_level
13073
			#$paramsForStream_context_create["ssl"]["security_level"]=5;
13074
 
13075
			#如果要 debug
13076
			if($conf["debug"]==="true"){
13077
 
13078
				#debug
13079
				var_dump(__LINE__,$paramsForStream_context_create);
13080
 
13081
				}#if end
13082
 
13083
			#建立ssl設定
13084
			$stream_context_create=stream_context_create($paramsForStream_context_create);
13085
 
13086
			#如果要 debug
13087
			if($conf["debug"]==="true"){
13088
 
13089
				#debug
13090
				var_dump(__LINE__,$stream_context_create);
13091
 
13092
				}#if end
13093
 
13094
			#連線到 $conf["targetServr"].":".$conf["targetPort"] ,若有 error 可從 $error_code,$error_message 取得資訊, timeout 為 30 秒, connection flags 為 STREAM_CLIENT_CONNECT, 連線的屬性記載在 $stream_context_create.
13095
			$stream_socket_client=stream_socket_client("ssl://".$conf["targetServr"].":".$conf["targetPort"],$error_code,$error_message,0,STREAM_CLIENT_CONNECT,$stream_context_create);
13096
 
13097
			#如果連線到 peer 失敗
13098
			if($stream_socket_client===false){
13099
 
13100
				#設置執行失敗
13101
				$result["status"]="false";
13102
 
13103
				#設置執行錯誤訊息
13104
				$result["error"][]="stream_socket_client() failed.".PHP_EOL."Reason: ".$error_message."(".$error_code.")".PHP_EOL;
13105
 
13106
				#回傳結果
13107
				return $result;
13108
 
13109
				}#if end
13110
 
13111
			#取得連線的資訊
13112
			$result["info"]=stream_get_meta_data($stream_socket_client);
13113
 
13114
			#write header - start
13115
 
13116
			#initial header
13117
			$header="";
13118
 
13119
			#method、path、protocol
13120
			$header=$header."HEAD ".$path." HTTP/1.1"."\r\n";
13121
 
13122
			#Host
13123
			$header=$header."Host: ".$conf["targetServr"]."\r\n";
13124
 
13125
			#Upgrade
13126
			$header=$header."Upgrade: websocket"."\r\n";
13127
 
13128
			#Connection
13129
			$header=$header."Connection: Upgrade"."\r\n";
13130
 
13131
			#Sec-WebSocket-Version
13132
			$header=$header."Sec-WebSocket-Version: 13"."\r\n";
13133
 
13134
			#Sec-WebSocket-Key
13135
			$header=$header."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
13136
 
13137
			#send header					
13138
			fwrite($stream_socket_client,$header."\r\n");
13139
 
13140
			#write header - close
13141
 
13142
			#GET server reponse
13143
			while(!feof($stream_socket_client)){
13144
 
13145
				#讀取內容
13146
				$fgets=fgets($stream_socket_client, 1024);
13147
 
13148
				#如果要 debug
13149
				if($conf["debug"]==="true"){
13150
 
13151
					#debug
13152
					var_dump(__LINE__,$fgets);
13153
 
13154
					}#if end
13155
 
13156
				#如果 server 已經回應要用 websocket 協定了
13157
				if(trim($fgets)==="Upgrade: websocket"){
13158
 
13159
					#跳出while
13160
					break;
13161
 
13162
					}#if end
13163
 
13164
				}#if end
13165
 
13166
			#將建立的 sock 放到 $master 陣列
13167
			$master[] = $stream_socket_client;
13168
 
13169
			#函式說明:
13170
			#取得目前瀏覽的頁面的路徑或執行的php程式路徑.
13171
			#回傳結果:
13172
			#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
13173
			#$result["error"],錯誤訊息.
13174
			#$result["function"],檔前執行的函數名稱.
13175
			#$result["content"],目前瀏覽的頁面的路徑或執行的php程式路徑.
13176
			#$result["serverIp"],取得伺服器ip.
13177
			#$result["scheme"],取得與伺服器連線所使用的通訊協定.
13178
			#必填參數:
13179
			$conf["csInformation::getPathOfThisPhpFile"]["type"]="pathOnly";#想要取得的路徑類型,"full"代表完整路徑,"pathOnly"代表只要路徑,"lastLayer"代表上一層目錄的名稱
13180
			#必填參數:
13181
			#無.
13182
			#可省略參數:
13183
			#無.
13184
			#參考資料:
13185
			#http://blog.longwin.com.tw/2009/01/php-get-directory-file-path-dirname-2008/
13186
			#備註:
13187
			#無.
13188
			$getPathOfThisPhpFile=csInformation::getPathOfThisPhpFile($conf["csInformation::getPathOfThisPhpFile"]);
13189
			unset($conf["csInformation::getPathOfThisPhpFile"]);
13190
 
13191
			#如果執行失敗
13192
			if($getPathOfThisPhpFile["status"]=="false"){
13193
 
13194
				#設置錯誤識別
13195
				$result["status"]="false";
13196
 
13197
				#設置錯誤訊息
13198
				$result["error"]=$getPathOfThisPhpFile;
13199
 
13200
				#回傳結果
13201
				return $result;
13202
 
13203
				}#if end
13204
 
13205
			#函式說明:
13206
			#使用 linux 的 uuid 指令來產生 uuid 字串
13207
			#回傳結果:
13208
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13209
			#$result["error"],錯誤訊息.
13210
			#$result["function"],當前執行的函式名稱.
13211
			#$result["content"],uuid.
13212
			#必填參數:
13213
			#無.
13214
			#可省略參數:
13215
			#無.
13216
			#參考資料:
13217
			#無.
13218
			#備註:
13219
			#無.
13220
			$uuid=cmd::uuid();
13221
 
13222
			#如果執行失敗
13223
			if($uuid["status"]=="false"){
13224
 
13225
				#設置錯誤識別
13226
				$result["status"]="false";
13227
 
13228
				#設置錯誤訊息
13229
				$result["error"]=$uuid;
13230
 
13231
				#回傳結果
13232
				return $result;
13233
 
13234
				}#if end
13235
 
13236
			#設置存放socket的path
13237
			$socketPath=$getPathOfThisPhpFile["content"]."var/webSock::clientDaemon";
13238
 
13239
			#讓存放unix domain socket的路徑存在
13240
			#函式說明:
13241
			#確保路徑存在.
13242
			#回傳結果:
13243
			#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
13244
			#$result["error"],錯誤訊息陣列.
13245
			#$resutl["function"],當前執行的涵式名稱.
13246
			#$result["path"],建立好的路徑字串.
13247
			#$result["fileName"],檔案名稱,若 $conf["haveFileName"] 為 "true" 則會回傳.
13248
			#$result["argu"],使用的參數.
13249
			#必填參數:
13250
			#$conf["path"],要檢查的路徑
13251
			$conf["fileAccess::validatePath"]["path"]=$socketPath;
13252
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
13253
			$conf["fileAccess::validatePath"]["fileArgu"]=__FILE__;
13254
			#可省略參數:
13255
			#$conf["haveFileName"],字串,"true"代表有$conf["path"]檔案名稱,"false"代表$conf["path"]為純路徑,預設為"false".
13256
			$conf["fileAccess::validatePath"]["haveFileName"]="false";
13257
			#$conf["dirPermission"],字串,新建資料夾的權限設定,預設爲0770,亦即擁有者,同群組者可以讀,寫,存取,其他人無法使用.
13258
			#$conf["dirPermission"]="";
13259
			#$conf["web"],是否為檔案系統,"true"為網頁路徑,"false"為網頁系統,預設為"false".
13260
			$conf["fileAccess::validatePath"]["web"]="false";
13261
			#參考資料:
13262
			#無.
13263
			#備註:
13264
			#無.
13265
			$validatePath=fileAccess::validatePath($conf["fileAccess::validatePath"]);
13266
			unset($conf["fileAccess::validatePath"]);
13267
 
13268
			#如果執行失敗
13269
			if($validatePath["status"]==="false"){
13270
 
13271
				#設置錯誤識別
13272
				$result["status"]="false";
13273
 
13274
				#設置錯誤訊息
13275
				$result["error"]=$validatePath;
13276
 
13277
				#回傳結果
13278
				return $result;
13279
 
13280
				}#if end
13281
 
13282
			#變更 working dir
13283
			$chdir=chdir($socketPath);
13284
 
13285
			#設置sock檔案名稱
13286
			$socketName=$uuid["content"].".sock";
13287
 
13288
			#設置sock檔案位置與名稱
13289
			$socketAddr=$socketPath."/".$socketName;
13290
 
13291
			#如果要 debug
13292
			if($conf["debug"]==="true"){
13293
 
13294
				#debug
13295
				var_dump(__LINE__,$socketAddr);
13296
 
13297
				}#if end
13298
 
13299
			#建立 unix domain socket
13300
			$usock=stream_socket_server("unix://".$socketName, $errno, $errstr);
13301
 
13302
			#如果建立 unix domain socket 失敗
13303
			if(!$usock){
13304
 
13305
				#設置執行失敗
13306
				$result["status"]="false";
13307
 
13308
				#設置錯誤訊息
13309
				$result["error"][]=$errstr." (".$errno.")";
13310
 
13311
				#設置錯誤訊息
13312
				$result["error"][]="建立 unix domain socket(".$socketAddr.") 失敗";
13313
 
13314
				#回傳結果
13315
				return $result;
13316
 
13317
				}#if end
13318
 
13319
			#印出socket addr
13320
			echo "unixDomainSocket:".$socketAddr;
13321
 
13322
			#將建立的 unix domain socket 放到 $master 陣列
13323
			$master[] = $usock;
13324
 
13325
			#永久監聽, 不 timeout
13326
			while(true){
13327
 
13328
				#設置給 stream_select 監控的 sock 變數
13329
				$read = $write = $except = $master;
13330
 
13331
				#等待1秒,看有沒有連線進來讀寫資料
13332
				$mod_fd = stream_select($read, $write, $except, 1);
13333
 
13334
				#如果沒有偵測到讀寫動作失敗
13335
				if($mod_fd===FALSE){
13336
 
13337
					#關閉 web socket 連線
13338
					@fclose($stream_socket_client);
13339
 
13340
					#關閉unix domain socket
13341
					@fclose($usock);
13342
 
13343
					#移除unix domain socket
13344
					@unlink($socketAddr);
13345
 
13346
					#設置執行失敗
13347
					$result["status"]="false";
13348
 
13349
					#設置錯誤訊息
13350
					$result["error"][]="監聽資源異動失敗";
13351
 
13352
					#回傳結果
13353
					return $result;
13354
 
13355
					}#if end
13356
 
13357
				#如果沒有訊息,代表閒置時可以做的事情
13358
				else if($mod_fd===0){
13359
 
13360
					#代表沒收到訊息
13361
					echo ".";
13362
 
13363
					}#if end
13364
 
13365
				#反之有收到來自 web socket server 或 unix socket 的訊息
13366
				else{
13367
 
13368
					#針對每個 sock 陣列
13369
					foreach($read as $readStream){
13370
 
13371
						#如果是來自 web socket server 的訊息
13372
						if($readStream===$stream_socket_client){
13373
 
13374
							#當等待別人連線時,若有人連線進來.
13375
							#$webConn = stream_socket_accept($stream_socket_client);
13376
 
13377
							#如果要 debug
13378
							if($conf["debug"]==="true"){
13379
 
13380
								#debug
13381
								var_dump(__LINE__,"有收到來自 web socket server 的訊息");
13382
 
13383
								}#if end
13384
 
13385
							#讀取內容
13386
							$fread=fread($stream_socket_client,1024);
13387
 
13388
							#如果要 debug
13389
							if($conf["debug"]==="true"){
13390
 
13391
								#debug
13392
								var_dump(__LINE__,strlen($fread),$fread);
13393
 
13394
								}#if end
13395
 
13396
							#函式說明:
13397
							#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
13398
							#回傳結果:
13399
							#$result["function"],當前函式的名稱.
13400
							#$result["argu"],使用的參數.
13401
							#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
13402
							#$result["content"],unmask後的內容.
13403
							#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
13404
							#$result["error"],錯誤訊息陣列.
13405
							#必填參數:
13406
							#$conf["payload"],字串,要解密的訊息.
13407
							$conf["webSock::unmask"]["payload"]=$fread; 
13408
							#可省略參數:
13409
							#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
13410
							$conf["webSock::unmask"]["allowUnmask"]="true";
13411
							#$conf["webSock::unmask"]["debug"]="true";
13412
							#參考資料
13413
							#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
13414
							#https://tools.ietf.org/html/rfc6455
13415
							#https://tools.ietf.org/html/rfc5234
13416
							#備註:
13417
							#無.
13418
							$unmask=webSock::unmask($conf["webSock::unmask"]);
13419
							unset($conf["webSock::unmask"]);
13420
 
13421
							#debug
13422
							#var_dump(__LINE__,$unmask);
13423
 
13424
							#如果出錯
13425
							if($unmask["status"]==="false"){
13426
 
13427
								#關閉 web socket 連線
13428
								@fclose($stream_socket_client);
13429
 
13430
								#關閉unix domain socket
13431
								@fclose($usock);
13432
 
13433
								#移除unix domain socket
13434
								@unlink($socketAddr);
13435
 
13436
								#設置執行失敗
13437
								$result["status"]="false";
13438
 
13439
								#設置執行錯誤訊息
13440
								$result["error"]=$unmask;
13441
 
13442
								#回傳結果
13443
								return $result;
13444
 
13445
								}#if end
13446
 
13447
							#如果收到文字訊息
13448
							if($unmask["type"]==="text"){
13449
 
13450
								#如果有解析出內容
13451
								if(isset($unmask["content"])){
13452
 
13453
									#提示收到的訊息
13454
									echo $unmask["content"];
13455
 
13456
									#傳遞給unix domain client
13457
									$fwrite=fwrite($unixConn,$unmask["content"]);
13458
 
13459
									#如果要 debug
13460
									if($conf["debug"]==="true"){
13461
 
13462
										#debug
13463
										var_dump(__LINE__,$fwrite);
13464
 
13465
										}#if end
13466
 
13467
									#關閉連線
13468
									fclose($unixConn);
13469
 
13470
									}#if end
13471
 
13472
								}#if end
13473
 
13474
							#如果收到ping
13475
							if($unmask["type"]==="ping"){
13476
 
13477
								#函式說明:
13478
								#加密 handshake 後要傳送的 webSocket 訊息 
13479
								#回傳結果:
13480
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13481
								#$result["error"],執行不正常結束的錯訊息陣列.
13482
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
13483
								#$result["argu"],陣列,使用的參數.
13484
								#必填參數:
13485
								#$conf["text"],字串,要加密的訊息.
13486
								$conf["webSock::encode"]["text"]=""; 
13487
								#可省略參數:
13488
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13489
								#$conf["ping"]="true";
13490
								#$conf["pong"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13491
								$conf["webSock::encode"]["pong"]="true";
13492
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
13493
								#$conf["frames"]=array();
13494
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
13495
								$conf["webSock::encode"]["mask"]="true";
13496
								#參考資料:
13497
								#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
13498
								#備註:
13499
								#無.
13500
								$encode=webSock::encode($conf["webSock::encode"]);
13501
								unset($conf["webSock::encode"]);
13502
 
13503
								#如果要 debug
13504
								if($conf["debug"]==="true"){
13505
 
13506
									#debug
13507
									var_dump(__LINE__,$encode);
13508
 
13509
									}#if end
13510
 
13511
								#如果出錯
13512
								if($encode["status"]==="false"){
13513
 
13514
									#設置執行失敗
13515
									$result["status"]="false";
13516
 
13517
									#設置執行錯誤訊息
13518
									$result["error"]=$encode;
13519
 
13520
									#回傳結果
13521
									return $result;
13522
 
13523
									}#if end
13524
 
13525
								#如果要 debug
13526
								if($conf["debug"]==="true"){
13527
 
13528
									#debug
13529
									var_dump(__LINE__,$encode);
13530
 
13531
									}#if end
13532
 
13533
								#針對每個 frame
13534
								foreach($encode["content"] as $fNo => $frame){
13535
 
13536
									#傳遞給 web socket server
13537
									$fwrite=fwrite($stream_socket_client,$frame);
13538
 
13539
									#如果傳遞失敗
13540
									if($fwrite===false){
13541
 
13542
										#關閉 web socket 連線
13543
										@fclose($stream_socket_client);
13544
 
13545
										#關閉unix domain socket
13546
										@fclose($usock);
13547
 
13548
										#移除unix domain socket
13549
										@unlink($socketAddr);
13550
 
13551
										#設置執行失敗
13552
										$result["status"]="false";
13553
 
13554
										#設置執行錯誤訊息
13555
										$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
13556
 
13557
										#回傳結果
13558
										return $result;
13559
 
13560
										}#if end
13561
 
13562
									}#foreach end
13563
 
13564
								}#if end
13565
 
13566
							}#if end
13567
 
13568
						#反之若為來自 unix domain socket 的訊息
13569
						else if($readStream===$usock){
13570
 
13571
							#當等待別人連線時,若有人連線進來.
13572
							$unixConn = stream_socket_accept($usock);
13573
 
13574
							#如果要 debug
13575
							if($conf["debug"]==="true"){
13576
 
13577
								#debug
13578
								var_dump(__LINE__,"有收到來自 unix domain socket 的訊息");
13579
 
13580
								}#if end
13581
 
13582
							#讀取內容
13583
							$fgets=trim(fgets($unixConn,1024));
13584
 
13585
							#如果要 debug
13586
							if($conf["debug"]==="true"){
13587
 
13588
								#debug
13589
								var_dump(__LINE__,strlen($fgets),$fgets);
13590
 
13591
								}#if end
13592
 
13593
							#轉換成 web socket 的格式
13594
							#函式說明:
13595
							#加密 handshake 後要傳送的 webSocket 訊息 
13596
							#回傳結果:
13597
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13598
							#$result["error"],執行不正常結束的錯訊息陣列.
13599
							#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
13600
							#$result["argu"],陣列,使用的參數.
13601
							#必填參數:
13602
							#$conf["text"],字串,要加密的訊息.
13603
							$conf["webSock::encode"]["text"]=$fgets; 
13604
							#可省略參數:
13605
							#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13606
							#$conf["ping"]="true";
13607
							#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
13608
							#$conf["frames"]=array();
13609
							#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
13610
							$conf["webSock::encode"]["mask"]="true";
13611
							#參考資料:
13612
							#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
13613
							#備註:
13614
							#無.
13615
							$encode=webSock::encode($conf["webSock::encode"]);
13616
							unset($conf["webSock::encode"]);
13617
 
13618
							#如果要 debug
13619
							if($conf["debug"]==="true"){
13620
 
13621
								#debug
13622
								var_dump(__LINE__,$encode);
13623
 
13624
								}#if end
13625
 
13626
							#如果出錯
13627
							if($encode["status"]==="false"){
13628
 
13629
								#設置執行失敗
13630
								$result["status"]="false";
13631
 
13632
								#設置執行錯誤訊息
13633
								$result["error"]=$encode;
13634
 
13635
								#回傳結果
13636
								return $result;
13637
 
13638
								}#if end
13639
 
13640
							#針對每個frame
13641
							foreach($encode["content"] as $fNo => $frame){
13642
 
13643
								#傳遞給 web socket server
13644
								$fwrite=fwrite($stream_socket_client,$frame);
13645
 
13646
								#如果要 debug
13647
								if($conf["debug"]==="true"){
13648
 
13649
									#debug
13650
									var_dump(__LINE__,$fwrite,"傳遞".strlen($frame)."bytes給webSocketServer",$frame);
13651
 
13652
									}#if end
13653
 
13654
								#如果傳遞失敗
13655
								if($fwrite===false){
13656
 
13657
									#關閉 web socket 連線
13658
									@fclose($stream_socket_client);
13659
 
13660
									#關閉unix domain socket
13661
									@fclose($usock);
13662
 
13663
									#移除unix domain socket
13664
									@unlink($socketAddr);
13665
 
13666
									#設置執行失敗
13667
									$result["status"]="false";
13668
 
13669
									#設置執行錯誤訊息
13670
									$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
13671
 
13672
									#回傳結果
13673
									return $result;
13674
 
13675
									}#if end
13676
 
13677
								}#foreach end
13678
 
13679
							}#if end
13680
 
13681
						#例外狀況
13682
						else{
13683
 
13684
							#如果要 debug
13685
							if($conf["debug"]==="true"){
13686
 
13687
								#debug
13688
								var_dump(__LINE__,$readStream);
13689
 
13690
								}#if end
13691
 
13692
							#關閉 web socket 連線
13693
							@fclose($stream_socket_client);
13694
 
13695
							#關閉unix domain socket
13696
							@fclose($usock);
13697
 
13698
							#移除unix domain socket
13699
							@unlink($socketAddr);
13700
 
13701
							#顯示 socket 的狀態
13702
							echo "非預期的錯誤,偵測到不應存在資源有異動".PHP_EOL;
13703
 
13704
							#結束執行並回傳1,代表異常結束
13705
							exit(1);
13706
 
13707
							}#else end
13708
 
13709
						}#foreach end
13710
 
13711
					}#else
13712
 
13713
				#等待1秒
13714
				sleep(1);
13715
 
13716
				}#while end
13717
 
13718
			#設置執行正常
13719
			$result["status"]="true";
13720
 
13721
			#回傳結果
13722
			return $result;
13723
 
13724
			}#if end
13725
 
13726
		#反之不用
13727
		else{
13728
 
13729
			#如果要 debug
13730
			if($conf["debug"]==="true"){
13731
 
13732
				#提示用戶端的文字
13733
				echo "TCP/IP Connection".PHP_EOL;
13734
 
13735
				}#if end
13736
 
13737
			/* Get the port for the WWW service. */
13738
			#http://php.net/manual/en/function.getservbyname.php
13739
			#$service_port = getservbyname('www', 'tcp');
13740
 
13741
			/* Get the IP address for the target host. */
13742
			#http://php.net/manual/en/function.gethostbyname.php
13743
			$ServerAddress = gethostbyname($conf["targetServr"]);
13744
 
13745
			/* Create a TCP/IP socket. */
13746
			$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
13747
 
13748
			#如果建立 socket 失敗
13749
			if ($socket === false) {
13750
 
13751
				#設置執行失敗
13752
				$result["status"]="false";
13753
 
13754
				#設置執行錯誤訊息
13755
				$result["error"][]="socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
13756
 
13757
				#回傳結果
13758
				return $result;
13759
 
13760
				}#if end
13761
 
13762
			#反之
13763
			else {
13764
 
13765
				#如果要 debug
13766
				if($conf["debug"]==="true"){
13767
 
13768
					#印出建立成功訊息
13769
					echo "OK.".PHP_EOL;
13770
 
13771
					}#if end
13772
 
13773
				}#else end
13774
 
13775
			#如果要 debug
13776
			if($conf["debug"]==="true"){
13777
 
13778
				#提示要連線到哪個位址的哪個port
13779
				echo "Attempting to connect to ".$ServerAddress." on port ".$conf["targetPort"]."...";
13780
 
13781
				}#if end
13782
 
13783
			#連線到目標 socket
13784
			$socket_connect=socket_connect($socket, $ServerAddress, $conf["targetPort"]);
13785
 
13786
			#如果連線到 socket 失敗
13787
			if($socket_connect===false){
13788
 
13789
				#設置執行失敗
13790
				$result["status"]="false";
13791
 
13792
				#設置執行錯誤訊息
13793
				$result["error"][]="socket_connect() failed.".PHP_EOL."Reason: ($socket_connect) " . socket_strerror(socket_last_error($socket)) . PHP_EOL;
13794
 
13795
				#回傳結果
13796
				return $result;
13797
 
13798
				}#if end
13799
 
13800
			#反之
13801
			else {
13802
 
13803
				#如果要 debug
13804
				if($conf["debug"]==="true"){
13805
 
13806
					#印出連線成功訊息
13807
					echo "OK.".PHP_EOL;
13808
 
13809
					}#if end
13810
 
13811
				}#else end
13812
 
13813
			}#else end
13814
 
13815
		#初始化要傳送的HEAD資訊
13816
		$in="HEAD / HTTP/1.1"."\r\n";
13817
		$in=$in."Host: ".$ServerAddress.":".$conf["targetPort"]."\r\n";
13818
		$in=$in."Upgrade: websocket"."\r\n";
13819
		$in=$in."Connection: Upgrade"."\r\n";
13820
		$in=$in."Sec-WebSocket-Version: 13"."\r\n";
13821
		$in=$in."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
13822
		$in=$in."\r\n";
13823
 
13824
		#初始化回傳的內容
13825
		$out = '';
13826
 
13827
		#如果連線到 socket 失敗
13828
		if($socket_connect===false){
13829
 
13830
			#提示傳送HTTP HEAD中
13831
			echo "Sending HTTP HEAD request...";
13832
 
13833
			}#if end
13834
 
13835
		#將訊息傳送到socket去
13836
		socket_write($socket, $in, strlen($in));
13837
 
13838
		#如果連線到 socket 失敗
13839
		if($socket_connect===false){
13840
 
13841
			#提示傳送完畢
13842
			echo "OK.".PHP_EOL;
13843
 
13844
			#提示讀取回應中
13845
			echo "Reading response:".PHP_EOL;
13846
 
13847
			}#if end
13848
 
13849
		#無窮迴圈
13850
		while(true){
13851
 
13852
			#一次讀取2048bytes,判斷有無回應,並取得其內容.
13853
			$out = socket_read($socket, 2048);
13854
 
13855
			#如果尚未取得 Sec-WebSocket-Accept
13856
			if(!isset($result["Sec-WebSocket-Accept"])){
13857
 
13858
				#如果連線到 socket 失敗
13859
				if($socket_connect===false){
13860
 
13861
					#印出收到的內容
13862
					echo $out;
13863
 
13864
					}#if end
13865
 
13866
				#如果 $out 有資料
13867
				if($out){
13868
 
13869
					#如果接收到的是字串,且不為空
13870
					if(gettype($out)==="string" && !empty($out)){
13871
 
13872
						#如果有既有的前次回應內容
13873
						if(isset($result["content"])){
13874
 
13875
							#儲存回應的內容
13876
							$result["content"]=$result["content"].$out;
13877
 
13878
							}#if end
13879
 
13880
						#反之
13881
						else{
13882
 
13883
							#儲存回應的內容
13884
							$result["content"]=$out;
13885
 
13886
							}#else end
13887
 
13888
						#涵式說明:
13889
						#將固定格式的字串分開,並回傳分開的結果。
13890
						#回傳結果:
13891
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13892
						#$result["error"],錯誤訊息陣列
13893
						#$result["function"],當前執行的函數名稱.
13894
						#$result["argu"],使用的參數.
13895
						#$result["oriStr"],要分割的原始字串內容
13896
						#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
13897
						#$result["dataCounts"],爲總共分成幾段
13898
						#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
13899
						#必填的參數:
13900
						#$conf["stringIn"],字串,要處理的字串.
13901
						$conf["stringProcess::spiltString"]["stringIn"]=$out;
13902
						#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
13903
						$conf["stringProcess::spiltString"]["spiltSymbol"]="Sec-WebSocket-Accept: ";
13904
						#可省略參數:
13905
						#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
13906
						$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
13907
						$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
13908
						unset($conf["stringProcess::spiltString"]);
13909
 
13910
						#如果執行失敗
13911
						if($spiltString["status"]==="false"){
13912
 
13913
							#設置執行失敗
13914
							$result["status"]="false";
13915
 
13916
							#設置執行錯誤訊息
13917
							$result["error"]=$spiltString;
13918
 
13919
							#回傳結果
13920
							return $result;
13921
 
13922
							}#if end
13923
 
13924
						#取得Sec-WebSocket-Accept
13925
						$result["Sec-WebSocket-Accept"]=trim($spiltString["dataArray"][1]);
13926
 
13927
						#初始化要傳遞的內容			
13928
						$in="id?";
13929
 
13930
						#初始化傳遞的內容長度
13931
						$len=strlen($in);
13932
 
13933
						#設置儲存每個元素為8bit字串的陣列
13934
						$bit8=array();
13935
						$bit8[0]="10000001";
13936
						$bit8[1]="1".sprintf("%07s",base_convert($len,10,2));
13937
 
13938
						#mask key
13939
						$bit8[2]="00000000";
13940
						$bit8[3]="00000000";
13941
						$bit8[4]="00000000";
13942
						$bit8[5]="00000000";
13943
 
13944
						#mask key
13945
						$mask_key=$bit8[2].$bit8[3].$bit8[4].$bit8[5];
13946
 
13947
						#針對每個字,進行mask
13948
						for($i=0;$i<$len;$i++){
13949
 
13950
							$j=$i%4;
13951
 
13952
							$in[$i]=$in[$i] xor $mask_key[$j];
13953
 
13954
							}#for end
13955
 
13956
						#如果連線到 socket 失敗
13957
						if($socket_connect===false){
13958
 
13959
							#提示傳送資料
13960
							echo "Sending Data...".PHP_EOL;
13961
 
13962
							}#if end
13963
 
13964
						#data frame
13965
						$in=chr(base_convert($bit8[0],2,10)).chr(base_convert($bit8[1],2,10)).chr(base_convert($bit8[2],2,10)).chr(base_convert($bit8[3],2,10)).chr(base_convert($bit8[4],2,10)).chr(base_convert($bit8[5],2,10)).$in;
13966
 
13967
						#將訊息傳送到socket去
13968
						socket_write($socket, $in, strlen($in));
13969
 
13970
						}#if end
13971
 
13972
					}#if end	
13973
 
13974
				}#if end
13975
 
13976
			#反之取得了 Sec-WebSocket-Accept 就結束 HTTP/1.1
13977
			else{
13978
 
13979
				#如果連線到 socket 失敗
13980
				if($socket_connect===false){
13981
 
13982
					echo "解密前的內容:".PHP_EOL;
13983
 
13984
					}#if end
13985
 
13986
				#函式說明:
13987
				#將字串中的每個字變成bytes陣列
13988
				#回傳結果:
13989
				#$result...
13990
				#必填參數:
13991
				#$conf["input"],字串,要轉換成bytes陣列的字串
13992
				$conf["stringProcess::str2bytesArray"]["input"]=$out;
13993
				#可省略參數:
13994
				#無
13995
				#建構中...
13996
				$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
13997
				unset($conf["stringProcess::str2bytesArray"]);
13998
 
13999
				#針對每個bytes				
14000
				foreach($str2bytesArray["content"] as $byte){
14001
 
14002
					#函式說明:
14003
					#將bytes數字轉換為bit字串(0跟1來表述)
14004
					#回傳結果:
14005
					#$result...
14006
					#必填參數:
14007
					#$conf["input"],字串,要轉換成byte的字串
14008
					$conf["stringProcess::str2bytesArray"]["bytes"]=$byte;
14009
					#可省略參數:
14010
					#無
14011
					#建構中...
14012
					$bytes2bitString=stringProcess::bytes2bitString($conf["stringProcess::str2bytesArray"]);
14013
					unset($conf["stringProcess::str2bytesArray"]);
14014
 
14015
					#如果連線到 socket 失敗
14016
					if($socket_connect===false){
14017
 
14018
						#debug
14019
						var_dump($bytes2bitString["content"]);
14020
 
14021
						}#if end
14022
 
14023
					}#foreach end
14024
 
14025
				#如果連線到 socket 失敗
14026
				if($socket_connect===false){
14027
 
14028
					echo "解密後接收的內容:".PHP_EOL;
14029
 
14030
					}#if end
14031
 
14032
				#函式說明:
14033
				#解密 handshake 後要接收的訊息
14034
				#回傳結果:
14035
				#$result["function"],當前函式的名稱.
14036
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14037
				#$result["content"],unmask後的內容.
14038
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14039
				#$result["error"],錯誤訊息陣列.
14040
				#必填參數:
14041
				#$conf["payload"],字串,要解密的訊息.
14042
				$conf["webSock::unmask"]["payload"]=$out; 
14043
				#可省略參數:
14044
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14045
				$conf["webSock::unmask"]["allowUnmask"]="true";
14046
				#參考資料
14047
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14048
				#https://tools.ietf.org/html/rfc6455
14049
				#https://tools.ietf.org/html/rfc5234
14050
				#備註:
14051
				#無.
14052
				$unmask=webSock::unmask($conf["webSock::unmask"]);
14053
				unset($conf["webSock::unmask"]);
14054
 
14055
				#如果執行失敗
14056
				if($unmask["status"]==="false"){
14057
 
14058
					#設置執行失敗
14059
					$result["status"]="false";
14060
 
14061
					#設置執行錯誤訊息
14062
					$result["error"]=$unmask;
14063
 
14064
					#回傳結果
14065
					return $result;
14066
 
14067
					}#if end
14068
 
14069
				#記錄接收到的內容
14070
				$received=$unmask["content"];
14071
 
14072
				#如果連線到 socket 失敗
14073
				if($socket_connect===false){	
14074
 
14075
					#debug
14076
					var_dump($received);
14077
 
14078
					}#if end
14079
 
14080
				}#else end
14081
 
14082
			#休息1秒
14083
			sleep(1);
14084
 
14085
			}#while end
14086
 
14087
		#如果連線到 socket 失敗
14088
		if($socket_connect===false){
14089
 
14090
			#提示關閉與 socket 的連線
14091
			echo "Closing socket...";
14092
 
14093
			}#if end
14094
 
14095
		#關閉與 socket 的連線
14096
		socket_close($socket);
14097
 
14098
		#如果連線到 socket 失敗
14099
		if($socket_connect===false){
14100
 
14101
			#提示關閉連線成功
14102
			echo "OK.".PHP_EOL;
14103
 
14104
			}#if end
14105
 
14106
		#設置執行正常
14107
		$result["status"]="true";
14108
 
14109
		#回傳結果
14110
		return $result;
14111
 
14112
		}#function clientDaemon end
14113
 
14114
	/*	
14115
	#函式說明:
14116
	#webSocket的javaScript用戶端
14117
	#回傳結果:
14118
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
14119
	#$result["error"],錯誤訊息陣列.
14120
	#$resutl["function"],當前執行的涵式名稱.
14121
	#$result["argu"],所使用的參數.
14122
	#$result["content"],語法.
14123
	#必填參數:
14124
	#$conf["url"],字串要拜訪的web socket,請省略"ws://".
14125
	$conf["url"]="";
14126
	#可省略參數:
14127
	#$conf["entry"],字串,是否要用加密的wss,預設為"false",代表用ws,若為"true"則為wss.
14128
	#$conf["entry"]="false";
14129
	#$conf["connVar"],字串,用來儲存webSocket連線的物件名稱,預設為"conn".
14130
	#$conf["connVar"]="conn";
14131
	#參考資料:
14132
	#無.
14133
	#備註:
14134
	#無.
14135
	*/
14136
	public static function client(&$conf){
14137
 
14138
		#初始化要回傳的結果
14139
		$result=array();
14140
 
14141
		#取得當前執行的函數名稱
14142
		$result["function"]=__FUNCTION__;
14143
 
14144
		#如果沒有參數
14145
		if(func_num_args()==0){
14146
 
14147
			#設置執行失敗
14148
			$result["status"]="false";
14149
 
14150
			#設置執行錯誤訊息
14151
			$result["error"]="函數".$result["function"]."需要參數";
14152
 
14153
			#回傳結果
14154
			return $result;
14155
 
14156
			}#if end
14157
 
14158
		#取得參數
14159
		$result["argu"]=$conf;
14160
 
14161
		#如果 $conf 不為陣列
14162
		if(gettype($conf)!=="array"){
14163
 
14164
			#設置執行失敗
14165
			$result["status"]="false";
14166
 
14167
			#設置執行錯誤訊息
14168
			$result["error"][]="\$conf變數須為陣列形態";
14169
 
14170
			#如果傳入的參數為 null
14171
			if($conf===null){
14172
 
14173
				#設置執行錯誤訊息
14174
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
14175
 
14176
				}#if end
14177
 
14178
			#回傳結果
14179
			return $result;
14180
 
14181
			}#if end
14182
 
14183
		#檢查參數
14184
		#函式說明:
14185
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
14186
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14187
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
14188
		#$result["function"],當前執行的函式名稱.
14189
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
14190
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
14191
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
14192
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
14193
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
14194
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
14195
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
14196
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
14197
		#必填寫的參數:
14198
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
14199
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
14200
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
14201
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("url");
14202
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
14203
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
14204
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
14205
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
14206
		#可以省略的參數:
14207
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
14208
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
14209
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
14210
		#$conf["canNotBeEmpty"]=array();
14211
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
14212
		#$conf["canBeEmpty"]=array();
14213
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
14214
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
14215
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
14216
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("entry","connVar");
14217
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
14218
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
14219
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
14220
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","conn");
14221
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
14222
		#$conf["arrayCountEqualCheck"][]=array();
14223
		#參考資料來源:
14224
		#array_keys=>http://php.net/manual/en/function.array-keys.php
14225
		#建議:
14226
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
14227
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
14228
		unset($conf["variableCheck::checkArguments"]);
14229
 
14230
		#如果檢查參數失敗
14231
		if($checkArguments["status"]==="false"){
14232
 
14233
			#設置執行失敗
14234
			$result["status"]="false";
14235
 
14236
			#設置執行錯誤訊息
14237
			$result["error"]=$checkArguments;
14238
 
14239
			#回傳結果
14240
			return $result;
14241
 
14242
			}#if end
14243
 
14244
		#如果參數檢查不通過
14245
		if($checkArguments["passed"]==="false"){
14246
 
14247
			#設置執行失敗
14248
			$result["status"]="false";
14249
 
14250
			#設置執行錯誤訊息
14251
			$result["error"]=$checkArguments;
14252
 
14253
			#回傳結果
14254
			return $result;
14255
 
14256
			}#if end		
14257
 
14258
		#初始化 web socket 的協定
14259
		$webSockUrl="ws://";
14260
 
14261
		#如果要加密
14262
		if($conf["entry"]==="true"){
14263
 
14264
			$webSockUrl="wss://";
14265
 
14266
			}#if end
14267
 
14268
		#設置用戶端連線到webSocket的範例
14269
		$script="<script>
14270
 
14271
			//建立 web socket 連線到 ".$webSockUrl.$conf["url"]."
14272
			var ".$conf["connVar"]." = new WebSocket('".$webSockUrl.$conf["url"]."');
14273
 
14274
			//當連線成功後
14275
			".$conf["connVar"].".onopen = function(e)
14276
			{
14277
				//印出連線成功訊息到console
14278
				console.log(\"Connection established!\");
14279
			};
14280
 
14281
			//當有收到訊息時
14282
			".$conf["connVar"].".onmessage = function(e) {
14283
 
14284
				//將訊息顯現在console
14285
				console.log(e.data);
14286
			};
14287
			</script>";
14288
 
14289
		#設置建立webSocket連線的按鈕
14290
		#函式說明:
14291
		#放置按鈕
14292
		#回傳結果:
14293
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14294
		#$result["function"],當前執行的函數.
14295
		#$result["error"],錯誤訊息陣列.
14296
		#$result["content"],按鈕語法. 
14297
		#必要的參數:
14298
		$conf["form::button"]["buttonDisplayValue"]="Send Hello!";#爲按鈕上顯示的文字。
14299
		#可省略的參數:
14300
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
14301
			#其屬性爲   "width","height","font-size","text-align"
14302
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
14303
		$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
14304
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
14305
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
14306
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
14307
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
14308
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
14309
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
14310
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
14311
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
14312
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
14313
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
14314
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
14315
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
14316
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
14317
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
14318
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
14319
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
14320
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
14321
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
14322
		#$conf["formId"],字串,表單的id.
14323
		#$conf["formId"]="";
14324
		#$conf["buttonId"],字串,按鈕的id.
14325
		#$conf["buttonId"]="";
14326
		#參考資料來源:
14327
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
14328
		$button=form::button($conf["form::button"]);
14329
		unset($conf["form::button"]);
14330
 
14331
		#如果建立按鈕失敗
14332
		if($button["status"]==="false"){
14333
 
14334
			#設置執行失敗
14335
			$result["status"]="false";
14336
 
14337
			#設置執行錯誤訊息
14338
			$result["error"]=$button;
14339
 
14340
			#回傳結果
14341
			return $result;
14342
 
14343
			}#if end	
14344
 
14345
		#設置用戶端的html與js語法
14346
		$result["content"]=$button["content"].$script;
14347
 
14348
		#設置執行正常
14349
		$result["status"]="true";
14350
 
14351
		#回傳結果
14352
		return $result;
14353
 
14354
		}#function client end
14355
 
14356
	/*
14357
	#函式說明:
14358
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
14359
	#回傳結果:
14360
	#$result["function"],當前函式的名稱.
14361
	#$result["argu"],使用的參數.
14362
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14363
	#$result["content"],unmask後的內容.
14364
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14365
	#$result["error"],錯誤訊息陣列.
14366
	#必填參數:
14367
	#$conf["payload"],字串,要解密的訊息.
14368
	$conf["payload"]=""; 
14369
	#可省略參數:
14370
	$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14371
	$conf["allowUnmask"]="false";
14372
	#參考資料
14373
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14374
	#https://tools.ietf.org/html/rfc6455
14375
	#https://tools.ietf.org/html/rfc5234
14376
	#備註:
14377
	#無.
14378
	*/
14379
	public static function mask(&$conf){
14380
 
14381
		#改呼叫 webSock::umask
14382
		return webSock::unmask($conf);
14383
 
14384
		}#function mask end
14385
 
14386
	/*
14387
	#函式說明:
14388
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
14389
	#回傳結果:
14390
	#$result["function"],當前函式的名稱.
14391
	#$result["argu"],使用的參數.
14392
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14393
	#$result["content"],unmask後的內容.
14394
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14395
	#$result["error"],錯誤訊息陣列.
14396
	#必填參數:
14397
	#$conf["payload"],字串,要解密的訊息.
14398
	$conf["payload"]=""; 
14399
	#可省略參數:
14400
	#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14401
	#$conf["allowUnmask"]="false";
14402
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
14403
	#$conf["debug"]="false";
14404
	#參考資料
14405
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14406
	#https://tools.ietf.org/html/rfc6455
14407
	#https://tools.ietf.org/html/rfc5234
14408
	#備註:
14409
	#無.
14410
	*/
14411
	public static function unmask(&$conf) {
14412
 
14413
		#初始化要回傳的結果
14414
		$result=array();
14415
 
14416
		#取得當前執行的函數名稱
14417
		$result["function"]=__FUNCTION__;
14418
 
14419
		#取得參數內容
14420
		$result["argu"]=$conf;
14421
 
14422
		#檢查參數
14423
		#函式說明:
14424
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
14425
		#回傳結果:
14426
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14427
		#$result["error"],執行不正常結束的錯訊息陣列.
14428
		#$result["simpleError"],簡單表示的錯誤訊息.
14429
		#$result["function"],當前執行的函式名稱.
14430
		#$result["argu"],設置給予的參數.
14431
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
14432
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
14433
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
14434
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
14435
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
14436
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
14437
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
14438
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
14439
		#必填參數:
14440
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
14441
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
14442
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
14443
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
14444
		#可省略參數:
14445
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
14446
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("payload");
14447
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
14448
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
14449
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
14450
		#$conf["canBeEmptyString"]="false";
14451
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
14452
		#$conf["canNotBeEmpty"]=array();
14453
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
14454
		#$conf["canBeEmpty"]=array();
14455
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
14456
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("allowUnmask","debug");
14457
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
14458
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("allowUnmask","debug");
14459
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
14460
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
14461
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
14462
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false");
14463
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
14464
		#$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="";
14465
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
14466
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
14467
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
14468
		#$conf["disallowAllSkipableVarNotExist"]="";
14469
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
14470
		#$conf["arrayCountEqualCheck"][]=array();
14471
		#參考資料:
14472
		#array_keys=>http://php.net/manual/en/function.array-keys.php
14473
		#備註:
14474
		#無.
14475
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
14476
		unset($conf["variableCheck::checkArguments"]);
14477
 
14478
		#如果檢查參數失敗
14479
		if($checkArguments["status"]==="false"){
14480
 
14481
			#設置執行不正常
14482
			$result["status"]="false";
14483
 
14484
			#設置錯誤訊息
14485
			$result["error"]=$checkArguments;
14486
 
14487
			#回傳結果
14488
			return $result;
14489
 
14490
			}#if end
14491
 
14492
		#如果檢查參數不通過
14493
		if($checkArguments["passed"]==="false"){
14494
 
14495
			#設置執行不正常
14496
			$result["status"]="false";
14497
 
14498
			#設置錯誤訊息
14499
			$result["error"]=$checkArguments;
14500
 
14501
			#回傳結果
14502
			return $result;
14503
 
14504
			}#if end
14505
 
14506
		#取得變數
14507
		$payload=$conf["payload"];
14508
 
14509
		#如果要debug
14510
		if($conf["debug"]==="true"){
14511
 
14512
			#debug payload length
14513
			echo __LINE__." strlen(\$payload)=".strlen($payload).PHP_EOL;
14514
 
14515
			}#if end
14516
 
14517
		#web socket frame 最少為 2bytes
14518
		if(strlen($payload)<2){
14519
 
14520
			#函式說明:
14521
			#將字串中的每個字變成hex的字串陣列
14522
			#回傳結果:
14523
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14524
			#$result["function"],當前執行的函式內容.
14525
			#$result["error"],錯誤訊息陣列.
14526
			#$result["content"],hex的字串陣列.
14527
			#必填參數:
14528
			#$conf["input"],字串,要轉換成bytes陣列的字串.
14529
			$conf["stringProcess::str2bytesArray"]["input"]=$payload;
14530
			#可省略參數:
14531
			#無.
14532
			#參考資料:
14533
			#無.
14534
			#備註:
14535
			#無.
14536
			$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
14537
			unset($conf["stringProcess::str2bytesArray"]);
14538
 
14539
			#如果檢查參數失敗
14540
			if($str2bytesArray["status"]==="false"){
14541
 
14542
				#設置執行不正常
14543
				$result["status"]="false";
14544
 
14545
				#設置錯誤訊息
14546
				$result["error"]=$str2bytesArray;
14547
 
14548
				#回傳結果
14549
				return $result;
14550
 
14551
				}#if end
14552
 
14553
			#設置警告訊息
14554
			$result["warning"][]="web socket frame 最少為 2 bytes,目前收到得為 ".strlen($payload)." bytes";
14555
 
14556
			#設置警告訊息
14557
			$result["warning"][]="接收到的 web socket frame 內容";
14558
 
14559
			#設置警告訊息
14560
			$result["warning"][]="(ASCII):".$payload;
14561
 
14562
			#開始截取輸出
14563
			ob_start();
14564
 
14565
			#針對每個bytes
14566
			for($i=0;$i<count($str2bytesArray["content"]);$i++){
14567
 
14568
				#印出其內容
14569
				echo "[".$str2bytesArray["content"][$i]."]";
14570
 
14571
				#若不是最後一個byte
14572
				if($i===count($str2bytesArray["content"])-1){
14573
 
14574
					#空一格
14575
					echo " ";
14576
 
14577
					}#if end
14578
 
14579
				}#if end
14580
 
14581
			#取得用HEX表示的內容
14582
			$hexStr=ob_get_contents();
14583
 
14584
			#結束截取輸出
14585
			ob_end_clean();
14586
 
14587
			#設置警告訊息
14588
			$result["warning"][]="(HEX):".$hexStr;
14589
 
14590
			#設置為非 web socket frame
14591
			$result["type"]="invalid";
14592
 
14593
			#設置執行正常
14594
			$result["status"]="true";
14595
 
14596
			#回傳結果
14597
			return $result;
14598
 
14599
			}#if end
14600
 
14601
		#如果要debug
14602
		if($conf["debug"]==="true"){
14603
 
14604
			#debug data length
14605
			echo __LINE__." \$length=".(ord($payload[1]) & 127).PHP_EOL;
14606
 
14607
			}#if end
14608
 
14609
		#取得字串長度
14610
		$psl=strlen($payload);
14611
 
14612
		#初始化儲存每個bytes
14613
		$bytes=array();
14614
 
14615
		#函式說明:
14616
		#將字串中的每個字變成bytes陣列
14617
		#回傳結果:
14618
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14619
		#$result["function"],當前執行的函式內容.
14620
		#$result["error"],錯誤訊息陣列.
14621
		#$result["content"],hex的字串陣列.
14622
		#必填參數:
14623
		#$conf["input"],字串,要轉換成bytes陣列的字串
14624
		$conf["stringProcess::str2bytesArray"]["input"]=$payload;
14625
		#可省略參數:
14626
		#無
14627
		$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
14628
		unset($conf["stringProcess::str2bytesArray"]);
14629
 
14630
		#如果執行失敗
14631
		if($str2bytesArray["status"]==="false"){
14632
 
14633
			#設置執行不正常
14634
			$result["status"]="false";
14635
 
14636
			#設置錯誤訊息
14637
			$result["error"]=$str2bytesArray;
14638
 
14639
			#回傳結果
14640
			return $result;
14641
 
14642
			}#if end
14643
 
14644
		#針對每個bytes
14645
		foreach($str2bytesArray["content"] as $bytesNum => $oneByte){
14646
 
14647
			#函式說明:
14648
			#將bytes數字轉換為bit陣列(0跟1來表述)
14649
			#回傳結果:
14650
			#$result...
14651
			#必填參數:
14652
			#$conf["input"],字串,要轉換成byte的字串
14653
			$conf["stringProcess::bytes2byte"]["bytes"]=$oneByte;
14654
			#可省略參數:
14655
			#無
14656
			$bytes2byte=stringProcess::bytes2bitString($conf["stringProcess::bytes2byte"]);
14657
			unset($conf["stringProcess::bytes2byte"]);
14658
 
14659
			#儲存bytes與其bit
14660
			$bytes[$bytesNum]["content"]=$bytes2byte["content"];
14661
 
14662
			}#foreach end
14663
 
14664
		#frame-fin 1 bit
14665
		#%x0 ; more frames of this message follow
14666
		#%x1 ; final frame of this message
14667
		$frameFin=$bytes[0]["content"][0];
14668
 
14669
		#如果不是最後一個 frame
14670
		if($frameFin==="0"){
14671
 
14672
			#如果要debug
14673
			if($conf["debug"]==="true"){
14674
 
14675
				#debug
14676
				echo __LINE__." frame-fin = 0, not supported".PHP_EOL;
14677
 
14678
				}#if end
14679
 
14680
			#設置警告訊息
14681
			$result["warning"][]="目前不支援大於一個frame的mask/unmask功能";
14682
 
14683
			#設置警告訊息
14684
			$result["warning"][]=$bytes;
14685
 
14686
			#設置為非 web socket frame
14687
			$result["type"]="invalid";
14688
 
14689
			#設置執行正常
14690
			$result["status"]="true";
14691
 
14692
			#回傳結果
14693
			return $result;
14694
 
14695
			}#if end
14696
 
14697
		#反之是最後一個 data frame
14698
		else{
14699
 
14700
			#如果要debug
14701
			if($conf["debug"]==="true"){
14702
 
14703
				#debug
14704
				echo __LINE__." frame-fin = 1, means this is a last data frame".PHP_EOL;
14705
 
14706
				}#if end
14707
 
14708
			}#else end
14709
 
14710
		#frame-rsv1 1 bit
14711
		#MUST be 0 unless negotiated otherwise
14712
		$frameRsv1=$bytes[0]["content"][1];
14713
 
14714
		#frame-rsv2 1 bit
14715
		#MUST be 0 unless negotiated otherwise
14716
		$frameRsv2=$bytes[0]["content"][2];
14717
 
14718
		#frame-rsv3 1 bit
14719
		#MUST be 0 unless negotiated otherwise
14720
		$frameRsv3=$bytes[0]["content"][3];
14721
 
14722
		#如果bit[1~3]都為0
14723
		if($frameRsv1===$frameRsv2 && $frameRsv2===$frameRsv3 && $frameRsv3==="0"){
14724
 
14725
			#如果要debug
14726
			if($conf["debug"]==="true"){
14727
 
14728
				#debug
14729
				echo __LINE__." frame-rsv1~3 = 0".PHP_EOL;
14730
 
14731
				}#if end
14732
 
14733
			}#if end
14734
 
14735
		#如果不存在第5個bit
14736
		if(!isset($bytes[0]["content"][4])){
14737
 
14738
			#如果要debug
14739
			if($conf["debug"]==="true"){
14740
 
14741
				#debug
14742
				echo __LINE__." $bytes[0]['content'][4] not set!".PHP_EOL;
14743
 
14744
				}#if end
14745
 
14746
			}#if end
14747
 
14748
		/*
14749
		frame-opcode 4 bit
14750
		frame-opcode-cont       = %x0 ; frame continuation
14751
 
14752
		frame-opcode-non-control= %x1 ; text frame
14753
					/ %x2 ; binary frame
14754
					/ %x3-7
14755
					; 4 bits in length,
14756
					; reserved for further non-control frames
14757
 
14758
		frame-opcode-control    = %x8 ; connection close
14759
					/ %x9 ; ping
14760
					/ %xA ; pong
14761
					/ %xB-F ; reserved for further control
14762
					; frames
14763
					; 4 bits in length
14764
		*/
14765
		#如果 bytes[0] 長度不足 8
14766
		if(gettype($bytes[0]["content"])==="array"){
14767
 
14768
			if(count($bytes[0]["content"])!==8){
14769
 
14770
				#$i為4~7
14771
				for($i=4;$i<8;$i++){
14772
 
14773
					#如果未設置
14774
					if(!isset($bytes[0]["content"][$i])){
14775
 
14776
						#用 "0" 去補
14777
						$bytes[0]["content"][$i]="0";
14778
 
14779
						}#if end
14780
 
14781
					}#for end
14782
 
14783
				}#if end
14784
 
14785
			}#if end
14786
 
14787
		$frameOpcode=$bytes[0]["content"][4].$bytes[0]["content"][5].$bytes[0]["content"][6].$bytes[0]["content"][7];
14788
 
14789
		#如果要debug
14790
		if($conf["debug"]==="true"){
14791
 
14792
			#debug
14793
			echo __LINE__." frame-opcode = ".$frameOpcode.PHP_EOL;
14794
 
14795
			}#if end
14796
 
14797
		$frameOpcodeIntX=$bytes[0]["content"][4]*pow(2,3)+$bytes[0]["content"][5]*pow(2,2)+$bytes[0]["content"][6]*pow(2,1)+$bytes[0]["content"][7]*pow(2,0); 
14798
 
14799
		#設置預設訊息類型為 unknow
14800
		$result["type"]="unknow";
14801
 
14802
		#如果 Opcode 等於 1
14803
		if($frameOpcodeIntX===1){
14804
 
14805
			#如果要debug
14806
			if($conf["debug"]==="true"){
14807
 
14808
				#debug
14809
				echo "It is a text frame".PHP_EOL;
14810
 
14811
				}#if end
14812
 
14813
			#設置該訊息類型為 text
14814
			$result["type"]="text";
14815
 
14816
			}#if end
14817
 
14818
		#如果 Opcode 等於 9
14819
		else if($frameOpcodeIntX===9){
14820
 
14821
			#如果要debug
14822
			if($conf["debug"]==="true"){
14823
 
14824
				#debug
14825
				echo "It is a ping frame".PHP_EOL;
14826
 
14827
				}#if end
14828
 
14829
			#設置該訊息類型為 text
14830
			$result["type"]="ping";
14831
 
14832
			}#if end
14833
 
14834
		#如果是 pong
14835
		else if($frameOpcodeIntX===10){
14836
 
14837
			#如果要debug
14838
			if($conf["debug"]==="true"){
14839
 
14840
				#debug
14841
				echo "It is a pong frame".PHP_EOL;
14842
 
14843
				}#if end
14844
 
14845
			#設置該訊息類型為 pong
14846
			$result["type"]="pong";
14847
 
14848
			}#if end
14849
 
14850
		#frame-masked 1 bit
14851
		#%x0 ;frame is not masked, no frame-masking-key
14852
		#%x1 ;frame is masked, frame-masking-key present 1 bit in lengt
14853
		$frameMasked=$bytes[1]["content"][0]; 
14854
 
14855
		#預設收到的訊息有mask過.
14856
		$masked=true;	
14857
 
14858
		#如果沒有 masked 
14859
		if($frameMasked!=='1'){
14860
 
14861
			#如果不允許沒有設置 masked bit 
14862
			if($conf["allowUnmask"]!=="true"){
14863
 
14864
				#如果要debug
14865
				if($conf["debug"]==="true"){
14866
 
14867
					#debug
14868
					echo __LINE__." frame-masked !== 1, differ with https://tools.ietf.org/html/rfc6455#section-5.3".PHP_EOL;
14869
 
14870
					}#if end
14871
 
14872
				#設置為非 web socket frame
14873
				$result["type"]="invalid";
14874
 
14875
				#設置執行正常
14876
				$result["status"]="true";
14877
 
14878
				#回傳結果
14879
				return $result;
14880
 
14881
				}#if end
14882
 
14883
			#設置收到的訊息沒有mask過.
14884
			$masked=false;
14885
 
14886
			}#if end
14887
 
14888
		#debug
14889
		#echo __LINE__." frame-masked = ".$frameMasked.PHP_EOL;
14890
 
14891
		#frame-payload-length 7 bit, 7+16 bits, or 7+64 bits
14892
		/*
14893
		The length of the "Payload data", in bytes: if 0-125, that is the
14894
		payload length.  If 126, the following 2 bytes interpreted as a
14895
		16-bit unsigned integer are the payload length.  If 127, the
14896
		following 8 bytes interpreted as a 64-bit unsigned integer (the
14897
		most significant bit MUST be 0) are the payload length.  Multibyte
14898
		length quantities are expressed in network byte order.  Note that
14899
		in all cases, the minimal number of bytes MUST be used to encode
14900
		the length, for example, the length of a 124-byte-long string
14901
		can't be encoded as the sequence 126, 0, 124.  The payload length
14902
		is the length of the "Extension data" + the length of the
14903
		"Application data".  The length of the "Extension data" may be
14904
		zero, in which case the payload length is the length of the
14905
		"Application data".
14906
		*/
14907
		if(gettype($bytes[1]["content"])==="array"){
14908
 
14909
			if(count($bytes[1]["content"])!==8){	
14910
 
14911
				#如果要debug
14912
				if($conf["debug"]==="true"){
14913
 
14914
					#debug
14915
					echo __LINE__." payloadLengthBit length !== 8".PHP_EOL;
14916
 
14917
					}#if end
14918
 
14919
				#如果 bit 不存在,用 0 補上
14920
				for($i=1;$i<8;$i++){
14921
 
14922
					#如果未設置
14923
					if(!isset($bytes[1]["content"][$i])){
14924
 
14925
						#用"0"替代
14926
						$bytes[1]["content"][$i]="0";
14927
 
14928
						}#if end
14929
 
14930
					}#for end
14931
 
14932
				#代表是用戶在連線.
14933
				#return "client connected!";
14934
 
14935
				}#if end
14936
 
14937
			}#if end
14938
 
14939
		$payloadLengthBit=$bytes[1]["content"][1].$bytes[1]["content"][2].$bytes[1]["content"][3].$bytes[1]["content"][4].$bytes[1]["content"][5].$bytes[1]["content"][6].$bytes[1]["content"][7];
14940
 
14941
		#length from 0~127(0~125)
14942
		$payloadLength=$bytes[1]["content"][7]*pow(2,0)+$bytes[1]["content"][6]*pow(2,1)+$bytes[1]["content"][5]*pow(2,2)+$bytes[1]["content"][4]*pow(2,3)+$bytes[1]["content"][3]*pow(2,4)+$bytes[1]["content"][2]*pow(2,5)+$bytes[1]["content"][1]*pow(2,6);
14943
 
14944
		#如果長度小於 126
14945
		if($payloadLength<126){
14946
 
14947
			#mask bit start bytes index 
14948
			$maskBitStartBytesIndex=2;
14949
 
14950
			#如果要debug
14951
			if($conf["debug"]==="true"){
14952
 
14953
				#debug
14954
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14955
 
14956
				}#if end
14957
 
14958
			}#if end
14959
 
14960
		#如果長度是 126
14961
		if($payloadLength===126){
14962
 
14963
			$payloadLengthBit=$bytes[2]["content"][0].$bytes[2]["content"][1].$bytes[2]["content"][2].$bytes[2]["content"][3].$bytes[2]["content"][4].$bytes[2]["content"][5].$bytes[2]["content"][6].$bytes[2]["content"][7].$bytes[3]["content"][0].$bytes[3]["content"][1].$bytes[3]["content"][2].$bytes[3]["content"][3].$bytes[3]["content"][4].$bytes[3]["content"][5].$bytes[3]["content"][6].$bytes[3]["content"][7];
14964
 
14965
			#初始化 payload 長度
14966
			$payloadLength=0;
14967
 
14968
			#2次迴圈,兩個bytes
14969
			for($i=0;$i<2;$i++){
14970
 
14971
				#8次迴圈,1個byte等於8個bit
14972
				for($j=0;$j<8;$j++){
14973
 
14974
					#次方數
14975
					$k=$j+8*$i;
14976
 
14977
					#加總 payload 長度
14978
					$payloadLength=$payloadLength+$bytes[3-$i]["content"][7-$j]*pow(2,$k);
14979
 
14980
					}#for end
14981
 
14982
				}#for end
14983
 
14984
			#mask bit start bytes index 
14985
			$maskBitStartBytesIndex=4;
14986
 
14987
			#如果要debug
14988
			if($conf["debug"]==="true"){
14989
 
14990
				#debug
14991
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14992
 
14993
				}#if end
14994
 
14995
			}#if end
14996
 
14997
		#如果長度是 127	
14998
		else if($payloadLength===127){
14999
 
15000
			$payloadLengthBit="";
15001
 
15002
			#四次迴圈(4個bytes)
15003
			for($i=0;$i<4;$i++){
15004
 
15005
				#8次迴圈,1個byte等於8個bit
15006
				for($j=0;$j<8;$j++){
15007
 
15008
					$payloadLengthBit=$payloadLengthBit.$bytes[4+$i]["content"][0+$j];
15009
 
15010
					}#for end
15011
 
15012
				}#for end
15013
 
15014
			#初始化 payload 長度
15015
			$payloadLength=0;
15016
 
15017
			#四次迴圈(4個bytes)
15018
			for($i=0;$i<4;$i++){
15019
 
15020
				#8次迴圈,1個byte等於8個bit
15021
				for($j=0;$j<8;$j++){
15022
 
15023
					#次方數
15024
					$k=$j+8*$i;
15025
 
15026
					$payloadLength=$payloadLength+$bytes[7-$i]["content"][7-$j]*pow(2,$k);
15027
 
15028
					}#for end
15029
 
15030
				}#for end
15031
 
15032
			#mask bit start bytes index 
15033
			$maskBitStartBytesIndex=8;
15034
 
15035
			#如果要debug
15036
			if($conf["debug"]==="true"){
15037
 
15038
				#debug
15039
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
15040
 
15041
				}#if end
15042
 
15043
			}#if end	
15044
 
15045
		#如果要debug
15046
		if($conf["debug"]==="true"){
15047
 
15048
			#debug
15049
			var_dump(__LINE__,$bytes);
15050
 
15051
			#debug 提示payload的長度的2進位表示法
15052
			echo __LINE__." payload data payloadLengthBit is ".$payloadLengthBit.PHP_EOL;	
15053
 
15054
			#debug 提示payload的長度
15055
			echo __LINE__." payload data length is ".$payloadLength." bytes".PHP_EOL;
15056
 
15057
			}#if end
15058
 
15059
		#如果有mask
15060
		if($masked){
15061
 
15062
			#組合 maskBit 字串
15063
			$maskBitStr=
15064
				chr(base_convert($bytes[$maskBitStartBytesIndex]["content"],2,10)).
15065
				chr(base_convert($bytes[$maskBitStartBytesIndex+1]["content"],2,10)).
15066
				chr(base_convert($bytes[$maskBitStartBytesIndex+2]["content"],2,10)).
15067
				chr(base_convert($bytes[$maskBitStartBytesIndex+3]["content"],2,10));
15068
 
15069
			#如果要debug
15070
			if($conf["debug"]==="true"){
15071
 
15072
				#debug 提示 mask bit 字串
15073
				echo __LINE__." maskBit str is ".$maskBitStr.PHP_EOL;
15074
 
15075
				}#if end
15076
 
15077
			}#if end
15078
 
15079
		#初始化 payload data 字串
15080
		$payloadDataStr="";
15081
 
15082
		#如果有mask
15083
		if($masked){
15084
 
15085
			#有多長就跑幾次
15086
			for($i=0;$i<$payloadLength;$i++){
15087
 
15088
				#串接 masked 的 payload data.
15089
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+4+$i]["content"],2,10));
15090
 
15091
				}#for end
15092
 
15093
			#如果要debug
15094
			if($conf["debug"]==="true"){
15095
 
15096
				#debug 提示 mask bit 字串
15097
				echo __LINE__." masked payload data str is ".$payloadDataStr.PHP_EOL;
15098
 
15099
				}#if end
15100
 
15101
			#unmask payload data
15102
			for($i=0;$i<$payloadLength;$i++){
15103
 
15104
				$payloadDataStr[$i]=$payloadDataStr[$i]^$maskBitStr[$i%4];
15105
 
15106
				}#for end
15107
 
15108
			}#if end
15109
 
15110
		#反之
15111
		else{
15112
 
15113
			#有多長就跑幾次
15114
			for($i=0;$i<$payloadLength;$i++){
15115
 
15116
				#串接 masked 的 payload data.
15117
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+$i]["content"],2,10));
15118
 
15119
				}#for end
15120
 
15121
			}#else end
15122
 
15123
		#取得 umask 後的內容
15124
		$result["content"]=$payloadDataStr;
15125
 
15126
		#設置執行正常
15127
		$result["status"]="true";
15128
 
15129
		#回傳結果	
15130
		return $result;
15131
 
15132
		}#function unmask end
15133
 
15134
	/*
15135
	#函式說明:
15136
	#加密 handshake 後要傳送的 webSocket 訊息 
15137
	#回傳結果:
15138
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15139
	#$result["error"],執行不正常結束的錯訊息陣列.
15140
	#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
15141
	#$result["argu"],陣列,使用的參數.
15142
	#必填參數:
15143
	#$conf["text"],字串,要加密的訊息.
15144
	$conf["text"]=""; 
15145
	#可省略參數:
15146
	#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
15147
	#$conf["payloadIsBin"]="false";
15148
	#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
15149
	#$conf["ping"]="false";
15150
	#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
15151
	#$conf["pong"]="false";
15152
	#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
15153
	#$conf["frames"]=array();
15154
	#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
15155
	#$conf["mask"]="false";
15156
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
15157
	#$conf["debug"]="false";
15158
	#參考資料:
15159
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
15160
	#備註:
15161
	#無.
15162
	*/
15163
	public static function encode(&$conf){
15164
 
15165
		#初始化要回傳的結果
15166
		$result=array();
15167
 
15168
		#設置當其函數名稱
15169
		$result["function"]=__FUNCTION__;
15170
 
15171
		#初始化分割好的 web socket 封包
15172
		$result["content"]=array();
15173
 
15174
		#如果 $conf 不為陣列
15175
		if(gettype($conf)!="array"){
15176
 
15177
			#設置執行失敗
15178
			$result["status"]="false";
15179
 
15180
			#設置執行錯誤訊息
15181
			$result["error"][]="\$conf變數須為陣列形態";
15182
 
15183
			#如果傳入的參數為 null
15184
			if($conf==null){
15185
 
15186
				#設置執行錯誤訊息
15187
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
15188
 
15189
				}#if end
15190
 
15191
			}#if end
15192
 
15193
		#設置放置的參數
15194
		$result["argu"]=$conf;
15195
 
15196
		#函式說明:
15197
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15198
		#回傳結果:
15199
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15200
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
15201
		#$result["simpleError"],簡單表示的錯誤訊息.
15202
		#$result["function"],當前執行的函式名稱.
15203
		#$result["argu"],設置給予的參數.
15204
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15205
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15206
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15207
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15208
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15209
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15210
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15211
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15212
		#必填參數:
15213
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15214
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
15215
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15216
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15217
		#可省略參數:
15218
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15219
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("text");
15220
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
15221
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
15222
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15223
		#$conf["canBeEmptyString"]="false";
15224
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15225
		#$conf["canNotBeEmpty"]=array();
15226
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15227
		#$conf["canBeEmpty"]=array();
15228
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15229
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("payloadIsBin","ping","pong","mask","debug");
15230
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15231
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("payloadIsBin","ping","pong","frames","mask","debug");
15232
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15233
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","string","string");
15234
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15235
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false","false",array(),"false","false");
15236
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15237
		$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="false";
15238
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15239
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15240
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15241
		#$conf["arrayCountEqualCheck"][]=array();
15242
		#參考資料:
15243
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15244
		#備註:
15245
		#無.
15246
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15247
		unset($conf["variableCheck::checkArguments"]);
15248
 
15249
		#如果執行失敗
15250
		if($checkArguments["status"]==="false"){
15251
 
15252
			#設置執行失敗
15253
			$result["status"]="false";
15254
 
15255
			#設置執行錯誤訊息
15256
			$result["error"]=$checkArguments;
15257
 
15258
			#回傳結果
15259
			return $result;
15260
 
15261
			}#if end
15262
 
15263
		#如果參數檢查不通過
15264
		if($checkArguments["passed"]==="false"){
15265
 
15266
			#設置執行失敗
15267
			$result["status"]="false";
15268
 
15269
			#設置執行錯誤訊息
15270
			$result["error"]=$checkArguments;
15271
 
15272
			#回傳結果
15273
			return $result;
15274
 
15275
			}#if end
15276
 
15277
		#如果是要產生 ping/pong 的訊息
15278
		if($conf["ping"]==="true" || $conf["pong"]==="true"){
15279
 
15280
			#強制將payload設置為空
15281
			$conf["text"]="";
15282
 
15283
			}#if end
15284
 
15285
		#取得payload
15286
		$text=$conf["text"];
15287
 
15288
		#取得 payload length
15289
		$length=strlen($text);
15290
 
15291
		#如果沒有payload
15292
		if($length===0){
15293
 
15294
			#初始化第一個 frame 為 最後一個 frame.
15295
			$header="1000";
15296
 
15297
			#如果是ping
15298
			if($conf["ping"]==="true"){
15299
 
15300
				#其訊息類別為 ping
15301
				$header=$header."1001";
15302
 
15303
				}#if end
15304
 
15305
			#如果是pong
15306
			else if($conf["pong"]==="true"){
15307
 
15308
				#其訊息類別為 pong
15309
				$header=$header."1010";
15310
 
15311
				}#if end
15312
 
15313
			#例外狀況
15314
			else{
15315
 
15316
				#設置執行失敗
15317
				$result["status"]="false";
15318
 
15319
				#設置執行錯誤訊息
15320
				$result["error"][]="參數 text 為空時,需要 ping or pong 參數擇一";
15321
 
15322
				#設置執行錯誤訊息
15323
				$result["error"][]=$checkArguments;
15324
 
15325
				#回傳結果
15326
				return $result;
15327
 
15328
				}#else end
15329
 
15330
			}#if end
15331
 
15332
		#反之有payload
15333
		else{
15334
 
15335
			#初始化第一個 frame 為 最後一個 frame.
15336
			$header="1000";
15337
 
15338
			#如果 payload 是 2元碼
15339
			if($conf["payloadIsBin"]==="true"){
15340
 
15341
				#設置 opecode 為 0010
15342
				$header=$header."0010";
15343
 
15344
				}#if end
15345
 
15346
			#反之為 text
15347
			else{
15348
 
15349
				#設置 opecode 為 0001
15350
				$header=$header."0001";
15351
 
15352
				}#else end
15353
 
15354
			}#else end
15355
 
15356
		#如果 payload 長度大於 125
15357
		while($length > 125){
15358
 
15359
			#初始化第一個 frame 為 不為最後一個 frame, 
15360
			$header="0000";
15361
 
15362
			#如果 payload 是 2元碼
15363
			if($conf["payloadIsBin"]==="true"){
15364
 
15365
				#設置 opecode 為 0010
15366
				$header=$header."0010";
15367
 
15368
				}#if end
15369
 
15370
			#反之為 text
15371
			else{
15372
 
15373
				#設置 opecode 為 0001
15374
				$header=$header."0001";
15375
 
15376
				}#else end
15377
 
15378
			#如果已經有前面的內容了
15379
			if(count($result["content"])>0){
15380
 
15381
				#設置為中間的 frame, 其 opcode 為 continue data.
15382
				$header="00000000";
15383
 
15384
				}#if end
15385
 
15386
			#取得125bytes
15387
			$body=substr($text,0,125);
15388
 
15389
			#函式說明:
15390
			#將2進位的8位數字字串,變成bytes字串.
15391
			#回傳結果:
15392
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15393
			#$result["function"],當前執行的函式內容.
15394
			#$result["error"],錯誤訊息陣列.
15395
			#$result["content"],bytes字串,亦即其代表的一個字.
15396
			#必填參數:
15397
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15398
			$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
15399
			#可省略參數:
15400
			#無.
15401
			#參考資料:
15402
			#無.
15403
			#備註:
15404
			#無.
15405
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15406
			unset($conf["stringProcess::bit2byteStr"]);
15407
 
15408
			#如果執行失敗
15409
			if($bit2byteStr["status"]==="false"){
15410
 
15411
				#設置執行失敗
15412
				$result["status"]="false";
15413
 
15414
				#設置執行錯誤訊息
15415
				$result["error"]=$bit2byteStr;
15416
 
15417
				#回傳結果
15418
				return $result;
15419
 
15420
				}#if end
15421
 
15422
			#取得該 byte 字串
15423
			$headerInByte=$bit2byteStr["content"];
15424
 
15425
			#預設不用mask
15426
			$maskBitAndLengthIntString=(string)(125);
15427
 
15428
			#如果需要mask
15429
			if($conf["mask"]==="true"){
15430
 
15431
				$maskBitAndLengthIntString=(string)(125+128);
15432
 
15433
				}#if end
15434
 
15435
			#函式說明:
15436
			#將2進位的8位數字字串,變成bytes字串.
15437
			#回傳結果:
15438
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15439
			#$result["function"],當前執行的函式內容.
15440
			#$result["error"],錯誤訊息陣列.
15441
			#$result["content"],bytes字串,亦即其代表的一個字.
15442
			#必填參數:
15443
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15444
			$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($maskBitAndLengthIntString,10,2);
15445
			#可省略參數:
15446
			#無.
15447
			#參考資料:
15448
			#無.
15449
			#備註:
15450
			#無.
15451
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15452
			unset($conf["stringProcess::bit2byteStr"]);
15453
 
15454
			#如果要 debug
15455
			if($conf["debug"]==="true"){
15456
 
15457
				#debug
15458
				var_dump(__LINE__,$bit2byteStr);
15459
 
15460
				}#if end
15461
 
15462
			#如果執行失敗
15463
			if($bit2byteStr["status"]==="false"){
15464
 
15465
				#設置執行失敗
15466
				$result["status"]="false";
15467
 
15468
				#設置執行錯誤訊息
15469
				$result["error"]=$bit2byteStr;
15470
 
15471
				#回傳結果
15472
				return $result;
15473
 
15474
				}#if end
15475
 
15476
			#取得該 byte 字串
15477
			$lengthInByte=$bit2byteStr["content"];
15478
 
15479
			#初始化 4 bytes mask key.
15480
			$maskKey4bytes="";
15481
 
15482
			#如果需要mask
15483
			if($conf["mask"]==="true"){
15484
 
15485
				#函式說明:
15486
				#隨機產生任意byte(s)組成的字串.
15487
				#回傳結果:
15488
				#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15489
				#$result["function"],當前執行的函式內容.
15490
				#$result["error"],錯誤訊息陣列.
15491
				#$result["content"],用字串來表示的byte(s).
15492
				#必填參數:
15493
				#無.
15494
				#可省略參數:
15495
				#$conf["length"],字串,要產生多少bytes的字串,預設為1.
15496
				$conf["stringProcess::randomByte"]["length"]="4";
15497
				#參考資料:
15498
				#無.
15499
				#備註:
15500
				#無.
15501
				$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
15502
				unset($conf["stringProcess::randomByte"]);
15503
 
15504
				#如果執行失敗
15505
				if($randomByte["status"]==="false"){
15506
 
15507
					#設置執行失敗
15508
					$result["status"]="false";
15509
 
15510
					#設置執行錯誤訊息
15511
					$result["error"]=$randomByte;
15512
 
15513
					#回傳結果
15514
					return $result;
15515
 
15516
					}#if end
15517
 
15518
				#取得隨機產生的 mask key
15519
				$maskKey4bytes=$randomByte["content"];
15520
 
15521
				#函式說明:
15522
				#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
15523
				#回傳結果:
15524
				#$result["function"],當前函式的名稱.
15525
				#$result["argu"],使用的參數.
15526
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
15527
				#$result["content"],unmask後的內容.
15528
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
15529
				#$result["error"],錯誤訊息陣列.
15530
				#必填參數:
15531
				#$conf["payload"],字串,要解密的訊息.
15532
				$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$body; 
15533
				#可省略參數:
15534
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
15535
				$conf["webSock::unmask"]["allowUnmask"]="true";
15536
				#參考資料
15537
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
15538
				#https://tools.ietf.org/html/rfc6455
15539
				#https://tools.ietf.org/html/rfc5234
15540
				#備註:
15541
				#無.
15542
				$unmask=webSock::unmask($conf["webSock::unmask"]);
15543
				unset($conf["webSock::unmask"]);
15544
 
15545
				#debug
15546
				#var_dump(__LINE__,$unmask);
15547
 
15548
				#如果執行失敗
15549
				if($unmask["status"]==="false"){
15550
 
15551
					#設置執行失敗
15552
					$result["status"]="false";
15553
 
15554
					#設置執行錯誤訊息
15555
					$result["error"]=$unmask;
15556
 
15557
					#回傳結果
15558
					return $result;
15559
 
15560
					}#if end
15561
 
15562
				#取得該段的結果
15563
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
15564
 
15565
				}#if end
15566
 
15567
			#反之
15568
			else{
15569
 
15570
				#取得該段的結果
15571
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$body;
15572
 
15573
				}#else end
15574
 
15575
			#取得剩下的內容
15576
			$text=substr($text,125);
15577
 
15578
			#取得 payload length
15579
			$length=strlen($text);
15580
 
15581
			}#while end
15582
 
15583
		#執行到這邊代表剩下的長度用一個 frame 即可表達
15584
 
15585
		#如果已經有內容了
15586
		if(count($result["content"])>0){
15587
 
15588
			#代表不用表示為 text frame 但要表示為最後一個 frame.
15589
			$header="10000000";
15590
 
15591
			}#if end
15592
 
15593
		#函式說明:
15594
		#將2進位的8位數字字串,變成bytes字串.
15595
		#回傳結果:
15596
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15597
		#$result["function"],當前執行的函式內容.
15598
		#$result["error"],錯誤訊息陣列.
15599
		#$result["content"],bytes字串,亦即其代表的一個字.
15600
		#必填參數:
15601
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15602
		$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
15603
		#可省略參數:
15604
		#無.
15605
		#參考資料:
15606
		#無.
15607
		#備註:
15608
		#無.
15609
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15610
		unset($conf["stringProcess::bit2byteStr"]);
15611
 
15612
		#如果執行失敗
15613
		if($bit2byteStr["status"]==="false"){
15614
 
15615
			#設置執行失敗
15616
			$result["status"]="false";
15617
 
15618
			#設置執行錯誤訊息
15619
			$result["error"]=$bit2byteStr;
15620
 
15621
			#回傳結果
15622
			return $result;
15623
 
15624
			}#if end
15625
 
15626
		#取得該 byte 字串
15627
		$headerInByte=$bit2byteStr["content"];
15628
 
15629
		#如果要 debug
15630
		if($conf["debug"]==="true"){
15631
 
15632
			#debug
15633
			var_dump(__LINE__,$length,base_convert($length,10,2));
15634
 
15635
			}#if end
15636
 
15637
		#如果需要mask
15638
		if($conf["mask"]==="true"){
15639
 
15640
			#增加maskbit
15641
			$length=$length+128;
15642
 
15643
			}#if end
15644
 
15645
		#函式說明:
15646
		#將2進位的8位數字字串,變成bytes字串.
15647
		#回傳結果:
15648
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15649
		#$result["function"],當前執行的函式內容.
15650
		#$result["error"],錯誤訊息陣列.
15651
		#$result["content"],bytes字串,亦即其代表的一個字.
15652
		#必填參數:
15653
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15654
		$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($length,10,2);
15655
		#可省略參數:
15656
		#無.
15657
		#參考資料:
15658
		#無.
15659
		#備註:
15660
		#無.
15661
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15662
		unset($conf["stringProcess::bit2byteStr"]);
15663
 
15664
		#如果要 debug
15665
		if($conf["debug"]==="true"){
15666
 
15667
			#debug
15668
			var_dump(__LINE__,$bit2byteStr);
15669
 
15670
			}#if end
15671
 
15672
		#如果執行失敗
15673
		if($bit2byteStr["status"]==="false"){
15674
 
15675
			#設置執行失敗
15676
			$result["status"]="false";
15677
 
15678
			#設置執行錯誤訊息
15679
			$result["error"]=$bit2byteStr;
15680
 
15681
			#回傳結果
15682
			return $result;
15683
 
15684
			}#if end
15685
 
15686
		#取得該 byte 字串
15687
		$lengthInByte=$bit2byteStr["content"];
15688
 
15689
		#初始化 4 bytes mask key.
15690
		$maskKey4bytes="";
15691
 
15692
		#如果需要mask
15693
		if($conf["mask"]==="true"){
15694
 
15695
			#函式說明:
15696
			#隨機產生任意byte(s)組成的字串.
15697
			#回傳結果:
15698
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15699
			#$result["function"],當前執行的函式內容.
15700
			#$result["error"],錯誤訊息陣列.
15701
			#$result["content"],用字串來表示的byte(s).
15702
			#必填參數:
15703
			#無.
15704
			#可省略參數:
15705
			#$conf["length"],字串,要產生多少bytes的字串,預設為1.
15706
			$conf["stringProcess::randomByte"]["length"]="4";
15707
			#參考資料:
15708
			#無.
15709
			#備註:
15710
			#無.
15711
			$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
15712
			unset($conf["stringProcess::randomByte"]);
15713
 
15714
			#如果執行失敗
15715
			if($randomByte["status"]==="false"){
15716
 
15717
				#設置執行失敗
15718
				$result["status"]="false";
15719
 
15720
				#設置執行錯誤訊息
15721
				$result["error"]=$randomByte;
15722
 
15723
				#回傳結果
15724
				return $result;
15725
 
15726
				}#if end
15727
 
15728
			#取得隨機產生的 mask key
15729
			$maskKey4bytes=$randomByte["content"];
15730
 
15731
			}#if end
15732
 
15733
		#函式說明:
15734
		#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
15735
		#回傳結果:
15736
		#$result["function"],當前函式的名稱.
15737
		#$result["argu"],使用的參數.
15738
		#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
15739
		#$result["content"],unmask後的內容.
15740
		#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
15741
		#$result["error"],錯誤訊息陣列.
15742
		#必填參數:
15743
		#$conf["payload"],字串,要解密的訊息.
15744
		$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$text; 
15745
		#可省略參數:
15746
		#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
15747
		$conf["webSock::unmask"]["allowUnmask"]="true";
15748
		#參考資料
15749
		#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
15750
		#https://tools.ietf.org/html/rfc6455
15751
		#https://tools.ietf.org/html/rfc5234
15752
		#備註:
15753
		#無.
15754
		$unmask=webSock::unmask($conf["webSock::unmask"]);
15755
		unset($conf["webSock::unmask"]);
15756
 
15757
		#如果要 debug
15758
		if($conf["debug"]==="true"){
15759
 
15760
			#debug
15761
			var_dump(__LINE__,$unmask);
15762
 
15763
			}#if end
15764
 
15765
		#如果執行失敗
15766
		if($unmask["status"]==="false"){
15767
 
15768
			#設置執行失敗
15769
			$result["status"]="false";
15770
 
15771
			#設置執行錯誤訊息
15772
			$result["error"]=$unmask;
15773
 
15774
			#回傳結果
15775
			return $result;
15776
 
15777
			}#if end
15778
 
15779
		#儲存訊息
15780
		$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
15781
 
15782
		#設置執行正常
15783
		$result["status"]="true";
15784
 
15785
		#回傳結果
15786
		return $result;
15787
 
15788
		}#function encode end
15789
 
15790
	/*
15791
	函式說明:
15792
	提供webSock::nativeSocketTcpIpServer的processFuncs參數所用的函式,可以接受要求傳遞檔案的內容給用戶.
15793
	#回傳結果:
15794
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
15795
	#$result["error"],執行不正常結束的錯訊息陣列.
15796
	#$result["argu"],陣列,使用的參數.
15797
	#必填參數:
15798
	#$conf["data"],字串,收到的json格式資料,必填的key有"Method","Host","File",Method的value目前只支援"GET",Host的value為ServerName亦即網站的網域,File為要求的檔案路徑與名稱;可省略的key有"Range"跟"partSize"跟id,Range的value為需要的檔案內容範圍,目前只支援"bytes=n1-n2"的格式,partSize的value為取得檔案的分段大小,預設為1024000(bytes),亦即1MB,id為用於給用戶端識別的id.
15799
	$conf["data"]="";
15800
	#$conf["serverSock"],resource,web socket server socket
15801
	$conf["serverSock"]=$resource;
15802
	#$conf["clientSock"],$resource,web socket client socket
15803
	$conf["clientSock"]=$resource;
15804
	#$conf["clientInfo"],陣列,web socket client info.
15805
	$conf["clientInfo"]=array();
15806
	#$conf["clientIndex"],整數.web socket client index.
15807
	$conf["clientIndex"];
15808
	#$conf["allConn"],陣列,all web socket client info.
15809
	$conf["allConn"]=array();
15810
	#可省略參數:
15811
	#無.
15812
	#參考資料:
15813
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
15814
	#備註:
15815
	#無.
15816
	*/
15817
	public static function getFileContent(&$conf){
15818
 
15819
		#初始化要回傳的結果
15820
		$result=array();
15821
 
15822
		#取得當前執行的函數名稱
15823
		$result["function"]=__FUNCTION__;
15824
 
15825
		#如果沒有參數
15826
		if(func_num_args()==0){
15827
 
15828
			#設置執行失敗
15829
			$result["status"]="false";
15830
 
15831
			#設置執行錯誤訊息
15832
			$result["error"]="函數".$result["function"]."需要參數";
15833
 
15834
			#回傳結果
15835
			return $result;
15836
 
15837
			}#if end
15838
 
15839
		#涵式說明:
15840
		#判斷當前環境為web還是cmd
15841
		#回傳結果:
15842
		#$result,"web"或"cmd"
15843
		if(csInformation::getEnv()==="web"){
15844
 
15845
			#設置執行失敗
15846
			$result["status"]="false";
15847
 
15848
			#設置執行錯誤訊息
15849
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
15850
 
15851
			#回傳結果
15852
			return $result;
15853
 
15854
			}#if end
15855
 
15856
		#取得參數
15857
		$result["argu"]=$conf;
15858
 
15859
		#如果 $conf 不為陣列
15860
		if(gettype($conf)!=="array"){
15861
 
15862
			#設置執行失敗
15863
			$result["status"]="false";
15864
 
15865
			#設置執行錯誤訊息
15866
			$result["error"][]="\$conf變數須為陣列形態";
15867
 
15868
			#如果傳入的參數為 null
15869
			if(is_null($conf)){
15870
 
15871
				#設置執行錯誤訊息
15872
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
15873
 
15874
				}#if end
15875
 
15876
			#回傳結果
15877
			return $result;
15878
 
15879
			}#if end
15880
 
15881
		#debug
15882
		#var_dump(__FUNCTION__,__LINE__,$conf);
15883
 
15884
		#檢查參數
15885
		#函式說明:
15886
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15887
		#回傳結果:
15888
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15889
		#$result["error"],執行不正常結束的錯訊息陣列.
15890
		#$result["simpleError"],簡單表示的錯誤訊息.
15891
		#$result["function"],當前執行的函式名稱.
15892
		#$result["argu"],設置給予的參數.
15893
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15894
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15895
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15896
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15897
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15898
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15899
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15900
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15901
		#必填參數:
15902
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15903
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
15904
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15905
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15906
		#可省略參數:
15907
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15908
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientSock","clientInfo","clientIndex","allConn");
15909
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
15910
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","resource","array","integer","array");
15911
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15912
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
15913
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15914
		#$conf["canNotBeEmpty"]=array();
15915
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15916
		#$conf["canBeEmpty"]=array();
15917
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15918
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("Range","partSize");
15919
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15920
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("Range","partSize");
15921
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15922
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","partSize");
15923
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15924
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,"1024000");
15925
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15926
		#$conf["disallowAllSkipableVarIsEmpty"]="";
15927
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15928
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15929
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
15930
		#$conf["disallowAllSkipableVarNotExist"]="";
15931
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15932
		#$conf["arrayCountEqualCheck"][]=array();
15933
		#參考資料:
15934
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15935
		#備註:
15936
		#無.
15937
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15938
		unset($conf["variableCheck::checkArguments"]);
15939
 
15940
		#debug
15941
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
15942
 
15943
		#如果執行失敗
15944
		if($checkArguments["status"]==="false"){
15945
 
15946
			#設置錯誤訊息
15947
			$result["error"]=$checkArguments;
15948
 
15949
			#var_dump,交給下個 processFuncs 處理
15950
			$result["status"]="false";
15951
 
15952
			#回傳結果
15953
			return $result;
15954
 
15955
			}#if end
15956
 
15957
		#如果檢查不通過
15958
		if($checkArguments["passed"]==="false"){
15959
 
15960
			#不處理,略過,交給下個 processFuncs 處理
15961
			$result["status"]="continue";
15962
 
15963
			#回傳結果
15964
			return $result;
15965
 
15966
			}#if end
15967
 
15968
		#檢查收到的訊息是否為json格式
15969
		$revJson=@json_decode($conf["data"]);
15970
 
15971
		#如果不是 json
15972
		if($revJson===null){
15973
 
15974
			#不處理,略過,交給下個 processFuncs 處理
15975
			$result["status"]="continue";
15976
 
15977
			#回傳結果
15978
			return $result;
15979
 
15980
			}#if enf
15981
 
15982
		#轉換為陣列
15983
		$revJson=(array)($revJson);
15984
 
15985
		#檢查參數
15986
		#函式說明:
15987
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15988
		#回傳結果:
15989
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15990
		#$result["error"],執行不正常結束的錯訊息陣列.
15991
		#$result["simpleError"],簡單表示的錯誤訊息.
15992
		#$result["function"],當前執行的函式名稱.
15993
		#$result["argu"],設置給予的參數.
15994
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15995
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15996
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15997
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15998
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15999
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
16000
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
16001
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
16002
		#必填參數:
16003
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
16004
		$conf["variableCheck::checkArguments"]["varInput"]=&$revJson;
16005
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
16006
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
16007
		#可省略參數:
16008
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
16009
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("Method","Host","File");
16010
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
16011
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string");
16012
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
16013
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
16014
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
16015
		#$conf["canNotBeEmpty"]=array();
16016
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
16017
		#$conf["canBeEmpty"]=array();
16018
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
16019
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("id","Range","partSize");
16020
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
16021
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","Range","partSize");
16022
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
16023
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string");
16024
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
16025
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,null,"1024000");
16026
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
16027
		#$conf["disallowAllSkipableVarIsEmpty"]="";
16028
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
16029
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
16030
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
16031
		#$conf["disallowAllSkipableVarNotExist"]="";
16032
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
16033
		#$conf["arrayCountEqualCheck"][]=array();
16034
		#參考資料:
16035
		#array_keys=>http://php.net/manual/en/function.array-keys.php
16036
		#備註:
16037
		#無.
16038
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
16039
		unset($conf["variableCheck::checkArguments"]);
16040
 
16041
		#debug
16042
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
16043
 
16044
		#如果執行失敗
16045
		if($checkArguments["status"]==="false"){
16046
 
16047
			#設置錯誤訊息
16048
			$result["error"]=$checkArguments;
16049
 
16050
			#var_dump,交給下個 processFuncs 處理
16051
			$result["status"]="false";
16052
 
16053
			#回傳結果
16054
			return $result;
16055
 
16056
			}#if end
16057
 
16058
		#如果檢查不通過
16059
		if($checkArguments["passed"]==="false"){
16060
 
16061
			#不處理,略過,交給下個 processFuncs 處理
16062
			$result["status"]="continue";
16063
 
16064
			#回傳結果
16065
			return $result;
16066
 
16067
			}#if end
16068
 
16069
		#如果是 GET Method
16070
		if($revJson["Method"]==="GET"){
16071
 
16072
			#解析 apache vhost info
16073
			#函式說明:
16074
			#使用 linux 的 httpd 指令來取得 vhost 資訊.
16075
			#回傳結果:
16076
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16077
			#$result["error"],錯誤訊息.
16078
			#$result["function"],當前執行的函式名稱.
16079
			#$result["content"],得到的結果陣列,每個元素可能會含有的key有ServerName、DocumentRoot、ServerAlias,其中DocumentRoot的數值會是用""包起來的路徑.
16080
			#必填參數:
16081
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
16082
			$conf["cmd::httpdGetVhostInfo"]["fileArgu"]=__FILE__;
16083
			#可省略參數:
16084
			#無.
16085
			#參考資料:
16086
			#無
16087
			#備註:
16088
			#無.
16089
			$httpdGetVhostInfo=cmd::httpdGetVhostInfo($conf["cmd::httpdGetVhostInfo"]);
16090
			unset($conf["cmd::httpdGetVhostInfo"]);
16091
 
16092
			#debug
16093
			#var_dump(__FUNCTION__,__LINE__,$httpdGetVhostInfo);
16094
 
16095
			#如果執行失敗
16096
			if($httpdGetVhostInfo["status"]==="false"){
16097
 
16098
				#設置錯誤訊息
16099
				$result["error"]=$httpdGetVhostInfo;
16100
 
16101
				#var_dump,交給下個 processFuncs 處理
16102
				$result["status"]="false";
16103
 
16104
				#回傳結果
16105
				return $result;
16106
 
16107
				}#if end
16108
 
16109
			#針對每個結果
16110
			foreach($httpdGetVhostInfo["content"] as $vhost){
16111
 
16112
				#如果有 ServerName
16113
				if(isset($vhost["ServerName"])){
16114
 
16115
					#如果是要找的 Host
16116
					if($vhost["ServerName"]===$revJson["Host"]){
16117
 
16118
						#如果有 DocumentRoot
16119
						if(isset($vhost["DocumentRoot"])){
16120
 
16121
							#組合要取得的檔案路徑與名稱
16122
							$file=$vhost["DocumentRoot"]."/".$revJson["File"];
16123
 
16124
							#debug
16125
							#var_dump(__LINE__,$file);
16126
 
16127
							#如果有 Range 參數
16128
							if(isset($revJson["Range"])){
16129
 
16130
								#格式參考
16131
								#bytes=0-499
16132
 
16133
								#函式說明:
16134
								#將字串特定關鍵字與其前面的內容剔除
16135
								#回傳結果:
16136
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16137
								#$result["error"],錯誤訊息陣列.
16138
								#$result["warning"],警告訊息鎮列.
16139
								#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
16140
								#$result["function"],當前執行的函數名稱.
16141
								#$result["argu"],使用的參數.
16142
								#$result["oriStr"],要處理的原始字串內容.
16143
								#$result["content"],處理好的的字串內容.	
16144
								#必填參數:
16145
								#$conf["stringIn"],字串,要處理的字串.
16146
								$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$revJson["Range"];
16147
								#$conf["keyWord"],字串,特定字串.
16148
								$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="bytes=";
16149
								#可省略參數:
16150
								#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
16151
								#$conf["recursive"]="true";
16152
								#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
16153
								#$conf["lastResult"]=$delStrBeforeKeyWord;
16154
								#參考資料:
16155
								#無.
16156
								#備註:
16157
								#無.
16158
								$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
16159
								unset($conf["stringProcess::delStrBeforeKeyWord"]);
16160
 
16161
								#如果執行失敗
16162
								if($delStrBeforeKeyWord["status"]==="false"){
16163
 
16164
									#設置錯誤訊息
16165
									$result["error"]=$delStrBeforeKeyWord;
16166
 
16167
									#var_dump,交給下個 processFuncs 處理
16168
									$result["status"]="false";
16169
 
16170
									#回傳結果
16171
									return $result;
16172
 
16173
									}#if end
16174
 
16175
								#如果沒有該有的關鍵字
16176
								if($delStrBeforeKeyWord["founded"]==="false"){
16177
 
16178
									#設置錯誤訊息
16179
									$result["error"]=$delStrBeforeKeyWord;
16180
 
16181
									#var_dump,交給下個 processFuncs 處理
16182
									$result["status"]="false";
16183
 
16184
									#回傳結果
16185
									return $result;
16186
 
16187
									}#if end
16188
 
16189
								#解析 bytes start and end
16190
								#函式說明:
16191
								#將固定格式的字串分開,並回傳分開的結果.
16192
								#回傳結果:
16193
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16194
								#$result["error"],錯誤訊息陣列
16195
								#$result["function"],當前執行的函數名稱.
16196
								#$result["argu"],使用的參數.
16197
								#$result["oriStr"],要分割的原始字串內容
16198
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
16199
								#$result["dataCounts"],爲總共分成幾段
16200
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
16201
								#必填參數:
16202
								#$conf["stringIn"],字串,要處理的字串.
16203
								$conf["stringProcess::spiltString"]["stringIn"]=$delStrBeforeKeyWord["content"];
16204
								#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
16205
								$conf["stringProcess::spiltString"]["spiltSymbol"]="-";
16206
								#可省略參數:
16207
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
16208
								#$conf["allowEmptyStr"]="false";
16209
								#參考資料:
16210
								#無.
16211
								#備註:
16212
								#無.
16213
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
16214
								unset($conf["stringProcess::spiltString"]);
16215
 
16216
								#如果執行失敗
16217
								if($spiltString["status"]==="false"){
16218
 
16219
									#設置錯誤訊息
16220
									$result["error"]=$spiltString;
16221
 
16222
									#var_dump,交給下個 processFuncs 處理
16223
									$result["status"]="false";
16224
 
16225
									#回傳結果
16226
									return $result;
16227
 
16228
									}#if end
16229
 
16230
								#如果沒有應該有的 - 符號
16231
								if($spiltString["found"]==="false"){
16232
 
16233
									#設置錯誤訊息
16234
									$result["error"]=$spiltString;
16235
 
16236
									#var_dump,交給下個 processFuncs 處理
16237
									$result["status"]="false";
16238
 
16239
									#回傳結果
16240
									return $result;
16241
 
16242
									}#if end
16243
 
16244
								#如果沒有分割成2段
16245
								if($spiltString["dataCounts"]!==2){
16246
 
16247
									#設置錯誤訊息
16248
									$result["error"]=$spiltString;
16249
 
16250
									#var_dump,交給下個 processFuncs 處理
16251
									$result["status"]="false";
16252
 
16253
									#回傳結果
16254
									return $result;
16255
 
16256
									}#if end
16257
 
16258
								#依照Range來取得檔案內容
16259
								#函式說明:
16260
								#取得檔案的部分內容
16261
								#回傳結果:
16262
								#$result["status"],"true"代表移除成功,"false"代表移除失敗.
16263
								#$result["error"],錯誤訊息陣列.
16264
								#$result["function"],當前執行的函數名稱.
16265
								#$result["cmd"],執行的指令.
16266
								#$result["content"],取得的檔案內容.
16267
								#$result["length"],取得的內容長度.
16268
								#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
16269
								#$result["mimeType"],檔案的 mime type.
16270
								#必填參數:
16271
								#$conf["file"],字串,檔案的路徑與名稱.
16272
								$conf["fileAccess::getFilePart"]["file"]=$file;
16273
								#$conf["fileArgu"],字串,__FILE__的內容.
16274
								$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
16275
								#$conf["bytes"],整數字串,要讀取多少bytes.
16276
								$conf["fileAccess::getFilePart"]["bytes"]=$spiltString["dataArray"][1]-$spiltString["dataArray"][0]+1;
16277
								#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
16278
								$conf["fileAccess::getFilePart"]["startIndex"]=$spiltString["dataArray"][0];
16279
								#可省略參數:
16280
								#無
16281
								#參考資料:
16282
								#無.
16283
								#備註:
16284
								#無
16285
								$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
16286
								unset($conf["fileAccess::getFilePart"]);
16287
 
16288
								#如果執行失敗
16289
								if($getFilePart["status"]==="false"){
16290
 
16291
									#設置錯誤訊息
16292
									$result["error"]=$getFilePart;
16293
 
16294
									#var_dump,交給下個 processFuncs 處理
16295
									$result["status"]="false";
16296
 
16297
									#回傳結果
16298
									return $result;
16299
 
16300
									}#if end
16301
 
16302
								#初始化要傳遞的訊息
16303
								$msg=array();
16304
 
16305
								#設置為最後一份了
16306
								$msg["LastPart"]="true";
16307
 
16308
								#設置資料內容類型為binary
16309
								$msg["dataType"]="binary";
16310
 
16311
								#設置內容
16312
								$msg["content"]=$getFilePart["content"];
16313
 
16314
								#設置 mimeType
16315
								$msg["mimeType"]=$getFilePart["mimeType"];
16316
 
16317
								#如果有設置 id
16318
								if(isset($revJson["id"])){
16319
 
16320
									#設置資料的 id
16321
									$msg["id"]=$revJson["id"];
16322
 
16323
									}#if end
16324
 
16325
								#函式說明:
16326
								#加密 handshake 後要傳送的訊息 
16327
								#回傳結果:
16328
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16329
								#$result["error"],執行不正常結束的錯訊息陣列.
16330
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16331
								#$result["argu"],陣列,使用的參數.
16332
								#必填參數:
16333
								#$conf["text"],字串,要加密的訊息.
16334
								$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
16335
								#可省略參數:
16336
								#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16337
								#$conf["webSock::encode"]["payloadIsBin"]="true";
16338
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16339
								#$conf["ping"]="false";
16340
								#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16341
								#$conf["pong"]="false";
16342
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16343
								#$conf["frames"]=array();
16344
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16345
								#$conf["webSock::encode"]["mask"]="false";
16346
								#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16347
								#$conf["debug"]="false";
16348
								#參考資料:
16349
								#無.
16350
								#備註:
16351
								#無.
16352
								$talkback=webSock::encode($conf["webSock::encode"]);
16353
								unset($conf["webSock::encode"]);
16354
 
16355
								#如果執行失敗
16356
								if($talkback["status"]==="false"){
16357
 
16358
									#印出結果
16359
									var_dump($talkback);
16360
 
16361
									#結束執行
16362
									exit;
16363
 
16364
									}#if end
16365
 
16366
								#針對每個訊息的分段
16367
								foreach($talkback["content"] as $msg){
16368
 
16369
									#回傳訊息
16370
									$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16371
 
16372
									#如果傳遞訊息給用戶失敗
16373
									if($socket_write===false){
16374
 
16375
										#取得錯誤代碼
16376
										$errorCode=socket_last_error($conf["clientSock"]);
16377
 
16378
										#設置執行失敗
16379
										$result["status"]="false";
16380
 
16381
										#設置錯誤代碼
16382
										$result["error"][]="error code:".$errorCode;
16383
 
16384
										#設置錯誤代碼說明
16385
										$result["erorr"][]="error description:".socket_strerror($errorCode);
16386
 
16387
										#回傳結果
16388
										return $result;
16389
 
16390
										}#if end
16391
 
16392
									}#foreach end
16393
 
16394
								#設置正常,結束後面函式的執行
16395
								$result["status"]="true";
16396
 
16397
								#回傳結果
16398
								return $result;
16399
 
16400
								}#if end
16401
 
16402
							#反之沒有 Rnage 參數
16403
							else{
16404
 
16405
								#執行到這邊代表要取得全部的檔案內容
16406
 
16407
								#debug
16408
								#var_dump(__LINE__,"get full file content");
16409
 
16410
								#第一部分的編號
16411
								$partNo=0;
16412
 
16413
								#無窮迴圈
16414
								while(true){
16415
 
16416
									#分段取得檔案
16417
									#函式說明:
16418
									#取得檔案的部分內容
16419
									#回傳結果:
16420
									#$result["status"],"true"代表移除成功,"false"代表移除失敗.
16421
									#$result["error"],錯誤訊息陣列.
16422
									#$result["function"],當前執行的函數名稱.
16423
									#$result["cmd"],執行的指令.
16424
									#$result["content"],取得的檔案內容.
16425
									#$result["length"],取得的內容長度.
16426
									#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
16427
									#$result["mimeType"],檔案的 mime type.
16428
									#必填參數:
16429
									#$conf["file"],字串,檔案的路徑與名稱.
16430
									$conf["fileAccess::getFilePart"]["file"]=$file;
16431
									#$conf["fileArgu"],字串,__FILE__的內容.
16432
									$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
16433
									#$conf["bytes"],整數字串,要讀取多少bytes.
16434
									$conf["fileAccess::getFilePart"]["bytes"]=$revJson["partSize"];
16435
									#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
16436
									$conf["fileAccess::getFilePart"]["startIndex"]=$partNo*$revJson["partSize"];
16437
									#可省略參數:
16438
									#無
16439
									#參考資料:
16440
									#無.
16441
									#備註:
16442
									#無
16443
									$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
16444
									unset($conf["fileAccess::getFilePart"]);
16445
 
16446
									#debug
16447
									#var_dump(__LINE__,$getFilePart);
16448
 
16449
									#如果執行失敗
16450
									if($getFilePart["status"]==="false"){
16451
 
16452
										#設置錯誤訊息
16453
										$result["error"]=$getFilePart;
16454
 
16455
										#var_dump,交給下個 processFuncs 處理
16456
										$result["status"]="false";
16457
 
16458
										#回傳結果
16459
										return $result;
16460
 
16461
										}#if end
16462
 
16463
									#初始化要傳遞的訊息
16464
									$msg=array();
16465
 
16466
									#設置不為最後一份
16467
									$msg["LastPart"]="false";
16468
 
16469
									#設置資料內容類型為binary
16470
									$msg["dataType"]="binary";
16471
 
16472
									#設置內容
16473
									$msg["content"]=$getFilePart["content"];
16474
 
16475
									#設置 mimeType
16476
									$msg["mimeType"]=$getFilePart["mimeType"];
16477
 
16478
									#如果有設置 id
16479
									if(isset($revJson["id"])){
16480
 
16481
										#設置資料的 id
16482
										$msg["id"]=$revJson["id"];
16483
 
16484
										}#if end
16485
 
16486
									#如果偵測到檔案結尾
16487
									if($getFilePart["EOF"]==="true"){
16488
 
16489
										#設置為最後一份了
16490
										$msg["LastPart"]="true";
16491
 
16492
										#如果沒有內容
16493
										if($getFilePart["length"]===0){
16494
 
16495
											#檔案區塊數字-1
16496
											$partNo--;
16497
 
16498
											}#if end
16499
 
16500
										#傳遞給 client - start
16501
 
16502
										#編碼後的訊息
16503
										$msgEncoded=base64_encode(urlencode(json_encode($msg)));
16504
 
16505
										#debug
16506
										#var_dump(__LINE__,$msg,$msgEncoded);
16507
 
16508
										#函式說明:
16509
										#加密 handshake 後要傳送的訊息 
16510
										#回傳結果:
16511
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16512
										#$result["error"],執行不正常結束的錯訊息陣列.
16513
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16514
										#$result["argu"],陣列,使用的參數.
16515
										#必填參數:
16516
										#$conf["text"],字串,要加密的訊息.
16517
										$conf["webSock::encode"]["text"]=$msgEncoded; 
16518
										#可省略參數:
16519
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16520
										#$conf["webSock::encode"]["payloadIsBin"]="false";
16521
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16522
										#$conf["ping"]="false";
16523
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16524
										#$conf["pong"]="false";
16525
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16526
										#$conf["frames"]=array();
16527
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16528
										#$conf["webSock::encode"]["mask"]="false";
16529
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16530
										#$conf["debug"]="false";
16531
										#參考資料:
16532
										#無.
16533
										#備註:
16534
										#無.
16535
										$talkback=webSock::encode($conf["webSock::encode"]);
16536
										unset($conf["webSock::encode"]);
16537
 
16538
										#debug
16539
										#var_dump(__LINE__,$talkback);
16540
 
16541
										#如果執行失敗
16542
										if($talkback["status"]==="false"){
16543
 
16544
											#印出結果
16545
											var_dump($talkback);
16546
 
16547
											#結束執行
16548
											exit;
16549
 
16550
											}#if end
16551
 
16552
										#針對每個訊息的分段
16553
										foreach($talkback["content"] as $msg){
16554
 
16555
											#回傳訊息
16556
											$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16557
 
16558
											#debug
16559
											#var_dump(__LINE__,$socket_write,$msg);
16560
 
16561
											#如果傳遞訊息給用戶失敗
16562
											if($socket_write===false){
16563
 
16564
												#取得錯誤代碼
16565
												$errorCode=socket_last_error($conf["clientSock"]);
16566
 
16567
												#設置執行失敗
16568
												$result["status"]="false";
16569
 
16570
												#設置錯誤代碼
16571
												$result["error"][]="error code:".$errorCode;
16572
 
16573
												#設置錯誤代碼說明
16574
												$result["erorr"][]="error description:".socket_strerror($errorCode);
16575
 
16576
												#回傳結果
16577
												return $result;
16578
 
16579
												}#if end
16580
 
16581
											}#foreach end
16582
 
16583
										#傳遞給 client - end
16584
 
16585
										#結束 while
16586
										break;
16587
 
16588
										}#if end
16589
 
16590
									#傳遞給 client - start
16591
 
16592
									#debug
16593
									#var_dump(__LINE__,"start tranfer");
16594
 
16595
									#函式說明:
16596
									#加密 handshake 後要傳送的訊息 
16597
									#回傳結果:
16598
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16599
									#$result["error"],執行不正常結束的錯訊息陣列.
16600
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16601
									#$result["argu"],陣列,使用的參數.
16602
									#必填參數:
16603
									#$conf["text"],字串,要加密的訊息.
16604
									$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
16605
									#可省略參數:
16606
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16607
									#$conf["webSock::encode"]["payloadIsBin"]="true";
16608
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16609
									#$conf["ping"]="false";
16610
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16611
									#$conf["pong"]="false";
16612
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16613
									#$conf["frames"]=array();
16614
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16615
									#$conf["webSock::encode"]["mask"]="false";
16616
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16617
									#$conf["debug"]="false";
16618
									#參考資料:
16619
									#無.
16620
									#備註:
16621
									#無.
16622
									$talkback=webSock::encode($conf["webSock::encode"]);
16623
									unset($conf["webSock::encode"]);
16624
 
16625
									#如果執行失敗
16626
									if($talkback["status"]==="false"){
16627
 
16628
										#印出結果
16629
										var_dump($talkback);
16630
 
16631
										#結束執行
16632
										exit;
16633
 
16634
										}#if end
16635
 
16636
									#針對每個訊息的分段
16637
									foreach($talkback["content"] as $msg){
16638
 
16639
										#回傳訊息
16640
										$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16641
 
16642
										#如果傳遞訊息給用戶失敗
16643
										if($socket_write===false){
16644
 
16645
											#取得錯誤代碼
16646
											$errorCode=socket_last_error($conf["clientSock"]);
16647
 
16648
											#設置執行失敗
16649
											$result["status"]="false";
16650
 
16651
											#設置錯誤代碼
16652
											$result["error"][]="error code:".$errorCode;
16653
 
16654
											#設置錯誤代碼說明
16655
											$result["erorr"][]="error description:".socket_strerror($errorCode);
16656
 
16657
											#回傳結果
16658
											return $result;
16659
 
16660
											}#if end
16661
 
16662
										}#foreach end
16663
 
16664
									#傳遞給 client - end
16665
 
16666
									#檔案區塊數字+1
16667
									$partNo++;
16668
 
16669
									}#while end
16670
 
16671
								#設置執行正常
16672
								$result["status"]="true";
16673
 
16674
								#回傳結果
16675
								return $result;
16676
 
16677
								}#else end
16678
 
16679
							}#if end
16680
 
16681
						}#if end
16682
 
16683
					}#if end
16684
 
16685
				}#foreach end
16686
 
16687
			#設置執行不正常
16688
			$result["status"]="false";
16689
 
16690
			#設置執行錯誤
16691
			$result["error"]="no matched ServerName";
16692
 
16693
			#debug
66 liveuser 16694
			var_dump(__FUNCTION__,__LINE__,$result);
3 liveuser 16695
 
16696
			#回傳結果
16697
			return $result;
16698
 
16699
			}#if end
16700
 
16701
		#設置執行不正常
16702
		$result["status"]="false";
16703
 
16704
		#設置執行錯誤
16705
		$result["error"]="Method should be GET";
16706
 
16707
		#回傳結果
16708
		return $result;
16709
 
16710
		}#function getFileContent end
16711
 
66 liveuser 16712
	/*
16713
	#函式說明:
16714
	#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
16715
	#回傳結果:
16716
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16717
	#$result["error"],執行不正常結束的錯訊息陣列.
16718
	#$result["argu"],陣列,使用的參數.
16719
	#必填參數:
16720
	#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
16721
	$conf["data"]="";
16722
	#$conf["serverSock"],resource,web socket server socket
16723
	$conf["serverSock"]=$resource;
16724
	#$conf["clientSock"],$resource,web socket client socket
16725
	$conf["clientSock"]=$resource;
16726
	#$conf["clientInfo"],陣列,web socket client info.
16727
	$conf["clientInfo"]=array();
16728
	#$conf["clientIndex"],整數.web socket client index.
16729
	$conf["clientIndex"];
16730
	#$conf["allConn"],陣列,all web socket client info.
16731
	$conf["allConn"]=array();
16732
	#$conf["func"],字串,要檢查的是否具備權限的函式.
16733
	$conf["func"]="";
16734
	#可省略參數:
16735
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
16736
	#$conf["wsMode"]="true";
16737
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
16738
	#$conf["gpgId"]=gnupgId;
16739
	#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
16740
	#$conf["falseAllowFuncPlus"]=array();
16741
	#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
16742
	#$conf["publicAllowFuncPlus"]=array();
16743
	#參考資料:
16744
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
16745
	#備註:
16746
	#無.
16747
	*/
16748
	public static function checkAuth(&$conf){
16749
 
16750
		#初始化要回傳的結果
16751
		$result=array();
16752
 
16753
		#取得當前執行的函數名稱
16754
		$result["function"]=__FUNCTION__;
16755
 
16756
		#涵式說明:
16757
		#判斷當前環境為web還是cmd
16758
		#回傳結果:
16759
		#$result,"web"或"cmd"
16760
		if(csInformation::getEnv()==="web"){
16761
 
16762
			#設置執行失敗
16763
			$result["status"]="false";
16764
 
16765
			#設置執行錯誤訊息
16766
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
16767
 
16768
			#回傳結果
16769
			return $result;
16770
 
16771
			}#if end
16772
 
16773
		#取得參數
16774
		$result["argu"]=$conf;
16775
 
16776
		#如果 $conf 不為陣列
16777
		if(gettype($conf)!="array"){
16778
 
16779
			#設置執行失敗
16780
			$result["status"]="false";
16781
 
16782
			#設置執行錯誤訊息
16783
			$result["error"][]="\$conf變數須為陣列形態";
16784
 
16785
			#如果傳入的參數為 null
16786
			if($conf==null){
16787
 
16788
				#設置執行錯誤訊息
16789
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
16790
 
16791
				}#if end
16792
 
16793
			#回傳結果
16794
			return $result;
16795
 
16796
			}#if end
16797
 
16798
		#檢查參數
16799
		#函式說明:
16800
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
16801
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16802
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
16803
		#$result["function"],當前執行的函式名稱.
16804
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
16805
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
16806
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
16807
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
16808
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
16809
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
16810
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
16811
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
16812
		#必填寫的參數:
16813
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
16814
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
16815
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
16816
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn","func");
16817
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
16818
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array","string");
16819
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
16820
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
16821
		#可以省略的參數:
16822
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
16823
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
16824
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
16825
		#$conf["canNotBeEmpty"]=array();
16826
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
16827
		#$conf["canBeEmpty"]=array();
16828
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
16829
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
16830
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
16831
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId","falseAllowFuncPlus","publicAllowFuncPlus");
16832
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
16833
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","array","array");
16834
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
16835
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId,array(),array());
16836
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
16837
		#$conf["arrayCountEqualCheck"][]=array();
16838
		#參考資料來源:
16839
		#array_keys=>http://php.net/manual/en/function.array-keys.php
16840
		#建議:
16841
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
16842
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
16843
		unset($conf["variableCheck::checkArguments"]);
16844
 
16845
		#如果檢查參數失敗
16846
		if($checkArguments["status"]==="false"){
16847
 
16848
			#設置執行失敗
16849
			$result["status"]="false";
16850
 
16851
			#設置執行錯誤訊息
16852
			$result["error"]=$checkArguments;
16853
 
16854
			#回傳結果
16855
			return $result;
16856
 
16857
			}#if end
16858
 
16859
		#如果檢查參數不通過
16860
		if($checkArguments["passed"]==="false"){
16861
 
16862
			#設置執行失敗
16863
			$result["status"]="false";
16864
 
16865
			#設置執行錯誤訊息
16866
			$result["error"]=$checkArguments;
16867
 
16868
			#回傳結果
16869
			return $result;
16870
 
16871
			}#if end
16872
 
16873
		#取得收到的訊息
16874
		$receivedData=$conf["data"];
16875
 
16876
		#取得 server 的 socket
16877
		$serverSocket=$conf["serverSock"];
16878
 
16879
		#取得 client 的 socket
16880
		$clientSocket=$conf["clientSock"];
16881
 
16882
		#取得 client 的資訊
16883
		$clientInfo=$conf["clientInfo"];
16884
 
16885
		#取得 client 的索引
16886
		$clientIndex=$conf["clientIndex"];
16887
 
16888
		#取得 all clients 的資訊
16889
		$allConn=&$conf["allConn"];
16890
 
16891
		/* 檢查權限不用看收到的訊息
16892
 
16893
		#hex2bin
16894
		#函式說明:
16895
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
16896
		#回傳結果:
16897
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
16898
		#$result["function"],當前執行的函數名稱.
16899
		#$result["content"],加密後的結果.
16900
		#$result["error"],錯誤訊息陣列.
16901
		#$result["argu"],使用的參數.
16902
		#必填參數:
16903
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
16904
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
16905
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
16906
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
16907
		#可省略參數:
16908
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
16909
		#$conf["sha1Raw"]="false";
16910
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
16911
		#$conf["p_hash"]="";
16912
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
16913
		#$conf["keyForAes256"]="";
16914
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
16915
		#$conf["aes256Encode"]="";
16916
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
16917
		#$conf["qbpwcfDecode"]="false";
16918
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
16919
		#$conf["gpgDecrypt"]="false";
16920
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
16921
		#$conf["gpgId"]="";
16922
		#參考資料:
16923
		#sha1=>http://php.net/manual/en/function.sha1.php
16924
		#md5=>http://php.net/manual/en/function.md5.php
16925
		#password_hash=>http://php.net/manual/en/function.password-hash.php
16926
		#password_verify=>http://php.net/manual/en/function.password-verify.php
16927
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
16928
		#備註:
16929
		#無.
16930
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
16931
		unset($conf["authenticate::enCodeStr"]);
16932
 
16933
		#如果執行失敗
16934
		if($enCodeStr["status"]==="false"){
16935
 
16936
			#設置執行異常
16937
			$result["status"]="false";
16938
 
16939
			#設置執行錯誤
16940
			$result["error"]=$enCodeStr;
16941
 
16942
			#回傳結果
16943
			return $result;
16944
 
16945
			}#if end
16946
 
16947
		#取得hex2bin後的字串
16948
		$receivedData=$enCodeStr["content"];
16949
 
16950
		#gpg decrypt
16951
		#函式說明:
16952
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
16953
		#回傳結果:
16954
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
16955
		#$result["function"],當前執行的函數名稱.
16956
		#$result["content"],加密後的結果.
16957
		#$result["error"],錯誤訊息陣列.
16958
		#$result["argu"],使用的參數.
16959
		#必填參數:
16960
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
16961
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
16962
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
16963
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
16964
		#可省略參數:
16965
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
16966
		#$conf["sha1Raw"]="false";
16967
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
16968
		#$conf["p_hash"]="";
16969
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
16970
		#$conf["keyForAes256"]="";
16971
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
16972
		#$conf["aes256Encode"]="";
16973
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
16974
		#$conf["qbpwcfDecode"]="false";
16975
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
16976
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
16977
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
16978
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
16979
		#參考資料:
16980
		#sha1=>http://php.net/manual/en/function.sha1.php
16981
		#md5=>http://php.net/manual/en/function.md5.php
16982
		#password_hash=>http://php.net/manual/en/function.password-hash.php
16983
		#password_verify=>http://php.net/manual/en/function.password-verify.php
16984
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
16985
		#備註:
16986
		#無.
16987
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
16988
		unset($conf["authenticate::enCodeStr"]);
16989
 
16990
		#如果執行失敗
16991
		if($enCodeStr["status"]==="false"){
16992
 
16993
			#設置執行異常
16994
			$result["status"]="false";
16995
 
16996
			#設置執行錯誤
16997
			$result["error"]=$enCodeStr;
16998
 
16999
			#回傳結果
17000
			return $result;
17001
 
17002
			}#if end
17003
 
17004
		#取得解密後的字串
17005
		$receivedData=$enCodeStr["content"];
17006
 
17007
		#json_decode
17008
		$receivedData=json_decode($receivedData);
17009
 
17010
		*/
17011
 
17012
		#取得認證狀態
17013
		$authStatus=$conf["clientInfo"][$conf["clientIndex"]]["auth"];
17014
 
17015
		#判斷 authStatus
17016
		switch($authStatus){
17017
 
17018
			#如果未經過認證
17019
			case "false":
17020
 
17021
				#預設可以使用的功能只有"auth"跟"checkAuth"
17022
				$authFunc=array("auth","checkAuth");
17023
 
17024
				#如果有 $conf["falseAllowFuncPlus"]
17025
				if(count($conf["falseAllowFuncPlus"])>0){
17026
 
17027
					#合併 array
17028
					#函式說明:
17029
					#將多個一維陣列串聯起來,key從0開始排序.
17030
					#回傳的結果:
17031
					#$result["status"],"true"表執行正常,"false"代表執行不正常.
17032
					#$result["error"],錯誤訊息陣列.
17033
					#$result["function"],當前執行的函數.
17034
					#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17035
					#$result["content"],合併好的一維陣列.
17036
					#必填參數
17037
					#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
17038
					$conf["arrays::mergeArray"]["inputArray"]=array($authFunc,$conf["falseAllowFuncPlus"]);
17039
					#可省略參數:
17040
					#$conf["allowRepeat"],字串,預設為"true",允許重複的結果;若為"false"則不會出現重複的元素內容.
17041
					$conf["arrays::mergeArray"]["allowRepeat"]="false";
17042
					#$conf["looseDiff"],字串,預設為"false",代表要嚴謹判斷為有相異,例如陣列中元素的key順序不同(整數)就代表有相異;反之為"true",例如陣列中元素的key順序不同(非整數),但value有相同,則視為無相異.
17043
					$conf["arrays::mergeArray"]["looseDiff"]="true";
17044
					#參考資料:
17045
					#無.
17046
					#備註:
17047
					#無.
17048
					$mergeArray=arrays::mergeArray($conf["arrays::mergeArray"]);
17049
					unset($conf["arrays::mergeArray"]);
17050
 
17051
					#如果執行失敗
17052
					if($mergeArray["status"]==="false"){
17053
 
17054
						#設置執行異常
17055
						$result["status"]="false";
17056
 
17057
						#設置執行錯誤
17058
						$result["error"]=$mergeArray;
17059
 
17060
						#回傳結果
17061
						return $result;
17062
 
17063
						}#if end
17064
 
17065
					#取得合併好允許使用的清單
17066
					$authFunc=$mergeArray["content"];
17067
 
17068
					}#if end
17069
 
17070
				#如果沒有權限使用 
17071
				if(!in_array($conf["func"],$authFunc)){
17072
 
17073
					#設置執行異常
17074
					$result["status"]="false";
17075
 
17076
					#設置執行錯誤
17077
					$result["error"][]="no ".$conf["func"]." permission";
17078
 
17079
					#回傳結果
17080
					return $result;
17081
 
17082
					}#if end
17083
 
17084
				#結束 switch
17085
				break;
17086
 
17087
			#如果是"root"賬戶,代表系統管理者,擁有所有權限.
17088
			case "root":
17089
 
17090
				#預設可以使用的功能只有"*",代表所有功能都能用.
17091
				$authFunc=array("*");
17092
 
17093
				/*	允許使用所有函式
17094
 
17095
				#如果沒有權限使用 
17096
				if(!in_array($conf["func"],$authFunc)){
17097
 
17098
					#設置執行異常
17099
					$result["status"]="false";
17100
 
17101
					#設置執行錯誤
17102
					$result["error"][]="no ".$conf["func"]." permission";
17103
 
17104
					#回傳結果
17105
					return $result;
17106
 
17107
					}#if end
17108
 
17109
				*/
17110
 
17111
				#結束 switch
17112
				break;
17113
 
17114
			#如果是"public"賬戶,代表具備一般使用權限的公用使用者.
17115
			case "public":
17116
 
17117
				#預設可以使用的功能只有"*",代表所有功能都能用.
17118
				$authFunc=array("auth","checkAuth","basic");
17119
 
17120
				#如果有 publicAllowFuncPlus
17121
				if(count($conf["publicAllowFuncPlus"])>0){
17122
 
17123
					#合併 array
17124
					#函式說明:
17125
					#將多個一維陣列串聯起來,key從0開始排序.
17126
					#回傳的結果:
17127
					#$result["status"],"true"表執行正常,"false"代表執行不正常.
17128
					#$result["error"],錯誤訊息陣列.
17129
					#$result["function"],當前執行的函數.
17130
					#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17131
					#$result["content"],合併好的一維陣列.
17132
					#必填參數
17133
					#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
17134
					$conf["arrays::mergeArray"]["inputArray"]=array($authFunc,$conf["publicAllowFuncPlus"]);
17135
					#可省略參數:
17136
					#$conf["allowRepeat"],字串,預設為"true",允許重複的結果;若為"false"則不會出現重複的元素內容.
17137
					$conf["arrays::mergeArray"]["allowRepeat"]="false";
17138
					#$conf["looseDiff"],字串,預設為"false",代表要嚴謹判斷為有相異,例如陣列中元素的key順序不同(整數)就代表有相異;反之為"true",例如陣列中元素的key順序不同(非整數),但value有相同,則視為無相異.
17139
					$conf["arrays::mergeArray"]["looseDiff"]="true";
17140
					#參考資料:
17141
					#無.
17142
					#備註:
17143
					#無.
17144
					$mergeArray=arrays::mergeArray($conf["arrays::mergeArray"]);
17145
					unset($conf["arrays::mergeArray"]);
17146
 
17147
					#如果執行失敗
17148
					if($mergeArray["status"]==="false"){
17149
 
17150
						#設置執行異常
17151
						$result["status"]="false";
17152
 
17153
						#設置執行錯誤
17154
						$result["error"]=$mergeArray;
17155
 
17156
						#回傳結果
17157
						return $result;
17158
 
17159
						}#if end
17160
 
17161
					#取得合併好允許使用的清單
17162
					$authFunc=$mergeArray["content"];
17163
 
17164
					}#if end
17165
 
17166
				#如果沒有權限使用 
17167
				if(!in_array($conf["func"],$authFunc)){
17168
 
17169
					#設置執行異常
17170
					$result["status"]="false";
17171
 
17172
					#設置執行錯誤
17173
					$result["error"][]="no ".$conf["func"]." permission";
17174
 
17175
					#回傳結果
17176
					return $result;
17177
 
17178
					}#if end
17179
 
17180
				break;
17181
 
17182
			#其他結果
17183
			default:
17184
 
17185
				#依照指定的資料來源進行權限與可用功能的檢查
17186
				#...
17187
 
17188
				#設置執行異常
17189
				$result["status"]="false";
17190
 
17191
				#設置執行錯誤
17192
				$result["error"][]="not supported authStatus(".$authStatus.")";
17193
 
17194
				#回傳結果
17195
				return $result;
17196
 
17197
			}#switch end
17198
 
17199
			#設置執行正常
17200
			$result["status"]="true";
17201
 
17202
			#回傳結果
17203
			return $result;
17204
 
17205
		}#function checkAuth end
17206
 
17207
	/*
17208
	#函式說明:
17209
	#提供webSock::nativeSocketTcpIpServer用於接受"auth:"開頭的訊息進行認證使用者的功能.
17210
	#回傳結果:
17211
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
17212
	#$result["error"],執行不正常結束的錯訊息陣列.
17213
	#$result["argu"],陣列,使用的參數.
17214
	#必填參數:
17215
	#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
17216
	$conf["data"]="";
17217
	#$conf["serverSock"],resource,web socket server socket
17218
	$conf["serverSock"]=$resource;
17219
	#$conf["clientSock"],$resource,web socket client socket
17220
	$conf["clientSock"]=$resource;
17221
	#$conf["clientInfo"],陣列,web socket client info.
17222
	$conf["clientInfo"]=array();
17223
	#$conf["clientIndex"],整數.web socket client index.
17224
	$conf["clientIndex"];
17225
	#$conf["allConn"],陣列,all web socket client info.
17226
	$conf["allConn"]=array();
17227
	#可省略參數:
17228
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
17229
	#$conf["wsMode"]="true";
17230
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
17231
	#$conf["gpgId"]=gnupgId;
17232
	#參考資料:
17233
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
17234
	#備註:
17235
	#無.
17236
	*/
17237
	public static function auth(&$conf){
17238
 
17239
		#初始化要回傳的結果
17240
		$result=array();
17241
 
17242
		#取得當前執行的函數名稱
17243
		$result["function"]=__FUNCTION__;
17244
 
17245
		#涵式說明:
17246
		#判斷當前環境為web還是cmd
17247
		#回傳結果:
17248
		#$result,"web"或"cmd"
17249
		if(csInformation::getEnv()==="web"){
17250
 
17251
			#設置執行失敗
17252
			$result["status"]="false";
17253
 
17254
			#設置執行錯誤訊息
17255
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
17256
 
17257
			#回傳結果
17258
			return $result;
17259
 
17260
			}#if end
17261
 
17262
		#取得參數
17263
		$result["argu"]=$conf;
17264
 
17265
		#如果 $conf 不為陣列
17266
		if(gettype($conf)!="array"){
17267
 
17268
			#設置執行失敗
17269
			$result["status"]="false";
17270
 
17271
			#設置執行錯誤訊息
17272
			$result["error"][]="\$conf變數須為陣列形態";
17273
 
17274
			#如果傳入的參數為 null
17275
			if($conf==null){
17276
 
17277
				#設置執行錯誤訊息
17278
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
17279
 
17280
				}#if end
17281
 
17282
			#回傳結果
17283
			return $result;
17284
 
17285
			}#if end
17286
 
17287
		#檢查參數
17288
		#函式說明:
17289
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
17290
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17291
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
17292
		#$result["function"],當前執行的函式名稱.
17293
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
17294
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
17295
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
17296
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
17297
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
17298
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17299
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
17300
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
17301
		#必填寫的參數:
17302
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
17303
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
17304
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
17305
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
17306
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
17307
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
17308
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
17309
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
17310
		#可以省略的參數:
17311
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
17312
		#$conf["canBeEmptyString"]="false";
17313
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
17314
		#$conf["canNotBeEmpty"]=array();
17315
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
17316
		#$conf["canBeEmpty"]=array();
17317
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
17318
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
17319
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
17320
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
17321
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
17322
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
17323
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
17324
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
17325
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
17326
		#$conf["arrayCountEqualCheck"][]=array();
17327
		#參考資料來源:
17328
		#array_keys=>http://php.net/manual/en/function.array-keys.php
17329
		#建議:
17330
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
17331
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
17332
		unset($conf["variableCheck::checkArguments"]);
17333
 
17334
		#如果檢查參數失敗
17335
		if($checkArguments["status"]==="false"){
17336
 
17337
			#設置執行失敗
17338
			$result["status"]="false";
17339
 
17340
			#設置執行錯誤訊息
17341
			$result["error"]=$checkArguments;
17342
 
17343
			#回傳結果
17344
			return $result;
17345
 
17346
			}#if end
17347
 
17348
		#如果檢查參數不通過
17349
		if($checkArguments["passed"]==="false"){
17350
 
17351
			#設置執行失敗
17352
			$result["status"]="false";
17353
 
17354
			#設置執行錯誤訊息
17355
			$result["error"]=$checkArguments;
17356
 
17357
			#回傳結果
17358
			return $result;
17359
 
17360
			}#if end
17361
 
17362
		#取得收到的訊息
17363
		$receivedData=$conf["data"];
17364
 
17365
		#取得 server 的 socket
17366
		$serverSocket=$conf["serverSock"];
17367
 
17368
		#取得 client 的 socket
17369
		$clientSocket=$conf["clientSock"];
17370
 
17371
		#取得 client 的資訊
17372
		$clientInfo=$conf["clientInfo"];
17373
 
17374
		#取得 client 的索引
17375
		$clientIndex=$conf["clientIndex"];
17376
 
17377
		#取得認證狀態
17378
		$authStatus=&$conf["clientInfo"][$conf["clientIndex"]]["auth"];
17379
 
17380
		#取得 all clients 的資訊
17381
		$allConn=&$conf["allConn"];
17382
 
17383
		#hex2bin
17384
		#函式說明:
17385
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
17386
		#回傳結果:
17387
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17388
		#$result["function"],當前執行的函數名稱.
17389
		#$result["content"],加密後的結果.
17390
		#$result["error"],錯誤訊息陣列.
17391
		#$result["argu"],使用的參數.
17392
		#必填參數:
17393
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
17394
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
17395
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
17396
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
17397
		#可省略參數:
17398
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
17399
		#$conf["sha1Raw"]="false";
17400
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
17401
		#$conf["p_hash"]="";
17402
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
17403
		#$conf["keyForAes256"]="";
17404
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
17405
		#$conf["aes256Encode"]="";
17406
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
17407
		#$conf["qbpwcfDecode"]="false";
17408
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
17409
		#$conf["gpgDecrypt"]="false";
17410
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
17411
		#$conf["gpgId"]="";
17412
		#參考資料:
17413
		#sha1=>http://php.net/manual/en/function.sha1.php
17414
		#md5=>http://php.net/manual/en/function.md5.php
17415
		#password_hash=>http://php.net/manual/en/function.password-hash.php
17416
		#password_verify=>http://php.net/manual/en/function.password-verify.php
17417
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
17418
		#備註:
17419
		#無.
17420
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
17421
		unset($conf["authenticate::enCodeStr"]);
17422
 
17423
		#如果執行失敗
17424
		if($enCodeStr["status"]==="false"){
17425
 
17426
			#設置執行異常
17427
			$result["status"]="false";
17428
 
17429
			#設置執行錯誤
17430
			$result["error"]=$enCodeStr;
17431
 
17432
			#回傳結果
17433
			return $result;
17434
 
17435
			}#if end
17436
 
17437
		#取得hex2bin後的字串
17438
		$receivedData=$enCodeStr["content"];
17439
 
17440
		#gpg decrypt
17441
		#函式說明:
17442
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
17443
		#回傳結果:
17444
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17445
		#$result["function"],當前執行的函數名稱.
17446
		#$result["content"],加密後的結果.
17447
		#$result["error"],錯誤訊息陣列.
17448
		#$result["argu"],使用的參數.
17449
		#必填參數:
17450
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
17451
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
17452
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
17453
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
17454
		#可省略參數:
17455
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
17456
		#$conf["sha1Raw"]="false";
17457
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
17458
		#$conf["p_hash"]="";
17459
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
17460
		#$conf["keyForAes256"]="";
17461
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
17462
		#$conf["aes256Encode"]="";
17463
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
17464
		#$conf["qbpwcfDecode"]="false";
17465
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
17466
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
17467
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
17468
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
17469
		#參考資料:
17470
		#sha1=>http://php.net/manual/en/function.sha1.php
17471
		#md5=>http://php.net/manual/en/function.md5.php
17472
		#password_hash=>http://php.net/manual/en/function.password-hash.php
17473
		#password_verify=>http://php.net/manual/en/function.password-verify.php
17474
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
17475
		#備註:
17476
		#無.
17477
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
17478
		unset($conf["authenticate::enCodeStr"]);
17479
 
17480
		#如果執行失敗
17481
		if($enCodeStr["status"]==="false"){
17482
 
17483
			#設置執行異常
17484
			$result["status"]="false";
17485
 
17486
			#設置執行錯誤
17487
			$result["error"]=$enCodeStr;
17488
 
17489
			#回傳結果
17490
			return $result;
17491
 
17492
			}#if end
17493
 
17494
		#取得解密後的字串
17495
		$receivedData=$enCodeStr["content"];
17496
 
17497
		#json_decode
17498
		$receivedData=json_decode($receivedData);
17499
 
17500
		#如果decode後的內容不為物件
17501
		if(gettype($receivedData)!=="Object"){
17502
 
17503
			#設置不適用
17504
			$result["status"]="continue";
17505
 
17506
			#回傳結果
17507
			return $result;
17508
 
17509
			}#if end
17510
 
17511
		#檢查物件是否符合格式
17512
		#函式說明:
17513
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
17514
		#回傳結果:
17515
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17516
		#$result["error"],執行不正常結束的錯訊息陣列.
17517
		#$result["simpleError"],簡單表示的錯誤訊息.
17518
		#$result["function"],當前執行的函式名稱.
17519
		#$result["argu"],設置給予的參數.
17520
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
17521
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
17522
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
17523
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
17524
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
17525
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17526
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
17527
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
17528
		#必填參數:
17529
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
17530
		$conf["variableCheck::checkArguments"]["varInput"]=&$receivedData;
17531
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
17532
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
17533
		#可省略參數:
17534
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
17535
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("user","type","secrect");
17536
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
17537
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string");
17538
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
17539
		#$conf["canBeEmptyString"]="false";
17540
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
17541
		#$conf["canNotBeEmpty"]=array();
17542
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
17543
		#$conf["canBeEmpty"]=array();
17544
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
17545
		#$conf["skipableVariableCanNotBeEmpty"]=array();
17546
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
17547
		#$conf["skipableVariableName"]=array();
17548
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
17549
		#$conf["skipableVariableType"]=array();
17550
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
17551
		#$conf["skipableVarDefaultValue"]=array("");
17552
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
17553
		#$conf["disallowAllSkipableVarIsEmpty"]="";
17554
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
17555
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
17556
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
17557
		#$conf["disallowAllSkipableVarNotExist"]="";
17558
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
17559
		#$conf["arrayCountEqualCheck"][]=array();
17560
		#參考資料:
17561
		#array_keys=>http://php.net/manual/en/function.array-keys.php
17562
		#備註:
17563
		#無.
17564
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
17565
		unset($conf["variableCheck::checkArguments"]);
17566
 
17567
		#如果執行異常
17568
		if($checkArguments["status"]==="false"){
17569
 
17570
			#設置異常
17571
			$result["status"]="false";
17572
 
17573
			#設置錯誤訊息
17574
			$result["error"]=$checkArguments;
17575
 
17576
			#回傳結果
17577
			return $result;
17578
 
17579
			}#if end
17580
 
17581
		#如果參數不合法
17582
		if($checkArguments["passed"]==="false"){
17583
 
17584
			#設置不適用
17585
			$result["status"]="continue";
17586
 
17587
			#回傳結果
17588
			return $result;
17589
 
17590
			}#if end
17591
 
17592
		#取得使用者名稱
17593
		$user=$receivedData->user;
17594
 
17595
		#取得密碼或金鑰內容
17596
		$secrect=$receivedData->secrect;
17597
 
17598
		#依照驗證方式
17599
		switch($receivedData->type){
17600
 
17601
			#若是密碼認證
17602
			case "password":
17603
 
17604
				#測試 $user 與 password 的組合是否能夠認證.
17605
				#函式說明:
17606
				#驗證Linux使用者的密碼是否正確.
17607
				#回傳結果:
17608
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17609
				#$result["function"],當前執行的函數名稱.
17610
				#$result["error"],錯誤訊息陣列.
17611
				#$result["warninig"],警告訊息陣列.
17612
				#$result["valid"],是否為存在的使用者且密碼正確.
17613
				#必填參數:
17614
				#$conf["username"],字串,要驗證的使用者名稱.
17615
				$conf["authenticate::validUser"]["username"]=$user;
17616
				#$conf["password"],字串,用於驗證使用者的密碼.
17617
				$conf["authenticate::validUser"]["password"]=$secrect;
17618
				#$conf["fileArgu"],字串,變數__FILE__的內容.
17619
				$conf["authenticate::validUser"]["fileArgu"]=__FILE__;
17620
				#可省略參數:
17621
				#無.
17622
				#參考資料:
17623
				#無.
17624
				#備註:
17625
				#僅能在命令列環境下運行.
17626
				$validUser=authenticate::validUser($conf["authenticate::validUser"]);
17627
				unset($conf["authenticate::validUser"]);
17628
 
17629
				#如果執行異常
17630
				if($validUser["status"]==="false"){
17631
 
17632
					#設置異常
17633
					$result["status"]="false";
17634
 
17635
					#設置錯誤訊息
17636
					$result["error"]=$validUser;
17637
 
17638
					#回傳結果
17639
					return $result;
17640
 
17641
					}#if end
17642
 
17643
				#如果認證失敗
17644
				if($validUser["valid"]==="false"){
17645
 
17646
					#記錄該 client 認證失敗的事件
17647
					$allConn[$clientIndex]["authFailed"][]=array("time"=>time(),"user"=>$user);
17648
 
17649
					#針對每次認證失敗的記錄
17650
					for($i=0;$i<count($allConn[$clientIndex]["authFailed"]);$i++){
17651
 
17652
						#如果有下一個事件
17653
						if(isset($allConn[$clientIndex]["authFailed"][$i+1])){
17654
 
17655
							#如果本次跟下次事件的時間間隔小於60秒
17656
							if($allConn[$clientIndex]["authFailed"][$i+1]["time"] - $allConn[$clientIndex]["authFailed"][$i]["time"] > 60){
17657
 
17658
								#移除本次記錄
17659
								array_shift($allConn[$clientIndex]["authFailed"]);
17660
 
17661
								#新記錄的索引減少了1,因此更新$i
17662
								$i--;
17663
 
17664
								}#if end
17665
 
17666
							}#if end
17667
 
17668
						}#foreach end
17669
 
17670
					#如果總事件次數大於3
17671
					if(count($allConn[$clientIndex]["authFailed"])>3){
17672
 
17673
						#設置異常
17674
						$result["status"]="false";
17675
 
17676
						#設置錯誤訊息
17677
						$result["error"]=$allConn[$clientIndex]["authFailed"];
17678
 
17679
						#回傳結果
17680
						return $result;
17681
 
17682
						}#if end
17683
 
17684
					#設置正常
17685
					$result["status"]="true";
17686
 
17687
					#回傳結果
17688
					return $result;
17689
 
17690
					}#if end
17691
 
17692
				#執行到這邊代表使用者認證通過
17693
 
17694
				#依照 user 取得其所屬 group
17695
				#函式說明:
17696
				#id指令來取得目標賬號的群組資訊
17697
				#回傳結果:
17698
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17699
				#$reuslt["error"],執行不正常結束的錯訊息陣列.
17700
				#$result["function"],當前執行的函式名稱.
17701
				#$result["content"],呼叫完WebService所得回傳結果.
17702
				#$result["content"]["groupId"],群組的id.
17703
				#$result["content"]["belongGroupName"],陣列,隸屬的群組名稱陣列.
17704
				#$result["content"]["belongGroupId"],陣列,隸屬的群組id.
17705
				#必填參數:
17706
				#$conf["user"],字串,要取得群組資訊的目標使用者名稱.
17707
				$conf["authenticate::getUserGroup"]["user"]=$user;
17708
				#可省略參數:
17709
				#無.
17710
				#參考資料:
17711
				#無.
17712
				#備註:
17713
				#無.
17714
				$getUserGroup=authenticate::getUserGroup($conf["authenticate::getUserGroup"]);
17715
				unset($conf["authenticate::getUserGroup"]);
17716
 
17717
				#如果執行異常
17718
				if($getUserGroup["status"]==="false"){
17719
 
17720
					#設置異常
17721
					$result["status"]="false";
17722
 
17723
					#設置錯誤訊息
17724
					$result["error"]=$getUserGroup;
17725
 
17726
					#回傳結果
17727
					return $result;
17728
 
17729
					}#if end
17730
 
17731
				#設置預設的權限為 "false"
17732
				$authStatus="false";
17733
 
17734
				#針對每個取得的群組名稱
17735
				foreach($getUserGroup["content"]["belongGroupName"] as $groupName){
17736
 
17737
					#如果是 root
17738
					if($groupName==="root"){
17739
 
17740
						#設置得到的權限
17741
						$authStatus=$groupName;
17742
 
17743
						#結束 foreach
17744
						break;
17745
 
17746
						}#if end
17747
 
17748
					#反之如果是公開的使用者
17749
					else if($groupName==="public"){
17750
 
17751
						#設置得到的權限
17752
						$authStatus=$groupName;
17753
 
17754
						}#if end
17755
 
17756
					#其他群組名稱
17757
					else{
17758
 
17759
						#跳過
17760
						continue;
17761
 
17762
						}#else end
17763
 
17764
					}#foreach end
17765
 
17766
				#設置正常
17767
				$result["status"]="true";
17768
 
17769
				#回傳結果
17770
				return $result;
17771
 
17772
				#跳出 switch
17773
				break;
17774
 
17775
			#若是金鑰認證
17776
			case "key":
17777
 
17778
				#測試 $user 與 key 的組合是否能夠認證.
17779
				#函式說明:
17780
				#驗證Linux使用者的密碼或ssh private key是否正確.
17781
				#回傳結果:
17782
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17783
				#$result["function"],當前執行的函數名稱.
17784
				#$result["error"],錯誤訊息陣列.
17785
				#$result["warninig"],警告訊息陣列.
17786
				#$result["valid"],是否為存在的使用者且密碼正確.
17787
				#必填參數:
17788
				#$conf["username"],字串,要驗證的使用者名稱.
17789
				$conf["authenticate::validUser"]["username"]=$user;
17790
				#$conf["password"],字串,用於驗證使用者的密碼.
17791
				$conf["authenticate::validUser"]["password"]=$secrect;
17792
				#$conf["fileArgu"],字串,變數__FILE__的內容.
17793
				$conf["authenticate::validUser"]["fileArgu"]=__FILE__;
17794
				#可省略參數:
17795
				#$conf["sshPrivateKey"],字串,"true"代表password為ssh private key的內容;反之預設為密碼,設置為"false".
17796
				$conf["authenticate::validUser"]["sshPrivateKey"]="true";
17797
				#參考資料:
17798
				#無.
17799
				#備註:
17800
				#僅能在命令列環境下運.
17801
				#目前僅支援驗證執行php端的使用者.
17802
				$validUser=authenticate::validUser($conf["authenticate::validUser"]);
17803
				unset($conf["authenticate::validUser"]);
17804
 
17805
				#如果執行異常
17806
				if($validUser["status"]==="false"){
17807
 
17808
					#設置異常
17809
					$result["status"]="false";
17810
 
17811
					#設置錯誤訊息
17812
					$result["error"]=$validUser;
17813
 
17814
					#回傳結果
17815
					return $result;
17816
 
17817
					}#if end
17818
 
17819
				#如果認證失敗
17820
				if($validUser["valid"]==="false"){
17821
 
17822
					#記錄該 client 認證失敗的事件
17823
					$allConn[$clientIndex]["authFailed"][]=array("time"=>time(),"user"=>$user);
17824
 
17825
					#針對每次認證失敗的記錄
17826
					for($i=0;$i<count($allConn[$clientIndex]["authFailed"]);$i++){
17827
 
17828
						#如果有下一個事件
17829
						if(isset($allConn[$clientIndex]["authFailed"][$i+1])){
17830
 
17831
							#如果本次跟下次事件的時間間隔小於60秒
17832
							if($allConn[$clientIndex]["authFailed"][$i+1]["time"] - $allConn[$clientIndex]["authFailed"][$i]["time"] > 60){
17833
 
17834
								#移除本次記錄
17835
								array_shift($allConn[$clientIndex]["authFailed"]);
17836
 
17837
								#新記錄的索引減少了1,因此更新$i
17838
								$i--;
17839
 
17840
								}#if end
17841
 
17842
							}#if end
17843
 
17844
						}#foreach end
17845
 
17846
					#如果總事件次數大於3
17847
					if(count($allConn[$clientIndex]["authFailed"])>3){
17848
 
17849
						#設置異常
17850
						$result["status"]="false";
17851
 
17852
						#設置錯誤訊息
17853
						$result["error"]=$allConn[$clientIndex]["authFailed"];
17854
 
17855
						#回傳結果
17856
						return $result;
17857
 
17858
						}#if end
17859
 
17860
					#設置正常
17861
					$result["status"]="true";
17862
 
17863
					#回傳結果
17864
					return $result;
17865
 
17866
					}#if end
17867
 
17868
				#執行到這邊代表使用者認證通過
17869
 
17870
				#依照 user 取得其所屬 group
17871
				#函式說明:
17872
				#id指令來取得目標賬號的群組資訊
17873
				#回傳結果:
17874
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17875
				#$reuslt["error"],執行不正常結束的錯訊息陣列.
17876
				#$result["function"],當前執行的函式名稱.
17877
				#$result["content"],呼叫完WebService所得回傳結果.
17878
				#$result["content"]["groupId"],群組的id.
17879
				#$result["content"]["belongGroupName"],陣列,隸屬的群組名稱陣列.
17880
				#$result["content"]["belongGroupId"],陣列,隸屬的群組id.
17881
				#必填參數:
17882
				#$conf["user"],字串,要取得群組資訊的目標使用者名稱.
17883
				$conf["authenticate::getUserGroup"]["user"]=$user;
17884
				#可省略參數:
17885
				#無.
17886
				#參考資料:
17887
				#無.
17888
				#備註:
17889
				#無.
17890
				$getUserGroup=authenticate::getUserGroup($conf["authenticate::getUserGroup"]);
17891
				unset($conf["authenticate::getUserGroup"]);
17892
 
17893
				#如果執行異常
17894
				if($getUserGroup["status"]==="false"){
17895
 
17896
					#設置異常
17897
					$result["status"]="false";
17898
 
17899
					#設置錯誤訊息
17900
					$result["error"]=$getUserGroup;
17901
 
17902
					#回傳結果
17903
					return $result;
17904
 
17905
					}#if end
17906
 
17907
				#設置預設的權限為 "false"
17908
				$authStatus="false";
17909
 
17910
				#針對每個取得的群組名稱
17911
				foreach($getUserGroup["content"]["belongGroupName"] as $groupName){
17912
 
17913
					#如果是 root
17914
					if($groupName==="root"){
17915
 
17916
						#設置得到的權限
17917
						$authStatus=$groupName;
17918
 
17919
						#結束 foreach
17920
						break;
17921
 
17922
						}#if end
17923
 
17924
					#反之如果是公開的使用者
17925
					else if($groupName==="public"){
17926
 
17927
						#設置得到的權限
17928
						$authStatus=$groupName;
17929
 
17930
						}#if end
17931
 
17932
					#其他群組名稱
17933
					else{
17934
 
17935
						#跳過
17936
						continue;
17937
 
17938
						}#else end
17939
 
17940
					}#foreach end
17941
 
17942
				#設置正常
17943
				$result["status"]="true";
17944
 
17945
				#回傳結果
17946
				return $result;
17947
 
17948
				#跳出 switch
17949
				break;
17950
 
17951
			#其他類型
17952
			default:
17953
 
17954
				#設置不適用
17955
				$result["status"]="continue";
17956
 
17957
				#回傳結果
17958
				return $result;
17959
 
17960
			}#switch end
17961
 
17962
		#執行到這邊代表異常
17963
 
17964
		#設置異常
17965
		$result["status"]="false";
17966
 
17967
		#回傳結果
17968
		return $result;
17969
 
17970
		}#function auth end
17971
 
17972
	/*
17973
	#函式說明:
17974
	#提供webSock::nativeSocketTcpIpServer使用基本功能(basic).
17975
	#回傳結果:
17976
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
17977
	#$result["error"],執行不正常結束的錯訊息陣列.
17978
	#$result["argu"],陣列,使用的參數.
17979
	#必填參數:
17980
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料.
17981
	$conf["data"]="";
17982
	#$conf["serverSock"],resource,web socket server socket
17983
	$conf["serverSock"]=$resource;
17984
	#$conf["clientSock"],$resource,web socket client socket
17985
	$conf["clientSock"]=$resource;
17986
	#$conf["clientInfo"],陣列,web socket client info.
17987
	$conf["clientInfo"]=array();
17988
	#$conf["clientIndex"],整數.web socket client index.
17989
	$conf["clientIndex"];
17990
	#$conf["allConn"],陣列,all web socket client info.
17991
	$conf["allConn"]=array();
17992
	#可省略參數:
17993
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
17994
	#$conf["wsMode"]="true";
17995
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
17996
	#$conf["gpgId"]=gnupgId;
17997
	#參考資料:
17998
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
17999
	#備註:
18000
	#收到用戶的"id?"訊息,會回傳用戶的id.
18001
	#收到用戶的"ids?"訊息,會回傳非自己的所有用戶id.
18002
	#收到用戶的"talkTo?"訊息,會回傳目前在跟誰談話.
18003
	#收到用戶的"talkTo:client-id"訊息,會建立與id對應的用戶對話,此後傳遞的訊息均會給對方.
18004
	#結束連線的訊息"quit".
18005
	*/
18006
	public static function basic(&$conf){
18007
 
18008
		#初始化要回傳的結果
18009
		$result=array();
18010
 
18011
		#取得當前執行的函數名稱
18012
		$result["function"]=__FUNCTION__;
18013
 
18014
		#涵式說明:
18015
		#判斷當前環境為web還是cmd
18016
		#回傳結果:
18017
		#$result,"web"或"cmd"
18018
		if(csInformation::getEnv()==="web"){
18019
 
18020
			#設置執行失敗
18021
			$result["status"]="false";
18022
 
18023
			#設置執行錯誤訊息
18024
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
18025
 
18026
			#回傳結果
18027
			return $result;
18028
 
18029
			}#if end
18030
 
18031
		#取得參數
18032
		$result["argu"]=$conf;
18033
 
18034
		#如果 $conf 不為陣列
18035
		if(gettype($conf)!="array"){
18036
 
18037
			#設置執行失敗
18038
			$result["status"]="false";
18039
 
18040
			#設置執行錯誤訊息
18041
			$result["error"][]="\$conf變數須為陣列形態";
18042
 
18043
			#如果傳入的參數為 null
18044
			if($conf==null){
18045
 
18046
				#設置執行錯誤訊息
18047
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
18048
 
18049
				}#if end
18050
 
18051
			#回傳結果
18052
			return $result;
18053
 
18054
			}#if end
18055
 
18056
		#檢查參數
18057
		#函式說明:
18058
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
18059
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18060
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
18061
		#$result["function"],當前執行的函式名稱.
18062
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
18063
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
18064
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
18065
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
18066
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
18067
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
18068
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
18069
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
18070
		#必填寫的參數:
18071
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
18072
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
18073
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
18074
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
18075
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
18076
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
18077
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
18078
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
18079
		#可以省略的參數:
18080
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
18081
		#$conf["canBeEmptyString"]="false";
18082
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
18083
		#$conf["canNotBeEmpty"]=array();
18084
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
18085
		#$conf["canBeEmpty"]=array();
18086
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
18087
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
18088
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
18089
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
18090
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
18091
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
18092
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
18093
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
18094
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
18095
		#$conf["arrayCountEqualCheck"][]=array();
18096
		#參考資料來源:
18097
		#array_keys=>http://php.net/manual/en/function.array-keys.php
18098
		#建議:
18099
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
18100
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
18101
		unset($conf["variableCheck::checkArguments"]);
18102
 
18103
		#如果檢查參數失敗
18104
		if($checkArguments["status"]==="false"){
18105
 
18106
			#設置執行失敗
18107
			$result["status"]="false";
18108
 
18109
			#設置執行錯誤訊息
18110
			$result["error"]=$checkArguments;
18111
 
18112
			#回傳結果
18113
			return $result;
18114
 
18115
			}#if end
18116
 
18117
		#如果檢查參數不通過
18118
		if($checkArguments["passed"]==="false"){
18119
 
18120
			#設置執行失敗
18121
			$result["status"]="false";
18122
 
18123
			#設置執行錯誤訊息
18124
			$result["error"]=$checkArguments;
18125
 
18126
			#回傳結果
18127
			return $result;
18128
 
18129
			}#if end
18130
 
18131
		#取得收到的訊息
18132
		$receivedData=$conf["data"];
18133
 
18134
		#取得 server 的 socket
18135
		$serverSocket=$conf["serverSock"];
18136
 
18137
		#取得 client 的 socket
18138
		$clientSocket=$conf["clientSock"];
18139
 
18140
		#取得 client 的資訊
18141
		$clientInfo=$conf["clientInfo"];
18142
 
18143
		#取得 client 的索引
18144
		$clientIndex=$conf["clientIndex"];
18145
 
18146
		#取得 all clients 的資訊
18147
		$allConn=&$conf["allConn"];
18148
 
18149
		#hex2bin
18150
		#函式說明:
18151
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
18152
		#回傳結果:
18153
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
18154
		#$result["function"],當前執行的函數名稱.
18155
		#$result["content"],加密後的結果.
18156
		#$result["error"],錯誤訊息陣列.
18157
		#$result["argu"],使用的參數.
18158
		#必填參數:
18159
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
18160
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
18161
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
18162
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
18163
		#可省略參數:
18164
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
18165
		#$conf["sha1Raw"]="false";
18166
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
18167
		#$conf["p_hash"]="";
18168
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
18169
		#$conf["keyForAes256"]="";
18170
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
18171
		#$conf["aes256Encode"]="";
18172
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
18173
		#$conf["qbpwcfDecode"]="false";
18174
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
18175
		#$conf["gpgDecrypt"]="false";
18176
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
18177
		#$conf["gpgId"]="";
18178
		#參考資料:
18179
		#sha1=>http://php.net/manual/en/function.sha1.php
18180
		#md5=>http://php.net/manual/en/function.md5.php
18181
		#password_hash=>http://php.net/manual/en/function.password-hash.php
18182
		#password_verify=>http://php.net/manual/en/function.password-verify.php
18183
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
18184
		#備註:
18185
		#無.
18186
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
18187
		unset($conf["authenticate::enCodeStr"]);
18188
 
18189
		#如果執行失敗
18190
		if($enCodeStr["status"]==="false"){
18191
 
18192
			#設置執行異常
18193
			$result["status"]="false";
18194
 
18195
			#設置執行錯誤
18196
			$result["error"]=$enCodeStr;
18197
 
18198
			#回傳結果
18199
			return $result;
18200
 
18201
			}#if end
18202
 
18203
		#取得hex2bin後的字串
18204
		$receivedData=$enCodeStr["content"];
18205
 
18206
		#gpg decrypt
18207
		#函式說明:
18208
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
18209
		#回傳結果:
18210
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
18211
		#$result["function"],當前執行的函數名稱.
18212
		#$result["content"],加密後的結果.
18213
		#$result["error"],錯誤訊息陣列.
18214
		#$result["argu"],使用的參數.
18215
		#必填參數:
18216
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
18217
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
18218
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
18219
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
18220
		#可省略參數:
18221
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
18222
		#$conf["sha1Raw"]="false";
18223
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
18224
		#$conf["p_hash"]="";
18225
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
18226
		#$conf["keyForAes256"]="";
18227
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
18228
		#$conf["aes256Encode"]="";
18229
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
18230
		#$conf["qbpwcfDecode"]="false";
18231
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
18232
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
18233
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
18234
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
18235
		#參考資料:
18236
		#sha1=>http://php.net/manual/en/function.sha1.php
18237
		#md5=>http://php.net/manual/en/function.md5.php
18238
		#password_hash=>http://php.net/manual/en/function.password-hash.php
18239
		#password_verify=>http://php.net/manual/en/function.password-verify.php
18240
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
18241
		#備註:
18242
		#無.
18243
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
18244
		unset($conf["authenticate::enCodeStr"]);
18245
 
18246
		#如果執行失敗
18247
		if($enCodeStr["status"]==="false"){
18248
 
18249
			#設置執行異常
18250
			$result["status"]="false";
18251
 
18252
			#設置執行錯誤
18253
			$result["error"]=$enCodeStr;
18254
 
18255
			#回傳結果
18256
			return $result;
18257
 
18258
			}#if end
18259
 
18260
		#取得解密後的字串
18261
		$receivedData=$enCodeStr["content"];
18262
 
18263
		#json_decode
18264
		$receivedData=json_decode($receivedData);
18265
 
18266
		#如果收到的是 id?
18267
		if($receivedData==="id?"){
18268
 
18269
			#如果尚未認證
18270
			if($connections[$conIndex]["auth"]==="false"){
18271
 
18272
				#設置要回傳的訊息
18273
				$talkback="permission denied";
18274
 
18275
				}#if end
18276
 
18277
			else{
18278
 
18279
				#設置要回傳的訊息
18280
				$talkback=$connections[$conIndex]["id"];
18281
 
18282
				}#else end
18283
 
18284
			#debug
18285
			#var_dump(__LINE__,$talkback);
18286
 
18287
			#json encode 要回傳的訊息
18288
			$talkback=json_encode($talkback);
18289
 
18290
			#debug
18291
			#var_dump(__LINE__,$talkback);
18292
 
18293
			#如果是 ws 模式
18294
			if($conf["wsMode"]==="true"){
18295
 
18296
				#如果已經 handshake 過
18297
				if($connections[$conIndex]["handshaked"]==="true"){
18298
 
18299
					#如果要 unmask	
18300
					if($connections[$conIndex]["unmask"]==="true"){
18301
 
18302
						#函式說明:
18303
						#加密 handshake 後要傳送的訊息 
18304
						#回傳結果:
18305
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18306
						#$result["error"],執行不正常結束的錯訊息陣列.
18307
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18308
						#$result["argu"],陣列,使用的參數.
18309
						#必填參數:
18310
						#$conf["text"],字串,要加密的訊息.
18311
						$conf["webSock::encode"]["text"]=$talkback; 
18312
						#可省略參數:
18313
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18314
						#$conf["payloadIsBin"]="false";
18315
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18316
						#$conf["ping"]="false";
18317
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18318
						#$conf["pong"]="false";
18319
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18320
						#$conf["frames"]=array();
18321
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18322
						#$conf["mask"]="false";
18323
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18324
						#$conf["debug"]="false";
18325
						#參考資料:
18326
						#無.
18327
						#備註:
18328
						#目前$conf["text"]長度超過125會出錯.
18329
						$talkback=webSock::encode($conf["webSock::encode"]);
18330
						unset($conf["webSock::encode"]);
18331
 
18332
						#如果執行失敗
18333
						if($talkback["status"]==="false"){
18334
 
18335
							#印出結果
18336
							var_dump($talkback);
18337
 
18338
							#結束執行
18339
							exit;
18340
 
18341
							}#if end
18342
 
18343
						#debug
18344
						#var_dump(__LINE__,$talkback);
18345
 
18346
						}#if end
18347
 
18348
					}#if end
18349
 
18350
				}#if end
18351
 
18352
			#反之不為 web socket 訊息
18353
			else{
18354
 
18355
				#儲存成只有一個訊息
18356
				$talkback["content"][]=$talkback;
18357
 
18358
				}#else
18359
 
18360
			#針對每個訊息的分段
18361
			foreach($talkback["content"] as $msg){
18362
 
18363
				#debug
18364
				var_dump(__LINE__,$msg);
18365
 
18366
				#回傳訊息
18367
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18368
 
18369
				#debug
18370
				var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18371
 
18372
				}#foreach end
18373
 
18374
			#設置執行正常
18375
			$result["status"]="true";
18376
 
18377
			#回傳結果
18378
			return $result;
18379
 
18380
			}#if end
18381
 
18382
		#反之如果收到的是 "quit"
18383
		else if($receivedData==="quit"){
18384
 
18385
			#設置要回傳的訊息
18386
			$talkback="結束與 server 的連線";
18387
 
18388
			#json encode 要回傳的訊息
18389
			$talkback=json_encode($talkback).PHP_EOL;
18390
 
18391
			#如果是 ws 模式
18392
			if($conf["wsMode"]==="true"){
18393
 
18394
				#如果已經 handshake 過
18395
				if($connections[$conIndex]["handshaked"]==="true"){
18396
 
18397
					#如果要 unmask	
18398
					if($connections[$conIndex]["unmask"]==="true"){
18399
 
18400
						#函式說明:
18401
						#加密 handshake 後要傳送的訊息 
18402
						#回傳結果:
18403
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18404
						#$result["error"],執行不正常結束的錯訊息陣列.
18405
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18406
						#$result["argu"],陣列,使用的參數.
18407
						#必填參數:
18408
						#$conf["text"],字串,要加密的訊息.
18409
						$conf["webSock::encode"]["text"]=$talkback; 
18410
						#可省略參數:
18411
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18412
						#$conf["payloadIsBin"]="false";
18413
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18414
						#$conf["ping"]="false";
18415
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18416
						#$conf["pong"]="false";
18417
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18418
						#$conf["frames"]=array();
18419
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18420
						#$conf["mask"]="false";
18421
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18422
						#$conf["debug"]="false";
18423
						#參考資料:
18424
						#無.
18425
						#備註:
18426
						#目前$conf["text"]長度超過125會出錯.
18427
						$talkback=webSock::encode($conf["webSock::encode"]);
18428
						unset($conf["webSock::encode"]);
18429
 
18430
						#如果執行失敗
18431
						if($talkback["status"]==="false"){
18432
 
18433
							#印出結果
18434
							var_dump($talkback);
18435
 
18436
							#結束執行
18437
							exit;
18438
 
18439
							}#if end
18440
 
18441
						#debug
18442
						#var_dump(__LINE__,$talkback);
18443
 
18444
						}#if end
18445
 
18446
					}#if end
18447
 
18448
				}#if end
18449
 
18450
			#反之不為 web socket 訊息
18451
			else{
18452
 
18453
				#儲存成只有一個訊息
18454
				$talkback["content"][]=$talkback;
18455
 
18456
				}#else
18457
 
18458
			#針對每個訊息的分段
18459
			foreach($talkback["content"] as $msg){
18460
 
18461
				#回傳訊息
18462
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
18463
 
18464
				#debug
18465
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18466
 
18467
				}#foreach end
18468
 
18469
			#關閉被 client 的連線	
18470
			socket_close($con["connect"]);
18471
 
18472
			#清理連線的陣列
18473
			unset($connections[$conIndex]);
18474
 
18475
			#設置執行正常
18476
			$result["status"]="true";
18477
 
18478
			#回傳結果
18479
			return $result;
18480
 
18481
			}#if end
18482
 
18483
		#反之是如果收到的是 ids?
18484
		else if($receivedData === 'ids?'){
18485
 
18486
			#如果尚未認證
18487
			if($connections[$conIndex]["auth"]==="false"){
18488
 
18489
				#設置要回傳的訊息
18490
				$talkback=json_encode("permission denied");
18491
 
18492
				}#if end
18493
 
18494
			#反之
18495
			else{
18496
 
18497
				#設置要回傳的訊息
18498
				$talkback=array();
18499
 
18500
				#針對每個連線
18501
				foreach($connections as $conIndex_ids => $con_ids){
18502
 
18503
					#如果不是自己
18504
					if($con_ids["connect"]!==$connections[$conIndex]["connect"]){
18505
 
18506
						#記錄其他人的id
18507
						$talkback[]=$con_ids["id"];
18508
 
18509
						}#if end
18510
 
18511
					}#foreach end
18512
 
18513
				#json encode要回傳的id陣列
18514
				$talkback=json_encode($talkback);
18515
 
18516
				}#else end
18517
 
18518
			#如果是 ws 模式
18519
			if($conf["wsMode"]==="true"){
18520
 
18521
				#如果已經 handshake 過
18522
				if($connections[$conIndex]["handshaked"]==="true"){
18523
 
18524
					#如果要 unmask
18525
					if($connections[$conIndex]["unmask"]==="true"){
18526
 
18527
						#函式說明:
18528
						#加密 handshake 後要傳送的訊息 
18529
						#回傳結果:
18530
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18531
						#$result["error"],執行不正常結束的錯訊息陣列.
18532
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18533
						#$result["argu"],陣列,使用的參數.
18534
						#必填參數:
18535
						#$conf["text"],字串,要加密的訊息.
18536
						$conf["webSock::encode"]["text"]=$talkback; 
18537
						#可省略參數:
18538
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18539
						#$conf["payloadIsBin"]="false";
18540
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18541
						#$conf["ping"]="false";
18542
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18543
						#$conf["pong"]="false";
18544
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18545
						#$conf["frames"]=array();
18546
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18547
						#$conf["mask"]="false";
18548
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18549
						#$conf["debug"]="false";
18550
						#參考資料:
18551
						#無.
18552
						#備註:
18553
						#目前$conf["text"]長度超過125會出錯.
18554
						$talkback=webSock::encode($conf["webSock::encode"]);
18555
						unset($conf["webSock::encode"]);
18556
 
18557
						#如果執行失敗
18558
						if($talkback["status"]==="false"){
18559
 
18560
							#印出結果
18561
							var_dump($talkback);
18562
 
18563
							#結束執行
18564
							exit;
18565
 
18566
							}#if end
18567
 
18568
						#debug
18569
						#var_dump(__LINE__,$talkback);
18570
 
18571
						}#if end
18572
 
18573
					}#if end
18574
 
18575
				}#if end
18576
 
18577
			#反之不為 web socket 訊息
18578
			else{
18579
 
18580
				#儲存成只有一個訊息
18581
				$talkback["content"][]=$talkback;
18582
 
18583
				}#else
18584
 
18585
			#針對每個訊息的分段
18586
			foreach($talkback["content"] as $msg){
18587
 
18588
				#回傳訊息
18589
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18590
 
18591
				#debug
18592
				var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18593
 
18594
				}#foreach end
18595
 
18596
			#設置執行正常
18597
			$result["status"]="true";
18598
 
18599
			#回傳結果
18600
			return $result;
18601
 
18602
			}#if end
18603
 
18604
		#反之如果收到 "talkTo?"
18605
		else if($receivedData==="talkTo?"){
18606
 
18607
			#如果尚未認證
18608
			if($connections[$conIndex]["auth"]==="false"){
18609
 
18610
				#設置要回傳的訊息
18611
				$talkback=json_encode("permission denied");
18612
 
18613
				}#if end
18614
 
18615
			#反之
18616
			else{
18617
 
18618
				#初始化要講話的id陣列
18619
				$talkback=array();
18620
 
18621
				#有幾個要講話的人就執行幾次
18622
				foreach($connections[$conIndex]["talkTo"] as $to){
18623
 
18624
					#串街要講話的人
18625
					$talkback[]=$to;
18626
 
18627
					}#foreach end
18628
 
18629
				#設置要回傳的訊息
18630
				$talkback=json_encode($talkback).PHP_EOL;
18631
 
18632
				}#else end
18633
 
18634
			#如果是 ws 模式
18635
			if($conf["wsMode"]==="true"){
18636
 
18637
				#如果已經 handshake 過
18638
				if($connections[$conIndex]["handshaked"]==="true"){
18639
 
18640
					#如果要 unmask	
18641
					if($connections[$conIndex]["unmask"]==="true"){
18642
 
18643
						#函式說明:
18644
						#加密 handshake 後要傳送的訊息 
18645
						#回傳結果:
18646
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18647
						#$result["error"],執行不正常結束的錯訊息陣列.
18648
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18649
						#$result["argu"],陣列,使用的參數.
18650
						#必填參數:
18651
						#$conf["text"],字串,要加密的訊息.
18652
						$conf["webSock::encode"]["text"]=$talkback; 
18653
						#可省略參數:
18654
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18655
						#$conf["payloadIsBin"]="false";
18656
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18657
						#$conf["ping"]="false";
18658
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18659
						#$conf["pong"]="false";
18660
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18661
						#$conf["frames"]=array();
18662
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18663
						#$conf["mask"]="false";
18664
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18665
						#$conf["debug"]="false";
18666
						#參考資料:
18667
						#無.
18668
						#備註:
18669
						#目前$conf["text"]長度超過125會出錯.
18670
						$talkback=webSock::encode($conf["webSock::encode"]);
18671
						unset($conf["webSock::encode"]);
18672
 
18673
						#如果執行失敗
18674
						if($talkback["status"]==="false"){
18675
 
18676
							#印出結果
18677
							var_dump($talkback);
18678
 
18679
							#結束執行
18680
							exit;
18681
 
18682
							}#if end
18683
 
18684
						#debug
18685
						#var_dump(__LINE__,$talkback);
18686
 
18687
						}#if end
18688
 
18689
					}#if end
18690
 
18691
				}#if end
18692
 
18693
			#反之不為 web socket 訊息
18694
			else{
18695
 
18696
				#儲存成只有一個訊息
18697
				$talkback["content"][]=$talkback;
18698
 
18699
				}#else
18700
 
18701
			#針對每個訊息的分段
18702
			foreach($talkback["content"] as $msg){
18703
 
18704
				#回傳訊息
18705
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18706
 
18707
				#debug
18708
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18709
 
18710
				}#foreach end
18711
 
18712
			#設置執行正常
18713
			$result["status"]="true";
18714
 
18715
			#回傳結果
18716
			return $result;
18717
 
18718
			}#if end
18719
 
18720
		#如果收到的訊息長度大於 "talkTo:"
18721
		if(strlen($receivedData)>strlen("talkTo:")){
18722
 
18723
			#如果收到開頭為 "talkTo:"
18724
			#涵式說明:
18725
			#取得符合特定字首與字尾的字串
18726
			#回傳的結果:
18727
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
18728
			#$result["function"],當前執行的函數名稱.
18729
			#$result["error"],錯誤訊息陣列.
18730
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
18731
			#$result["returnString"],爲符合字首條件的字串內容。
18732
			#必填參數:
18733
			#$conf["checkString"],字串,要檢查的字串.
18734
			$conf["search::getMeetConditionsString"]["checkString"]=$receivedData;
18735
			#可省略參數:
18736
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
18737
			$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
18738
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
18739
			#$conf["tailWord"]="";
18740
			#參考資料:
18741
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
18742
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
18743
			unset($conf["search::getMeetConditionsString"]);
18744
 
18745
			#如果選找前置字串 "talkTo:" 失敗
18746
			if($getMeetConditionsString["status"]==="false"){
18747
 
18748
				#設置執行失敗
18749
				$result["status"]="false";
18750
 
18751
				#設置執行錯誤訊息
18752
				$result["error"]=$getMeetConditionsString;
18753
 
18754
				#回傳結果
18755
				return $result;
18756
 
18757
				}#if end
18758
 
18759
			#如果存在 "talkTo:" 前置字串
18760
			if($getMeetConditionsString["founded"]==="true"){
18761
 
18762
				#如果尚未認證
18763
				if($connections[$conIndex]["auth"]==="false"){
18764
 
18765
					#設置要回傳的訊息
18766
					$talkback=json_encode("permission denied");
18767
 
18768
					#如果是 ws 模式
18769
					if($conf["wsMode"]==="true"){
18770
 
18771
						#如果已經 handshake 過
18772
						if($connections[$conIndex]["handshaked"]==="true"){
18773
 
18774
							#如果要 unmask	
18775
							if($connections[$conIndex]["unmask"]==="true"){
18776
 
18777
								#函式說明:
18778
								#加密 handshake 後要傳送的訊息 
18779
								#回傳結果:
18780
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18781
								#$result["error"],執行不正常結束的錯訊息陣列.
18782
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18783
								#$result["argu"],陣列,使用的參數.
18784
								#必填參數:
18785
								#$conf["text"],字串,要加密的訊息.
18786
								$conf["webSock::encode"]["text"]=$talkback; 
18787
								#可省略參數:
18788
								#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18789
								#$conf["payloadIsBin"]="false";
18790
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18791
								#$conf["ping"]="false";
18792
								#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18793
								#$conf["pong"]="false";
18794
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18795
								#$conf["frames"]=array();
18796
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18797
								#$conf["mask"]="false";
18798
								#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18799
								#$conf["debug"]="false";
18800
								#參考資料:
18801
								#無.
18802
								#備註:
18803
								#目前$conf["text"]長度超過125會出錯.
18804
								$talkback=webSock::encode($conf["webSock::encode"]);
18805
								unset($conf["webSock::encode"]);
18806
 
18807
								#如果執行失敗
18808
								if($talkback["status"]==="false"){
18809
 
18810
									#印出結果
18811
									var_dump($talkback);
18812
 
18813
									#結束執行
18814
									exit;
18815
 
18816
									}#if end
18817
 
18818
								#debug
18819
								#var_dump(__LINE__,$talkback);
18820
 
18821
								}#if end
18822
 
18823
							}#if end
18824
 
18825
						}#if end
18826
 
18827
					#反之不為 web socket 訊息
18828
					else{
18829
 
18830
						#儲存成只有一個訊息
18831
						$talkback["content"][]=$talkback;
18832
 
18833
						}#else
18834
 
18835
					#針對每個訊息的分段
18836
					foreach($talkback["content"] as $msg){
18837
 
18838
						#回傳訊息
18839
						$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18840
 
18841
						#debug
18842
						#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18843
 
18844
						}#foreach end
18845
 
18846
					#設置執行正常
18847
					$result["status"]="true";
18848
 
18849
					#回傳結果
18850
					return $result;
18851
 
18852
					}#if end
18853
 
18854
				#用 "talkTo:" 分割收到的訊息
18855
				#涵式說明:
18856
				#將固定格式的字串分開,並回傳分開的結果。
18857
				#回傳結果:
18858
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18859
				#$result["error"],錯誤訊息陣列
18860
				#$result["function"],當前執行的函數名稱.
18861
				#$result["oriStr"],要分割的原始字串內容
18862
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
18863
				#$result["dataCounts"],爲總共分成幾段
18864
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
18865
				#必填的參數:
18866
				$conf["stringProcess::spiltString"]["stringIn"]=$receivedData;#要處理的字串。
18867
				$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
18868
				#可省略參數:
18869
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
18870
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
18871
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
18872
				unset($conf["stringProcess::spiltString"]);
18873
 
18874
				#如果分割字串失敗
18875
				if($spiltString["status"]==="false"){
18876
 
18877
					#設置執行失敗
18878
					$result["status"]="false";
18879
 
18880
					#設置執行錯誤訊息
18881
					$result["error"]=$spiltString;
18882
 
18883
					#回傳結果
18884
					return $result;
18885
 
18886
					}#if end
18887
 
18888
				#如果剛好分割出一筆資料
18889
				if($spiltString["dataCounts"]===1){
18890
 
18891
					#取得自己的id
18892
					$myId=$connections[$conIndex]["id"];
18893
 
18894
					#取得講話對象的id
18895
					$toId=$spiltString["dataArray"][0];
18896
 
18897
					#設置對象不存在的識別
18898
					$targetExist=false;
18899
 
18900
					#設置通話對象的key
18901
					$targetKey="";
18902
 
18903
					#取得除了自己的id以外的所有連線
18904
					foreach($connections as $index=>$talkInfo){
18905
 
18906
						#除了自己的id
18907
						if($talkInfo["id"]!==$myId){
18908
 
18909
							#如果存在要對話的對象
18910
							if($talkInfo["id"]===$toId){
18911
 
18912
								#設置對象存在的識別
18913
								$targetExist=true;
18914
 
18915
								#通話對象的key
18916
								$targetKey=$index;
18917
 
18918
								}#if end
18919
 
18920
							}#if end
18921
 
18922
						}#for each end
18923
 
18924
					#如果通話對象存在
18925
					if($targetExist){
18926
 
18927
						#保存自己的通話對象
18928
						$connections[$conIndex]["talkTo"][]=$toId;
18929
 
18930
						#設置要給自己看的訊息
18931
						$talkback="您與 ".$toId." 展開對話";
18932
 
18933
						#json encode 要給自己看的訊息
18934
						$talkback=json_encode($talkback).PHP_EOL;
18935
 
18936
						#如果是 ws 模式
18937
						if($conf["wsMode"]==="true"){
18938
 
18939
							#如果已經 handshake 過
18940
							if($connections[$conIndex]["handshaked"]==="true"){
18941
 
18942
								#如果要 unmask	
18943
								if($connections[$conIndex]["unmask"]==="true"){
18944
 
18945
									#函式說明:
18946
									#加密 handshake 後要傳送的訊息 
18947
									#回傳結果:
18948
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18949
									#$result["error"],執行不正常結束的錯訊息陣列.
18950
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18951
									#$result["argu"],陣列,使用的參數.
18952
									#必填參數:
18953
									#$conf["text"],字串,要加密的訊息.
18954
									$conf["webSock::encode"]["text"]=$talkback; 
18955
									#可省略參數:
18956
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18957
									#$conf["payloadIsBin"]="false";
18958
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18959
									#$conf["ping"]="false";
18960
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18961
									#$conf["pong"]="false";
18962
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18963
									#$conf["frames"]=array();
18964
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18965
									#$conf["mask"]="false";
18966
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18967
									#$conf["debug"]="false";
18968
									#參考資料:
18969
									#無.
18970
									#備註:
18971
									#目前$conf["text"]長度超過125會出錯.
18972
									$talkback=webSock::encode($conf["webSock::encode"]);
18973
									unset($conf["webSock::encode"]);
18974
 
18975
									#如果執行失敗
18976
									if($talkback["status"]==="false"){
18977
 
18978
										#印出結果
18979
										var_dump($talkback);
18980
 
18981
										#結束執行
18982
										exit;
18983
 
18984
										}#if end
18985
 
18986
									#debug
18987
									#var_dump(__LINE__,$talkback);
18988
 
18989
									}#if end
18990
 
18991
								}#if end
18992
 
18993
							}#if end
18994
 
18995
						#反之不為 web socket 訊息
18996
						else{
18997
 
18998
							#儲存成只有一個訊息
18999
							$talkback["content"][]=$talkback;
19000
 
19001
							}#else
19002
 
19003
						#針對每個訊息的分段
19004
						foreach($talkback["content"] as $msg){
19005
 
19006
							#回傳訊息
19007
							$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
19008
 
19009
							#debug
19010
							#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19011
 
19012
							}#foreach end
19013
 
19014
						#讓對方可以跟自己對話
19015
						$connections[$targetKey]["talkTo"][]=$myId;
19016
 
19017
						#設置要給對方看的訊息
19018
						$talkback=$connections[$conIndex]["id"]." 與您展開對話";
19019
 
19020
						#json encode 設置要給對方看的訊息
19021
						$talkback=json_encode($talkback);
19022
 
19023
						#如果是 ws 模式
19024
						if($conf["wsMode"]==="true"){
19025
 
19026
							#如果已經 handshake 過
19027
							if($connections[$conIndex]["handshaked"]==="true"){
19028
 
19029
								#如果要 unmask	
19030
								if($connections[$conIndex]["unmask"]==="true"){
19031
 
19032
									#函式說明:
19033
									#加密 handshake 後要傳送的訊息 
19034
									#回傳結果:
19035
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19036
									#$result["error"],執行不正常結束的錯訊息陣列.
19037
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19038
									#$result["argu"],陣列,使用的參數.
19039
									#必填參數:
19040
									#$conf["text"],字串,要加密的訊息.
19041
									$conf["webSock::encode"]["text"]=$talkback; 
19042
									#可省略參數:
19043
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19044
									#$conf["payloadIsBin"]="false";
19045
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19046
									#$conf["ping"]="false";
19047
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19048
									#$conf["pong"]="false";
19049
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19050
									#$conf["frames"]=array();
19051
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19052
									#$conf["mask"]="false";
19053
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19054
									#$conf["debug"]="false";
19055
									#參考資料:
19056
									#無.
19057
									#備註:
19058
									#目前$conf["text"]長度超過125會出錯.
19059
									$talkback=webSock::encode($conf["webSock::encode"]);
19060
									unset($conf["webSock::encode"]);
19061
 
19062
									#如果執行失敗
19063
									if($talkback["status"]==="false"){
19064
 
19065
										#印出結果
19066
										var_dump($talkback);
19067
 
19068
										#結束執行
19069
										exit;
19070
 
19071
										}#if end
19072
 
19073
									#debug
19074
									#var_dump(__LINE__,$talkback);
19075
 
19076
									}#if end
19077
 
19078
								}#if end
19079
 
19080
							}#if end
19081
 
19082
						#反之不為 web socket 訊息
19083
						else{
19084
 
19085
							#儲存成只有一個訊息
19086
							$talkback["content"][]=$talkback;
19087
 
19088
							}#else
19089
 
19090
						#針對每個訊息的分段
19091
						foreach($talkback["content"] as $msg){
19092
 
19093
							#給對方看的訊息
19094
							$socket_write=socket_write($connections[$targetKey]["connect"], $msg, strlen($msg));
19095
 
19096
							#debug
19097
							#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19098
 
19099
							}#foreach end
19100
 
19101
						#設置執行正常
19102
						$result["status"]="true";
19103
 
19104
						#回傳結果
19105
						return $result;
19106
 
19107
						}#if end
19108
 
19109
					}#if end
19110
 
19111
				}#if end
19112
 
19113
			}#if end
19114
 
19115
		#不是支援的訊息
19116
		$result["status"]="continue";
19117
 
19118
		#回傳結果
19119
		return $result;
19120
 
19121
		}#function basic end
19122
 
19123
	/*
19124
	#函式說明:
19125
	#提供webSock::nativeSocketTcpIpServer使用系統功能(system).
19126
	#回傳結果:
19127
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
19128
	#$result["error"],執行不正常結束的錯訊息陣列.
19129
	#$result["argu"],陣列,使用的參數.
19130
	#必填參數:
19131
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
19132
	$conf["data"]="";
19133
	#$conf["serverSock"],resource,web socket server socket
19134
	$conf["serverSock"]=$resource;
19135
	#$conf["clientSock"],$resource,web socket client socket
19136
	$conf["clientSock"]=$resource;
19137
	#$conf["clientInfo"],陣列,web socket client info.
19138
	$conf["clientInfo"]=array();
19139
	#$conf["clientIndex"],整數.web socket client index.
19140
	$conf["clientIndex"];
19141
	#$conf["allConn"],陣列,all web socket client info.
19142
	$conf["allConn"]=array();
19143
	#可省略參數:
19144
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
19145
	#$conf["wsMode"]="true";
19146
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
19147
	#$conf["gpgId"]=gnupgId;
19148
	#參考資料:
19149
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
19150
	#備註:
19151
	#收到用戶的"shutdown"訊息,會重新啟動webSocket server.
19152
	#無.
19153
	*/
19154
	public static function system(&$conf){
19155
 
19156
		#初始化要回傳的結果
19157
		$result=array();
19158
 
19159
		#取得當前執行的函數名稱
19160
		$result["function"]=__FUNCTION__;
19161
 
19162
		#涵式說明:
19163
		#判斷當前環境為web還是cmd
19164
		#回傳結果:
19165
		#$result,"web"或"cmd"
19166
		if(csInformation::getEnv()==="web"){
19167
 
19168
			#設置執行失敗
19169
			$result["status"]="false";
19170
 
19171
			#設置執行錯誤訊息
19172
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19173
 
19174
			#回傳結果
19175
			return $result;
19176
 
19177
			}#if end
19178
 
19179
		#取得參數
19180
		$result["argu"]=$conf;
19181
 
19182
		#如果 $conf 不為陣列
19183
		if(gettype($conf)!="array"){
19184
 
19185
			#設置執行失敗
19186
			$result["status"]="false";
19187
 
19188
			#設置執行錯誤訊息
19189
			$result["error"][]="\$conf變數須為陣列形態";
19190
 
19191
			#如果傳入的參數為 null
19192
			if($conf==null){
19193
 
19194
				#設置執行錯誤訊息
19195
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19196
 
19197
				}#if end
19198
 
19199
			#回傳結果
19200
			return $result;
19201
 
19202
			}#if end
19203
 
19204
		#檢查參數
19205
		#函式說明:
19206
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19207
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19208
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19209
		#$result["function"],當前執行的函式名稱.
19210
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19211
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19212
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19213
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19214
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19215
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
19216
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
19217
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
19218
		#必填寫的參數:
19219
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
19220
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
19221
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
19222
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
19223
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
19224
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
19225
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
19226
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
19227
		#可以省略的參數:
19228
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
19229
		#$conf["canBeEmptyString"]="false";
19230
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
19231
		#$conf["canNotBeEmpty"]=array();
19232
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
19233
		#$conf["canBeEmpty"]=array();
19234
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
19235
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
19236
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
19237
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
19238
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
19239
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
19240
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
19241
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
19242
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
19243
		#$conf["arrayCountEqualCheck"][]=array();
19244
		#參考資料來源:
19245
		#array_keys=>http://php.net/manual/en/function.array-keys.php
19246
		#建議:
19247
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
19248
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
19249
		unset($conf["variableCheck::checkArguments"]);
19250
 
19251
		#如果檢查參數失敗
19252
		if($checkArguments["status"]==="false"){
19253
 
19254
			#設置執行失敗
19255
			$result["status"]="false";
19256
 
19257
			#設置執行錯誤訊息
19258
			$result["error"]=$checkArguments;
19259
 
19260
			#回傳結果
19261
			return $result;
19262
 
19263
			}#if end
19264
 
19265
		#如果檢查參數不通過
19266
		if($checkArguments["passed"]==="false"){
19267
 
19268
			#設置執行失敗
19269
			$result["status"]="false";
19270
 
19271
			#設置執行錯誤訊息
19272
			$result["error"]=$checkArguments;
19273
 
19274
			#回傳結果
19275
			return $result;
19276
 
19277
			}#if end
19278
 
19279
		#取得收到的訊息
19280
		$receivedData=$conf["data"];
19281
 
19282
		#取得 server 的 socket
19283
		$serverSocket=$conf["serverSock"];
19284
 
19285
		#取得 client 的 socket
19286
		$clientSocket=$conf["clientSock"];
19287
 
19288
		#取得 client 的資訊
19289
		$clientInfo=$conf["clientInfo"];
19290
 
19291
		#取得 client 的索引
19292
		$clientIndex=$conf["clientIndex"];
19293
 
19294
		#取得 all clients 的資訊
19295
		$allConn=&$conf["allConn"];
19296
 
19297
		#hex2bin
19298
		#函式說明:
19299
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19300
		#回傳結果:
19301
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19302
		#$result["function"],當前執行的函數名稱.
19303
		#$result["content"],加密後的結果.
19304
		#$result["error"],錯誤訊息陣列.
19305
		#$result["argu"],使用的參數.
19306
		#必填參數:
19307
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19308
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19309
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
19310
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
19311
		#可省略參數:
19312
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19313
		#$conf["sha1Raw"]="false";
19314
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19315
		#$conf["p_hash"]="";
19316
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19317
		#$conf["keyForAes256"]="";
19318
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19319
		#$conf["aes256Encode"]="";
19320
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19321
		#$conf["qbpwcfDecode"]="false";
19322
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19323
		#$conf["gpgDecrypt"]="false";
19324
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19325
		#$conf["gpgId"]="";
19326
		#參考資料:
19327
		#sha1=>http://php.net/manual/en/function.sha1.php
19328
		#md5=>http://php.net/manual/en/function.md5.php
19329
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19330
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19331
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19332
		#備註:
19333
		#無.
19334
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19335
		unset($conf["authenticate::enCodeStr"]);
19336
 
19337
		#如果執行失敗
19338
		if($enCodeStr["status"]==="false"){
19339
 
19340
			#設置執行異常
19341
			$result["status"]="false";
19342
 
19343
			#設置執行錯誤
19344
			$result["error"]=$enCodeStr;
19345
 
19346
			#回傳結果
19347
			return $result;
19348
 
19349
			}#if end
19350
 
19351
		#取得hex2bin後的字串
19352
		$receivedData=$enCodeStr["content"];
19353
 
19354
		#gpg decrypt
19355
		#函式說明:
19356
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19357
		#回傳結果:
19358
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19359
		#$result["function"],當前執行的函數名稱.
19360
		#$result["content"],加密後的結果.
19361
		#$result["error"],錯誤訊息陣列.
19362
		#$result["argu"],使用的參數.
19363
		#必填參數:
19364
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19365
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19366
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
19367
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
19368
		#可省略參數:
19369
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19370
		#$conf["sha1Raw"]="false";
19371
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19372
		#$conf["p_hash"]="";
19373
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19374
		#$conf["keyForAes256"]="";
19375
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19376
		#$conf["aes256Encode"]="";
19377
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19378
		#$conf["qbpwcfDecode"]="false";
19379
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19380
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
19381
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19382
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
19383
		#參考資料:
19384
		#sha1=>http://php.net/manual/en/function.sha1.php
19385
		#md5=>http://php.net/manual/en/function.md5.php
19386
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19387
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19388
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19389
		#備註:
19390
		#無.
19391
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19392
		unset($conf["authenticate::enCodeStr"]);
19393
 
19394
		#如果執行失敗
19395
		if($enCodeStr["status"]==="false"){
19396
 
19397
			#設置執行異常
19398
			$result["status"]="false";
19399
 
19400
			#設置執行錯誤
19401
			$result["error"]=$enCodeStr;
19402
 
19403
			#回傳結果
19404
			return $result;
19405
 
19406
			}#if end
19407
 
19408
		#取得解密後的字串
19409
		$receivedData=$enCodeStr["content"];
19410
 
19411
		#json_decode
19412
		$receivedData=json_decode($receivedData);
19413
 
19414
		#如果收到 "shutdown"
19415
		if($receivedData==="shutdown"){
19416
 
19417
			#設置要回傳的訊息
19418
			$talkback="Server 即將關閉";
19419
 
19420
			#json encode 要回傳的訊息
19421
			$talkback=json_encode($talkback);
19422
 
19423
			#如果是 ws 模式
19424
			if($conf["wsMode"]==="true"){
19425
 
19426
				#如果已經 handshake 過
19427
				if($connections[$conIndex]["handshaked"]==="true"){
19428
 
19429
					#如果要 unmask	
19430
					if($connections[$conIndex]["unmask"]==="true"){
19431
 
19432
						#函式說明:
19433
						#加密 handshake 後要傳送的訊息 
19434
						#回傳結果:
19435
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19436
						#$result["error"],執行不正常結束的錯訊息陣列.
19437
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19438
						#$result["argu"],陣列,使用的參數.
19439
						#必填參數:
19440
						#$conf["text"],字串,要加密的訊息.
19441
						$conf["webSock::encode"]["text"]=$talkback; 
19442
						#可省略參數:
19443
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19444
						#$conf["payloadIsBin"]="false";
19445
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19446
						#$conf["ping"]="false";
19447
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19448
						#$conf["pong"]="false";
19449
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19450
						#$conf["frames"]=array();
19451
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19452
						#$conf["mask"]="false";
19453
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19454
						#$conf["debug"]="false";
19455
						#參考資料:
19456
						#無.
19457
						#備註:
19458
						#無.
19459
						$talkback=webSock::encode($conf["webSock::encode"]);
19460
						unset($conf["webSock::encode"]);
19461
 
19462
						#如果執行失敗
19463
						if($talkback["status"]==="false"){
19464
 
19465
							#印出結果
19466
							var_dump($talkback);
19467
 
19468
							#結束執行
19469
							exit;
19470
 
19471
							}#if end
19472
 
19473
						#debug
19474
						#var_dump(__LINE__,$talkback);
19475
 
19476
						}#if end
19477
 
19478
					}#if end
19479
 
19480
				}#if end
19481
 
19482
			#反之不為 web socket 訊息
19483
			else{
19484
 
19485
				#儲存成只有一個訊息
19486
				$talkback["content"][]=$talkback;
19487
 
19488
				}#else
19489
 
19490
			#針對每個訊息的分段
19491
			foreach($talkback["content"] as $msg){
19492
 
19493
				#回傳訊息
19494
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
19495
 
19496
				#debug
19497
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19498
 
19499
				}#foreach end
19500
 
19501
			#關閉用戶的連線
19502
			socket_close($con["connect"]);
19503
 
19504
			}#if end
19505
 
19506
		#關閉 server socket
19507
		socket_close($serverSocket);
19508
 
19509
		#設置執行正常
19510
		$result["status"]="true";
19511
 
19512
		#回傳結果
19513
		return $result;
19514
 
19515
		}#function system end
19516
 
19517
	/*
19518
	#函式說明:
19519
	#提供webSock::nativeSocketTcpIpServer使用系統功能(system).
19520
	#回傳結果:
19521
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
19522
	#$result["error"],執行不正常結束的錯訊息陣列.
19523
	#$result["argu"],陣列,使用的參數.
19524
	#必填參數:
19525
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料.
19526
	$conf["data"]="";
19527
	#$conf["serverSock"],resource,web socket server socket
19528
	$conf["serverSock"]=$resource;
19529
	#$conf["clientSock"],$resource,web socket client socket
19530
	$conf["clientSock"]=$resource;
19531
	#$conf["clientInfo"],陣列,web socket client info.
19532
	$conf["clientInfo"]=array();
19533
	#$conf["clientIndex"],整數.web socket client index.
19534
	$conf["clientIndex"];
19535
	#$conf["allConn"],陣列,all web socket client info.
19536
	$conf["allConn"]=array();
19537
	#可省略參數:
19538
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
19539
	#$conf["wsMode"]="true";
19540
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
19541
	#$conf["gpgId"]=gnupgId;
19542
	#參考資料:
19543
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
19544
	#備註:
19545
	#收到用戶的"quit"訊息,會結束與用戶的連線.
19546
	*/
19547
	public static function noAuth(&$conf){
19548
 
19549
		#初始化要回傳的結果
19550
		$result=array();
19551
 
19552
		#取得當前執行的函數名稱
19553
		$result["function"]=__FUNCTION__;
19554
 
19555
		#涵式說明:
19556
		#判斷當前環境為web還是cmd
19557
		#回傳結果:
19558
		#$result,"web"或"cmd"
19559
		if(csInformation::getEnv()==="web"){
19560
 
19561
			#設置執行失敗
19562
			$result["status"]="false";
19563
 
19564
			#設置執行錯誤訊息
19565
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19566
 
19567
			#回傳結果
19568
			return $result;
19569
 
19570
			}#if end
19571
 
19572
		#取得參數
19573
		$result["argu"]=$conf;
19574
 
19575
		#如果 $conf 不為陣列
19576
		if(gettype($conf)!="array"){
19577
 
19578
			#設置執行失敗
19579
			$result["status"]="false";
19580
 
19581
			#設置執行錯誤訊息
19582
			$result["error"][]="\$conf變數須為陣列形態";
19583
 
19584
			#如果傳入的參數為 null
19585
			if($conf==null){
19586
 
19587
				#設置執行錯誤訊息
19588
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19589
 
19590
				}#if end
19591
 
19592
			#回傳結果
19593
			return $result;
19594
 
19595
			}#if end
19596
 
19597
		#檢查參數
19598
		#函式說明:
19599
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19600
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19601
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19602
		#$result["function"],當前執行的函式名稱.
19603
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19604
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19605
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19606
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19607
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19608
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
19609
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
19610
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
19611
		#必填寫的參數:
19612
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
19613
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
19614
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
19615
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
19616
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
19617
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
19618
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
19619
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
19620
		#可以省略的參數:
19621
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
19622
		#$conf["canBeEmptyString"]="false";
19623
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
19624
		#$conf["canNotBeEmpty"]=array();
19625
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
19626
		#$conf["canBeEmpty"]=array();
19627
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
19628
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
19629
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
19630
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
19631
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
19632
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
19633
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
19634
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
19635
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
19636
		#$conf["arrayCountEqualCheck"][]=array();
19637
		#參考資料來源:
19638
		#array_keys=>http://php.net/manual/en/function.array-keys.php
19639
		#建議:
19640
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
19641
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
19642
		unset($conf["variableCheck::checkArguments"]);
19643
 
19644
		#如果檢查參數失敗
19645
		if($checkArguments["status"]==="false"){
19646
 
19647
			#設置執行失敗
19648
			$result["status"]="false";
19649
 
19650
			#設置執行錯誤訊息
19651
			$result["error"]=$checkArguments;
19652
 
19653
			#回傳結果
19654
			return $result;
19655
 
19656
			}#if end
19657
 
19658
		#如果檢查參數不通過
19659
		if($checkArguments["passed"]==="false"){
19660
 
19661
			#設置執行失敗
19662
			$result["status"]="false";
19663
 
19664
			#設置執行錯誤訊息
19665
			$result["error"]=$checkArguments;
19666
 
19667
			#回傳結果
19668
			return $result;
19669
 
19670
			}#if end
19671
 
19672
		#取得收到的訊息
19673
		$receivedData=$conf["data"];
19674
 
19675
		#取得 server 的 socket
19676
		$serverSocket=$conf["serverSock"];
19677
 
19678
		#取得 client 的 socket
19679
		$clientSocket=$conf["clientSock"];
19680
 
19681
		#取得 client 的資訊
19682
		$clientInfo=$conf["clientInfo"];
19683
 
19684
		#取得 client 的索引
19685
		$clientIndex=$conf["clientIndex"];
19686
 
19687
		#取得 all clients 的資訊
19688
		$allConn=&$conf["allConn"];
19689
 
19690
		#hex2bin
19691
		#函式說明:
19692
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19693
		#回傳結果:
19694
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19695
		#$result["function"],當前執行的函數名稱.
19696
		#$result["content"],加密後的結果.
19697
		#$result["error"],錯誤訊息陣列.
19698
		#$result["argu"],使用的參數.
19699
		#必填參數:
19700
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19701
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19702
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
19703
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
19704
		#可省略參數:
19705
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19706
		#$conf["sha1Raw"]="false";
19707
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19708
		#$conf["p_hash"]="";
19709
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19710
		#$conf["keyForAes256"]="";
19711
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19712
		#$conf["aes256Encode"]="";
19713
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19714
		#$conf["qbpwcfDecode"]="false";
19715
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19716
		#$conf["gpgDecrypt"]="false";
19717
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19718
		#$conf["gpgId"]="";
19719
		#參考資料:
19720
		#sha1=>http://php.net/manual/en/function.sha1.php
19721
		#md5=>http://php.net/manual/en/function.md5.php
19722
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19723
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19724
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19725
		#備註:
19726
		#無.
19727
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19728
		unset($conf["authenticate::enCodeStr"]);
19729
 
19730
		#如果執行失敗
19731
		if($enCodeStr["status"]==="false"){
19732
 
19733
			#設置執行異常
19734
			$result["status"]="false";
19735
 
19736
			#設置執行錯誤
19737
			$result["error"]=$enCodeStr;
19738
 
19739
			#回傳結果
19740
			return $result;
19741
 
19742
			}#if end
19743
 
19744
		#取得hex2bin後的字串
19745
		$receivedData=$enCodeStr["content"];
19746
 
19747
		#gpg decrypt
19748
		#函式說明:
19749
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19750
		#回傳結果:
19751
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19752
		#$result["function"],當前執行的函數名稱.
19753
		#$result["content"],加密後的結果.
19754
		#$result["error"],錯誤訊息陣列.
19755
		#$result["argu"],使用的參數.
19756
		#必填參數:
19757
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19758
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19759
		#$conf["enCodeType"],"字串",加密的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin",7種,"sha1"較耗時,"md5"較快,"p_hash"適用於密碼加密,"aes256"是對稱式加解密,"qbpwcf"是透過urlencode、json_encode、base64_encode的結果,"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin".
19760
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
19761
		#可省略參數:
19762
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19763
		#$conf["sha1Raw"]="false";
19764
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19765
		#$conf["p_hash"]="";
19766
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19767
		#$conf["keyForAes256"]="";
19768
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19769
		#$conf["aes256Encode"]="";
19770
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19771
		#$conf["qbpwcfDecode"]="false";
19772
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19773
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
19774
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19775
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
19776
		#參考資料:
19777
		#sha1=>http://php.net/manual/en/function.sha1.php
19778
		#md5=>http://php.net/manual/en/function.md5.php
19779
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19780
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19781
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19782
		#備註:
19783
		#無.
19784
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19785
		unset($conf["authenticate::enCodeStr"]);
19786
 
19787
		#如果執行失敗
19788
		if($enCodeStr["status"]==="false"){
19789
 
19790
			#設置執行異常
19791
			$result["status"]="false";
19792
 
19793
			#設置執行錯誤
19794
			$result["error"]=$enCodeStr;
19795
 
19796
			#回傳結果
19797
			return $result;
19798
 
19799
			}#if end
19800
 
19801
		#取得解密後的字串
19802
		$receivedData=$enCodeStr["content"];
19803
 
19804
		#json_decode
19805
		$receivedData=json_decode($receivedData);
19806
 
19807
		#如果訊息內容為 "quit"
19808
		if($receivedData==="quit"){
19809
 
19810
			#設置要回傳的訊息
19811
			$talkback="結束與 server 的連線";
19812
 
19813
			#json encode 要回傳的訊息
19814
			$talkback=json_encode($talkback).PHP_EOL;
19815
 
19816
			#如果是 ws 模式
19817
			if($conf["wsMode"]==="true"){
19818
 
19819
				#如果已經 handshake 過
19820
				if($connections[$conIndex]["handshaked"]==="true"){
19821
 
19822
					#如果要 unmask	
19823
					if($connections[$conIndex]["unmask"]==="true"){
19824
 
19825
						#函式說明:
19826
						#加密 handshake 後要傳送的訊息 
19827
						#回傳結果:
19828
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19829
						#$result["error"],執行不正常結束的錯訊息陣列.
19830
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19831
						#$result["argu"],陣列,使用的參數.
19832
						#必填參數:
19833
						#$conf["text"],字串,要加密的訊息.
19834
						$conf["webSock::encode"]["text"]=$talkback; 
19835
						#可省略參數:
19836
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19837
						#$conf["payloadIsBin"]="false";
19838
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19839
						#$conf["ping"]="false";
19840
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19841
						#$conf["pong"]="false";
19842
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19843
						#$conf["frames"]=array();
19844
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19845
						#$conf["mask"]="false";
19846
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19847
						#$conf["debug"]="false";
19848
						#參考資料:
19849
						#無.
19850
						#備註:
19851
						#目前$conf["text"]長度超過125會出錯.
19852
						$talkback=webSock::encode($conf["webSock::encode"]);
19853
						unset($conf["webSock::encode"]);
19854
 
19855
						#如果執行失敗
19856
						if($talkback["status"]==="false"){
19857
 
19858
							#印出結果
19859
							var_dump($talkback);
19860
 
19861
							#結束執行
19862
							exit;
19863
 
19864
							}#if end
19865
 
19866
						#debug
19867
						#var_dump(__LINE__,$talkback);
19868
 
19869
						}#if end
19870
 
19871
					}#if end
19872
 
19873
				}#if end
19874
 
19875
			#反之不為 web socket 訊息
19876
			else{
19877
 
19878
				#儲存成只有一個訊息
19879
				$talkback["content"][]=$talkback;
19880
 
19881
				}#else
19882
 
19883
			#針對每個訊息的分段
19884
			foreach($talkback["content"] as $msg){
19885
 
19886
				#回傳訊息
19887
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
19888
 
19889
				#debug
19890
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19891
 
19892
				}#foreach end
19893
 
19894
			#關閉被 client 的連線
19895
			socket_close($con["connect"]);
19896
 
19897
			#清理連線的陣列
19898
			unset($connections[$conIndex]);
19899
 
19900
			#設置執行正常
19901
			$result["status"]="true";
19902
 
19903
			#回傳結果
19904
			return $result;
19905
 
19906
			}#if end
19907
 
19908
		}#function noAuth end
19909
 
19910
	/*
19911
	#函式說明:
19912
	#依照參數來執行對應的函式.
19913
	#回傳結果:
19914
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19915
	#$result["function"],當前執行的函數名稱.
19916
	#$result["content"],加密後的結果.
19917
	#$result["error"],錯誤訊息陣列.
19918
	#$result["argu"],使用的參數.
19919
	#必填參數:
19920
	#$conf["data"],字串,收到bin2hex編碼後再gpg加密後的資料.
19921
	$conf["data"]="";
19922
	#$conf["serverSock"],socket,代表web socket server的socket.
19923
	$conf["serverSock"]=;
19924
	#$conf["clientSock"],socket,代表web socket client的socket.
19925
	#$conf["clientInfo"],陣列,用戶端的資訊.
19926
	$conf["clientInfo"]=array();
19927
	#$conf["clientIndex"],字串,代表client於allConn中的索引.
19928
	$conf["clientIndex"]="";
19929
	#$conf["allConn"],陣列,所有連線的用戶端的連線資訊.
19930
	$conf["allConn"]=array();
19931
	#可省略參數:
19932
	#無.
19933
	#參考資料:
19934
	#無.
19935
	#備註:
19936
	#無.
19937
	*/
19938
	public static function callFunc(&$conf){
19939
 
19940
		#初始化要回傳的結果
19941
		$result=array();
19942
 
19943
		#取得當前執行的函數名稱
19944
		$result["function"]=__FUNCTION__;
19945
 
19946
		#涵式說明:
19947
		#判斷當前環境為web還是cmd
19948
		#回傳結果:
19949
		#$result,"web"或"cmd"
19950
		if(csInformation::getEnv()==="web"){
19951
 
19952
			#設置執行失敗
19953
			$result["status"]="false";
19954
 
19955
			#設置執行錯誤訊息
19956
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19957
 
19958
			#回傳結果
19959
			return $result;
19960
 
19961
			}#if end
19962
 
19963
		#取得參數
19964
		$result["argu"]=$conf;
19965
 
19966
		#如果 $conf 不為陣列
19967
		if(gettype($conf)!="array"){
19968
 
19969
			#設置執行失敗
19970
			$result["status"]="false";
19971
 
19972
			#設置執行錯誤訊息
19973
			$result["error"][]="\$conf變數須為陣列形態";
19974
 
19975
			#如果傳入的參數為 null
19976
			if($conf==null){
19977
 
19978
				#設置執行錯誤訊息
19979
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19980
 
19981
				}#if end
19982
 
19983
			#回傳結果
19984
			return $result;
19985
 
19986
			}#if end
19987
 
19988
		#檢查參數
19989
		#函式說明:
19990
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19991
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19992
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19993
		#$result["function"],當前執行的函式名稱.
19994
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19995
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19996
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19997
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19998
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19999
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
20000
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
20001
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
20002
		#必填寫的參數:
20003
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
20004
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
20005
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
20006
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
20007
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
20008
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
20009
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
20010
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
20011
		#可以省略的參數:
20012
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
20013
		#$conf["canBeEmptyString"]="false";
20014
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
20015
		#$conf["canNotBeEmpty"]=array();
20016
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
20017
		#$conf["canBeEmpty"]=array();
20018
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
20019
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
20020
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
20021
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("listenIp","listenPort","wsMode","processFuncs");
20022
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
20023
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array");
20024
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
20025
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",null,"false",null);
20026
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
20027
		#$conf["arrayCountEqualCheck"][]=array();
20028
		#參考資料來源:
20029
		#array_keys=>http://php.net/manual/en/function.array-keys.php
20030
		#建議:
20031
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
20032
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
20033
		unset($conf["variableCheck::checkArguments"]);
20034
 
20035
		#如果檢查參數失敗
20036
		if($checkArguments["status"]==="false"){
20037
 
20038
			#設置執行失敗
20039
			$result["status"]="false";
20040
 
20041
			#設置執行錯誤訊息
20042
			$result["error"]=$checkArguments;
20043
 
20044
			#回傳結果
20045
			return $result;
20046
 
20047
			}#if end
20048
 
20049
		#如果檢查參數不通過
20050
		if($checkArguments["passed"]==="false"){
20051
 
20052
			#設置執行失敗
20053
			$result["status"]="false";
20054
 
20055
			#設置執行錯誤訊息
20056
			$result["error"]=$checkArguments;
20057
 
20058
			#回傳結果
20059
			return $result;
20060
 
20061
			}#if end
20062
 
20063
		#取得收到的訊息
20064
		$receivedData=$conf["data"];
20065
 
20066
		#取得 server 的 socket
20067
		$serverSocket=$conf["serverSock"];
20068
 
20069
		#取得 client 的 socket
20070
		$clientSocket=$conf["clientSock"];
20071
 
20072
		#取得 client 的資訊
20073
		$clientInfo=$conf["clientInfo"];
20074
 
20075
		#取得 client 的索引
20076
		$clientIndex=$conf["clientIndex"];
20077
 
20078
		#取得 all clients 的資訊
20079
		$allConn=$conf["allConn"];
20080
 
20081
		#hex2bin
20082
		#函式說明:
20083
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,gpg,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
20084
		#回傳結果:
20085
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
20086
		#$result["function"],當前執行的函數名稱.
20087
		#$result["content"],加密後的結果.
20088
		#$result["error"],錯誤訊息陣列.
20089
		#$result["argu"],使用的參數.
20090
		#必填參數:
20091
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
20092
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
20093
		#$conf["enCodeType"],"字串",加密或編碼的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin"與"gpg"與"hex2bin&gpg",9種,"sha1"較耗時;"md5"較快;"p_hash"適用於密碼加密;"aes256"是對稱式加解密;"qbpwcf"是透過urlencode、json_encode、base64_encode的結果;"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin";"gpg"是應用gpg進行加解密,需要先有ID對應的key;"hex2bin&gpg"為先hex2bin在進行gpg加解密.
20094
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
20095
		#可省略參數:
20096
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
20097
		#$conf["sha1Raw"]="false";
20098
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
20099
		#$conf["p_hash"]="";
20100
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
20101
		#$conf["keyForAes256"]="";
20102
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
20103
		#$conf["aes256Encode"]="";
20104
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
20105
		#$conf["qbpwcfDecode"]="false";
20106
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
20107
		#$conf["gpgDecrypt"]="false";
20108
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
20109
		$conf["authenticate::enCodeStr"]["gpgId"]=gnupgId;
20110
		#參考資料:
20111
		#sha1=>http://php.net/manual/en/function.sha1.php
20112
		#md5=>http://php.net/manual/en/function.md5.php
20113
		#password_hash=>http://php.net/manual/en/function.password-hash.php
20114
		#password_verify=>http://php.net/manual/en/function.password-verify.php
20115
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
20116
		#備註:
20117
		#無.
20118
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
20119
		unset($conf["authenticate::enCodeStr"]);
20120
 
20121
		#如果執行失敗
20122
		if($enCodeStr["status"]==="false"){
20123
 
20124
			#印出結果
20125
			return $enCodeStr;
20126
 
20127
			}#if end
20128
 
20129
		#用GnuPG解密
20130
		#函式說明:
20131
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,gpg,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
20132
		#回傳結果:
20133
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
20134
		#$result["function"],當前執行的函數名稱.
20135
		#$result["content"],加密後的結果.
20136
		#$result["error"],錯誤訊息陣列.
20137
		#$result["argu"],使用的參數.
20138
		#必填參數:
20139
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
20140
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$$enCodeStr["content"];
20141
		#$conf["enCodeType"],"字串",加密或編碼的類型,有"sha1"與"md5"與"p_hash"與"aes256"與"qbpwcf"與"bin2hex"與"hex2bin"與"gpg"與"hex2bin&gpg",9種,"sha1"較耗時;"md5"較快;"p_hash"適用於密碼加密;"aes256"是對稱式加解密;"qbpwcf"是透過urlencode、json_encode、base64_encode的結果;"bin2hex"是依照每個byte的整數數值轉成"00"~"FF"後的結果,反之為"hex2bin";"gpg"是應用gpg進行加解密,需要先有ID對應的key;"hex2bin&gpg"為先hex2bin在進行gpg加解密.
20142
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
20143
		#可省略參數:
20144
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
20145
		#$conf["sha1Raw"]="false";
20146
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
20147
		#$conf["p_hash"]="";
20148
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
20149
		#$conf["keyForAes256"]="";
20150
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
20151
		#$conf["aes256Encode"]="";
20152
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
20153
		#$conf["qbpwcfDecode"]="false";
20154
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
20155
		#$conf["gpgDecrypt"]="false";
20156
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
20157
		$conf["authenticate::enCodeStr"]["gpgId"]=gnupgId;
20158
		#參考資料:
20159
		#sha1=>http://php.net/manual/en/function.sha1.php
20160
		#md5=>http://php.net/manual/en/function.md5.php
20161
		#password_hash=>http://php.net/manual/en/function.password-hash.php
20162
		#password_verify=>http://php.net/manual/en/function.password-verify.php
20163
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
20164
		#備註:
20165
		#無.
20166
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
20167
		unset($conf["authenticate::enCodeStr"]);
20168
 
20169
		#如果執行失敗
20170
		if($enCodeStr["status"]==="false"){
20171
 
20172
			#印出結果
20173
			return $enCodeStr;
20174
 
20175
			}#if end
20176
 
20177
		#解碼取得的內容
20178
		$receivedData=json_decode($enCodeStr["content"]);
20179
 
20180
		#如果有設置 callFunc
20181
		if(isset($receivedData->callFunc)){
20182
 
20183
			#取得要呼叫的函式
20184
			$func=$receivedData->callFunc;
20185
 
20186
			#檢查是否有權限執行該函式
20187
			#函式說明:
20188
			#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
20189
			#回傳結果:
20190
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
20191
			#$result["error"],執行不正常結束的錯訊息陣列.
20192
			#$result["argu"],陣列,使用的參數.
20193
			#必填參數:
20194
			#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
20195
			$conf["self::checkAuth"]["data"]=$conf["data"];
20196
			#$conf["serverSock"],resource,web socket server socket
20197
			$conf["self::checkAuth"]["serverSock"]=$conf["serverSock"];
20198
			#$conf["clientSock"],$resource,web socket client socket
20199
			$conf["self::checkAuth"]["clientSock"]=$conf["clientSock"];
20200
			#$conf["clientInfo"],陣列,web socket client info.
20201
			$conf["self::checkAuth"]["clientInfo"]=$conf["clientInfo"];
20202
			#$conf["clientIndex"],整數.web socket client index.
20203
			$conf["self::checkAuth"]["clientIndex"]=$conf["clientIndex"];
20204
			#$conf["allConn"],陣列,all web socket client info.
20205
			$conf["self::checkAuth"]["allConn"]=$conf["allConn"];
20206
			#$conf["func"],字串,要檢查的是否具備權限的函式.
20207
			$conf["self::checkAuth"]["func"]=$func;
20208
			#可省略參數:
20209
			#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
20210
			#$conf["wsMode"]="true";
20211
			#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
20212
			#$conf["gpgId"]=gnupgId;
20213
			#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
20214
			#$conf["falseAllowFuncPlus"]=array();
20215
			#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
20216
			#$conf["publicAllowFuncPlus"]=array();
20217
			#參考資料:
20218
			#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
20219
			#備註:
20220
			#無.
20221
			$checkAuth=self::checkAuth($conf["self::checkAuth"]);
20222
			unset($conf["self::checkAuth"]);
20223
 
20224
			#如果異常
20225
			if($checkAuth["status"]==="false"){
20226
 
20227
				#回傳結果
20228
				return $checkAuth;
20229
 
20230
				}#if end
20231
 
20232
			#移除使用好的元素
20233
			unset($receivedData["callFunc"]);
20234
 
20235
			#置換data為未加密的內容
20236
			$conf["data"]=json_encode($receivedData);
20237
 
20238
			#呼叫對應的函式
20239
			return eval($func."(&\$conf);");
20240
 
20241
			}#if end
20242
 
20243
		#設置執行失敗
20244
		$result["ststus"]="false";
20245
 
20246
		#回傳結果
20247
		return $result;
20248
 
20249
		}#function callFunc end
20250
 
3 liveuser 20251
	}#class webSock end
20252
 
66 liveuser 20253
?>