Subversion Repositories php-qbpwcf

Rev

Rev 66 | Rev 71 | 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
	#僅能在命令列執行.
10124
	*/
10125
	public static function nativeSocketTcpIpServer(&$conf){
10126
 
10127
		#初始化要回傳的結果
10128
		$result=array();
10129
 
10130
		#取得當前執行的函數名稱
10131
		$result["function"]=__FUNCTION__;
10132
 
10133
		#涵式說明:
10134
		#判斷當前環境為web還是cmd
10135
		#回傳結果:
10136
		#$result,"web"或"cmd"
10137
		if(csInformation::getEnv()==="web"){
10138
 
10139
			#設置執行失敗
10140
			$result["status"]="false";
10141
 
10142
			#設置執行錯誤訊息
10143
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
10144
 
10145
			#回傳結果
10146
			return $result;
10147
 
10148
			}#if end
10149
 
10150
		#取得參數
10151
		$result["argu"]=$conf;
10152
 
10153
		#如果 $conf 不為陣列
10154
		if(gettype($conf)!="array"){
10155
 
10156
			#設置執行失敗
10157
			$result["status"]="false";
10158
 
10159
			#設置執行錯誤訊息
10160
			$result["error"][]="\$conf變數須為陣列形態";
10161
 
10162
			#如果傳入的參數為 null
10163
			if($conf==null){
10164
 
10165
				#設置執行錯誤訊息
10166
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
10167
 
10168
				}#if end
10169
 
10170
			#回傳結果
10171
			return $result;
10172
 
10173
			}#if end
10174
 
10175
		#檢查參數
10176
		#函式說明:
10177
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
10178
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10179
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
10180
		#$result["function"],當前執行的函式名稱.
10181
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
10182
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
10183
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
10184
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
10185
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
10186
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
10187
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
10188
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
10189
		#必填寫的參數:
10190
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
10191
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
10192
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
10193
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
10194
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
10195
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
10196
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
10197
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
10198
		#可以省略的參數:
10199
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
10200
		#$conf["canBeEmptyString"]="false";
10201
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
10202
		#$conf["canNotBeEmpty"]=array();
10203
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
10204
		#$conf["canBeEmpty"]=array();
10205
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
10206
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
10207
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
66 liveuser 10208
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("listenIp","listenPort","wsMode","processFuncs","idleFunc");
3 liveuser 10209
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
66 liveuser 10210
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","array");
3 liveuser 10211
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
68 liveuser 10212
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",null,"false",array("noAuth"),array());
3 liveuser 10213
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
10214
		#$conf["arrayCountEqualCheck"][]=array();
10215
		#參考資料來源:
10216
		#array_keys=>http://php.net/manual/en/function.array-keys.php
10217
		#建議:
10218
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
10219
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
10220
		unset($conf["variableCheck::checkArguments"]);
10221
 
10222
		#如果檢查參數失敗
10223
		if($checkArguments["status"]==="false"){
10224
 
10225
			#設置執行失敗
10226
			$result["status"]="false";
10227
 
10228
			#設置執行錯誤訊息
10229
			$result["error"]=$checkArguments;
10230
 
10231
			#回傳結果
10232
			return $result;
10233
 
10234
			}#if end
10235
 
10236
		#如果檢查參數不通過
10237
		if($checkArguments["passed"]==="false"){
10238
 
10239
			#設置執行失敗
10240
			$result["status"]="false";
10241
 
10242
			#設置執行錯誤訊息
10243
			$result["error"]=$checkArguments;
10244
 
10245
			#回傳結果
10246
			return $result;
10247
 
66 liveuser 10248
			}#if end
3 liveuser 10249
 
10250
		#如果 $conf["listenPort"] 不存在
10251
		if(!isset($conf["listenPort"])){
10252
 
10253
			#用nmap掃port
10254
			#函式說明:
10255
			#掃port的程式
10256
			#回傳結果:
10257
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10258
			#$result["error"],錯誤訊息.
10259
			#$result["function"],當前執行的函數名稱.
10260
			#$result["argu"],使用的參數.
10261
			#$result["content"],掃好可能可以使用的port資訊.
10262
			#必填參數
10263
			#無:
10264
			#可省略參數:
10265
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10266
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10267
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10268
			#$conf["-Pn"]="false";
10269
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10270
			unset($conf["cmd::nmap"]);
10271
 
10272
			#如果掃port失敗
10273
			if($nmap["status"]==="false"){
10274
 
10275
				#設置執行失敗
10276
				$result["status"]="false";
10277
 
10278
				#設置執行錯誤訊息
10279
				$result["error"]=$nmap;
10280
 
10281
				#回傳結果
10282
				return $result;
10283
 
10284
				}#if end
10285
 
10286
			#如果有掃到port
10287
			if(count($nmap["content"])>0){
10288
 
10289
				#找最大的port
10290
				#涵式說明:
10291
				#找最大值,結果會回傳最大值.
10292
				#回傳的結果:
10293
				#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10294
				#$result["error"],錯誤訊息陣列.
10295
				#$result["function"],當前執行的函數名稱.
10296
				#$result["key"],最大值原先的key.
10297
				#$result["value"],最大值的數字.
10298
				#必填的參數:
10299
				$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10300
				$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10301
				unset($conf["math::getMaxValue"]);
10302
 
10303
				#如果找最大port失敗
10304
				if($getMaxValue["status"]==="false"){
10305
 
10306
					#設置執行失敗
10307
					$result["status"]="false";
10308
 
10309
					#設置執行錯誤訊息
10310
					$result["error"]=$getMaxValue;
10311
 
10312
					#回傳結果
10313
					return $result;
10314
 
10315
					}#if end
10316
 
10317
				#設置 $conf["listenPort"] 為最大 port+1
10318
				$conf["listenPort"]=$getMaxValue["value"]+1;
10319
 
10320
				#如果port小於4000,會無法讓nmap偵測到有使用
10321
				if($conf["listenPort"]<4000){
10322
 
10323
					#設為4000
10324
					$conf["listenPort"]="4000";
10325
 
10326
					}#if end
10327
 
66 liveuser 10328
				}#if end
3 liveuser 10329
 
10330
			}#if end
10331
 
10332
		#反之
10333
		else{
10334
 
10335
			#用nmap掃port
10336
			#函式說明:
10337
			#掃port的程式
10338
			#回傳結果:
10339
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10340
			#$result["error"],錯誤訊息.
10341
			#$result["function"],當前執行的函數名稱.
10342
			#$result["argu"],使用的參數.
10343
			#$result["content"],掃好可能可以使用的port資訊.
10344
			#必填參數
10345
			#無:
10346
			#可省略參數:
10347
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10348
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10349
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10350
			#$conf["-Pn"]="false";
10351
			#$conf["fileArgu"],字串,變數__FILE__的內容.
10352
			$conf["cmd::nmap"]["fileArgu"]=$conf["fileArgu"];
10353
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10354
			unset($conf["cmd::nmap"]);
10355
 
10356
			#如果掃port失敗
10357
			if($nmap["status"]==="false"){
10358
 
10359
				#設置執行失敗
10360
				$result["status"]="false";
10361
 
10362
				#設置執行錯誤訊息
10363
				$result["error"]=$nmap;
10364
 
10365
				#回傳結果
10366
				return $result;
10367
 
10368
				}#if end
10369
 
10370
			#如果有掃到port
10371
			if(count($nmap["content"])>0){
10372
 
10373
				#如果要用來建立socket的port已被使用
10374
				if(in_array($conf["listenPort"],$nmap["content"])){
10375
 
10376
					#找最大的port
10377
					#涵式說明:
10378
					#找最大值,結果會回傳最大值.
10379
					#回傳的結果:
10380
					#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10381
					#$result["error"],錯誤訊息陣列.
10382
					#$result["function"],當前執行的函數名稱.
10383
					#$result["key"],最大值原先的key.
10384
					#$result["value"],最大值的數字.
10385
					#必填的參數:
10386
					$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10387
					$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10388
					unset($conf["math::getMaxValue"]);
10389
 
10390
					#如果找最大port失敗
10391
					if($getMaxValue["status"]==="false"){
10392
 
10393
						#設置執行失敗
10394
						$result["status"]="false";
10395
 
10396
						#設置執行錯誤訊息
10397
						$result["error"]=$getMaxValue;
10398
 
10399
						#回傳結果
10400
						return $result;
10401
 
10402
						}#if end
10403
 
10404
					#設置 $conf["listenPort"] 為最大 port+1
10405
					$conf["listenPort"]=$getMaxValue["value"]+1;
10406
 
10407
					#如果port小於4000,會無法讓nmap偵測到有使用
10408
					if($conf["listenPort"]<4000){
10409
 
10410
						#設為4000
10411
						$conf["listenPort"]="4000";
10412
 
10413
						}#if end
10414
 
10415
					}#if end
10416
 
10417
				}#if end
10418
 
10419
			}#else end
10420
 
10421
		#回報任何錯誤
10422
		#error_reporting(E_ALL);
10423
 
10424
		/* Allow the script to hang around waiting for connections. */
10425
		set_time_limit(0);
10426
 
10427
		/* Turn on implicit output flushing so we see what we're getting as it comes in. */
10428
		#ob_implicit_flush();
10429
 
10430
		#設定要listen的主機ip
10431
		$address = $conf["listenIp"];
10432
 
10433
		#設定要listen的port
10434
		$port = $conf["listenPort"];
10435
 
10436
		#重複做,讓socket服務不會結束.
10437
		do{
10438
 
10439
			#如果建立 socket 失敗
10440
			if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){
10441
 
10442
				#印出錯誤訊息
10443
				echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
10444
 
10445
				}#if end
10446
 
10447
			#設置不等待連線與訊息的到來,變成不會卡位
10448
			socket_set_nonblock($sock);
10449
 
10450
			#SOL_SOCKET => socket level
10451
			#SO_REUSEADDR => Reports whether local addresses can be reused. 
10452
			socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
66 liveuser 10453
 
3 liveuser 10454
			#如果 Binds a name to a socket 失敗
10455
			if (@socket_bind($sock, $address, $port) === false){
10456
 
10457
				#儲存錯誤訊息
10458
				$error=socket_strerror(socket_last_error($sock));
10459
 
10460
				#印出錯誤訊息
10461
				echo "socket_bind() failed: reason: " .$error. PHP_EOL;
10462
 
10463
				#判斷錯誤訊息的是否有 "Address already in use"
10464
				#函式說明:
10465
				#檢查字串裡面有無指定的關鍵字
10466
				#回傳的結果:
10467
				#$result["status"],"true"代表執行成功,"false"代表執行失敗。
10468
				#$result["error"],錯誤訊息
10469
				#$result["function"],當前執行的函數名稱.
10470
				#$result["founded"],是否找到關鍵字,"true"代表有找到關鍵字;"false"代表沒有找到關鍵字。
10471
				#$result["keyWordCount"],找到的關鍵字數量.
10472
				#必填的參數:
10473
				$conf["search::findKeyWord"]["keyWord"]="Address already in use";#想要搜尋的關鍵字
10474
				$conf["search::findKeyWord"]["string"]=$error;#要被搜尋的字串內容
10475
				#可省略的參數:
10476
				#$conf["completeEqual"]="true";#是否內容要完全符合,不能多出任何不符合的內容,預設為不需要完全符合。
10477
				$findKeyWord=search::findKeyWord($conf["search::findKeyWord"]);
10478
				unset($conf["search::findKeyWord"]);
10479
 
10480
				#如果解析錯誤訊息失敗
10481
				if($findKeyWord["status"]==="false"){
10482
 
10483
					#設置執行失敗
10484
					$result["status"]="false";
10485
 
10486
					#設置執行錯誤訊息
10487
					$result["error"]=$getMeetConditionsString;
10488
 
10489
					#回傳結果
10490
					return $result;
10491
 
10492
					}#if end
10493
 
10494
				#如果錯誤原因為socket的port已經被使用了.
10495
				if($findKeyWord["founded"]==="true"){
10496
 
10497
					#port加1
10498
					$port++;
10499
 
10500
					#再次建立socket服務
10501
					continue;
10502
 
10503
					}#if end
10504
 
10505
				#反之
10506
				else{
10507
 
10508
					#結束程式
10509
					exit;
10510
 
10511
					}#else 
10512
 
10513
				}#if end
10514
 
10515
			#如果 listen socket 經過嘗試5次後仍然失敗
10516
			if (socket_listen($sock, 5) === false) {
10517
 
10518
				#印出錯誤訊息
10519
				echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;
10520
 
10521
				}#if end
10522
 
10523
			#初始化儲存已經連線到 socket service 的服務
10524
			$connections=array();
10525
 
66 liveuser 10526
			#初始化 idle 時要呼叫的函式名稱陣列
10527
			$idleFunc=array();
10528
 
3 liveuser 10529
			#提示 listen 的 ip 與 port
10530
			echo "Listen to:".$address.":".$port.PHP_EOL;
10531
 
10532
			#重複做,等待別人連線.
10533
			do{
10534
 
10535
				#初始化儲存有需要處理的socket連線
10536
				$read = array();
10537
 
10538
				#初始化一開始建立的socket為要處理的項目
10539
				$read[] = $sock;
10540
 
10541
				#有幾個連線就執行幾次
10542
				foreach($connections as $conForSockSelect){
10543
 
10544
					#產生要合併的陣列
10545
					$arrayToMerage=array($conForSockSelect["connect"]);
10546
 
10547
					#合併陣列
10548
					$read = array_merge($read,$arrayToMerage);
10549
 
10550
					}#foreach end
10551
 
10552
				#從socket物件陣列($read)裡面取出有需要處理連線的socket物件.
10553
				#Set up a blocking call to socket_select
10554
				$write=array();
10555
				$except=array();
10556
				$tv_sec = 1;
10557
				if(socket_select($read, $write, $except, $tv_sec) < 1){
10558
 
10559
					#沒有事情發生
10560
					echo ".";
10561
 
10562
					#函式說明:
10563
					#加密 handshake 後要傳送的訊息 
10564
					#回傳結果:
10565
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10566
					#$result["error"],執行不正常結束的錯訊息陣列.
10567
					#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
10568
					#$result["argu"],陣列,使用的參數.
10569
					#必填參數:
10570
					#$conf["text"],字串,要加密的訊息.
10571
					$conf["webSock::encode"]["text"]=""; 
10572
					#可省略參數:
10573
					#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
10574
					$conf["webSock::encode"]["ping"]="true";
10575
					#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
10576
					#$conf["frames"]=array();
10577
					#參考資料:
10578
					#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
10579
					#備註:
10580
					#無.
10581
					$encode=webSock::encode($conf["webSock::encode"]);
10582
					unset($conf["webSock::encode"]);
10583
 
10584
					#debug
10585
					#var_dump(__LINE__,$encode);
10586
 
10587
					#如果執行失敗
10588
					if($encode["status"]==="false"){
10589
 
10590
						#設置執行失敗
10591
						$result["status"]="false";
10592
 
10593
						#設置執行錯誤訊息
10594
						$result["error"]=$encode;
66 liveuser 10595
 
3 liveuser 10596
						#回傳結果
10597
						return $result;
10598
 
10599
						}#if end
10600
 
10601
					#針對每個連線的 client
10602
					foreach($connections as $client){
10603
 
10604
						#如果有 last ping time
10605
						if(isset($client["lastPongTime"])){
10606
 
10607
							#如果小於5秒沒有收到pong
10608
							if(time()-$client["lastPongTime"]<5){
10609
 
66 liveuser 10610
								#看下一個連線,亦即視為用戶已經斷線.
3 liveuser 10611
								continue;
10612
 
10613
								}#if end
10614
 
10615
							}#if end
10616
 
10617
						#取得用戶socket
10618
						$clientSock=$client["connect"];
10619
 
10620
						#傳送ping給client
10621
						$socket_write=socket_write($clientSock, $encode["content"][0], strlen($encode["content"][0]));
10622
 
10623
						#debug
10624
						#var_dump(__LINE__,"send ping",$socket_write,socket_strerror(socket_last_error($clientSock)));
10625
 
10626
						}#foreach end
10627
 
66 liveuser 10628
					#如果有idle時要做的事情
10629
					if(count($conf["idleFunc"])>0){
10630
 
10631
						#取得idleFunc設定
10632
						$idleFunc=$conf["idleFunc"];
10633
 
10634
						#移除初始的idelFunc設定
10635
						unset($conf["idleFunc"]);
10636
 
10637
						}#if end
10638
 
10639
					#如果有idle時要做的事情
10640
					if(count($idleFunc)>0){
10641
 
10642
						#針對每個要執行的函式
10643
						foreach($idleFunc as $if){
10644
 
10645
							#設置要給予函式的參數陣列
10646
							$param=array("idleFunc"=>&$idleFunc,"serverSock"=>&$sock,"allConn"=>&$connections);
10647
 
10648
							#初始化給予 call_user_func_array 的第2個參數
10649
							$params=array();
10650
 
10651
							#設置呼叫函式 $if 時要傳遞的參數為一個 $param
10652
							$params[]=&$param;
10653
 
10654
							#呼叫函式 $if 與要傳遞的參數.
10655
							$result=call_user_func_array($if,$params);
10656
 
10657
							}#foreach end
10658
 
10659
						}#if end
10660
 
10661
					#如果有php程式要於idle時執行
10662
					while(count($php2runWhenIdle)>0){
10663
 
10664
						#取得要執行的 php code
10665
						$phpCode=array_shift($php2runWhenIdle);
10666
 
10667
						#...
10668
 
10669
						}#while end
10670
 
3 liveuser 10671
					#下一輪
10672
					continue;
10673
 
10674
					}#if end
10675
 
10676
				#有事情發生
10677
				echo "something happen".PHP_EOL;
66 liveuser 10678
 
3 liveuser 10679
				#如果有socket要處理
10680
				if(in_array($sock,$read)){
10681
 
10682
					#如果有接收到 socket 連線
10683
					if (($msgsock = socket_accept($sock)) !== false) {
66 liveuser 10684
 
3 liveuser 10685
						#初始化不是既有的 sock
10686
						$existSock=false;
66 liveuser 10687
 
3 liveuser 10688
						#尋找是哪個 socket
10689
						for($i=0;$i<count($connections);$i++){
10690
 
10691
							#如果是既有的 sock
10692
							if($connections[$i]["connect"]===$msgsock){
10693
 
10694
								#設置是既有的 sock
10695
								$existSock=true;
10696
 
10697
								}#if end
10698
 
10699
							}#for end
10700
 
10701
						#如果該 socket 是新的
10702
						if(!$existSock){
10703
 
10704
							#重複做
10705
							do{
66 liveuser 10706
 
3 liveuser 10707
								#亂數產生連線id
10708
								#涵式說明:
10709
								#建立以圖片(PNG格式)呈現的驗證碼.
10710
								#回傳的解果:
10711
								#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
10712
								#$result["error"],錯誤訊息.
10713
								#$result["function"],檔前執行的函數名稱.
10714
								#$result["randNumberWord"],傳驗證碼的內容.
10715
								#$result["imgAddress"],圖片的位置與名稱.
10716
								#必填的參數:
10717
								#$conf["imgAddressAndName"],字串,爲驗證碼圖片儲存的位置與名稱,副檔名程式會自動產生
10718
								$conf["authenticate::validationCode"]["imgAddressAndName"]="no used!";
10719
								#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
10720
								$conf["authenticate::validationCode"]["fileArgu"]=$conf["fileArgu"];
10721
								#可省略的參數:
10722
								#$conf["num"],字串,爲驗證碼的位數,請輸入阿拉伯數字,預設為"8"位數.
10723
								#$conf["num"]="8";
10724
								#$conf["disableImg"],字串,是否要取消驗證碼圖片的輸出,"true"為要取消,預設為"false"為不取消
10725
								$conf["authenticate::validationCode"]["disableImg"]="true";
10726
								#$conf["imgToData"],字串,預設為"true"代表將圖片轉存成base64圖片,並將原始圖片移除;反之為"false"
10727
								#$conf["authenticate::validationCode"]["imgToData"]="true";
10728
								$validationCode=authenticate::validationCode($conf["authenticate::validationCode"]);
10729
								unset($conf["authenticate::validationCode"]);
10730
 
10731
								#如果產生亂數失敗
10732
								if($validationCode["status"]==="false"){
10733
 
10734
									#設置執行失敗
10735
									$result["status"]="false";
10736
 
10737
									#設置執行錯誤訊息
10738
									$result["error"]=$validationCode;
10739
 
10740
									#回傳結果
10741
									return $result;
10742
 
10743
									}#if end
10744
 
10745
								#如果不存在既有的連線資訊
10746
								if(count($connections)<1){
10747
 
10748
									#跳出迴圈
10749
									break;
10750
 
10751
									}#if end
10752
 
10753
								#初始化連線id的陣列
10754
								$idArray=array();
10755
 
10756
								#針對既有的連線
10757
								foreach($connections as $exist_conn){
10758
 
10759
									#儲存連線id
10760
									$idArray[]=$exist_conn["id"];
10761
 
10762
									}#foreach end
10763
 
10764
								}#do end
10765
 
10766
							#檢查id有無重複
10767
							while(in_array($validationCode["randNumberWord"],$idArray));
66 liveuser 10768
 
10769
							#如果不是 ws 模式
3 liveuser 10770
							if($conf["wsMode"]==="false"){
66 liveuser 10771
 
3 liveuser 10772
								#儲存連線到陣列裡面
10773
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array());
66 liveuser 10774
 
3 liveuser 10775
								}#if end
66 liveuser 10776
 
3 liveuser 10777
							#如果是 ws 模式
10778
							if($conf["wsMode"]==="true"){
66 liveuser 10779
 
3 liveuser 10780
								#儲存連線到陣列裡面
10781
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array(),"handshaked"=>"false","unmask"=>"false","userAgent"=>"false","3rn"=>0,"receivedMsgFromServer"=>array());
66 liveuser 10782
 
3 liveuser 10783
								}#if end
66 liveuser 10784
 
3 liveuser 10785
							#debug,提示 Server 給予的新 Id
10786
							echo "new connection:".PHP_EOL;
10787
 
10788
							#初始化連線後要回傳的訊息
10789
							$msg="";
66 liveuser 10790
 
3 liveuser 10791
							#如果不是 ws 模式
10792
							if($conf["wsMode"]!=="true"){
10793
 
10794
								#提示client連上線後得到的訊息
10795
								$msg = $msg.PHP_EOL."Welcome to the PHP Test Server.".PHP_EOL;
10796
								$msg = $msg."To quit, type 'quit'. To shut down the server type 'shutdown'.".PHP_EOL;
10797
								socket_write($msgsock, $msg, strlen($msg));
10798
 
10799
								}#if end
10800
 
10801
							}#if end
10802
 
10803
						}#if end
10804
 
10805
					}#if end
10806
 
10807
				#重新排序 $connections
10808
				#函式說明:
10809
				#將陣列的key重新排序,然後回傳,以便後續存取,也可以指定key的內容,但一定要跟元素數量相同。
10810
				#回傳的解果:
10811
				#$result["status"],執行是否成功,"true"代表成功,"false"代表失敗.
10812
				#$result["error"],執行錯誤的訊息.
10813
				#$result["function"],當前執行的函數名稱.
10814
				#$result["dataContent"],儲存陣列元素的內容.
10815
				#若指定了key的名稱,則 $result["dataContent"] 會變成 $result["dataContent"]["指定的key名稱"]
10816
				#$result["dataCount"],儲存陣列元素的數量。
10817
				#必填的參數:
10818
				$conf["arrays::createV2"]["arrayContent"]=$connections;#陣列變數
10819
				#可省略的參數:
10820
				#$conf["specifiesKeyArray"]=array();#指定key的名稱,須與$conf["arrayContent"]的元素數量相同
10821
				$createV2=arrays::createV2($conf["arrays::createV2"]);
10822
				unset($conf["arrays::createV2"]);
10823
 
10824
				#如果重新排序失敗
10825
				if($createV2["status"]==="false"){
10826
 
10827
					#設置執行失敗
10828
					$result["status"]="false";
10829
 
10830
					#設置執行錯誤訊息
10831
					$result["error"]=$createV2;
10832
 
10833
					#回傳結果
10834
					return $result;
10835
 
10836
					}#if end
10837
 
10838
				#取得重新排序好的陣列
10839
				$connections=$createV2["dataContent"];
10840
 
10841
				#依據每個 client 的連線
10842
				foreach($connections as $conIndex => $con){
10843
 
10844
					#如果有要處理的socket連線項目
10845
					if(in_array($con["connect"], $read)){
10846
 
10847
						#如果不存在 handshaked
10848
						if(!isset($con["handshaked"])){
10849
 
10850
							#預設為 "false"
10851
							$con["handshaked"]="false";
10852
 
10853
							}#if end
10854
 
10855
						#如果有 handshaked
10856
						if($con["handshaked"]==="true"){
66 liveuser 10857
 
10858
							#讀取內容
3 liveuser 10859
							$buf = @socket_read($con["connect"], 2048, PHP_BINARY_READ);
10860
 
10861
							#設置要 unmask
10862
							$connections[$conIndex]["unmask"]="true";
66 liveuser 10863
 
10864
							#設置尚未 auth
10865
							$connections[$conIndex]["auth"]="false";
3 liveuser 10866
 
10867
							}#if end
66 liveuser 10868
 
3 liveuser 10869
						#反之
10870
						else{
10871
 
10872
							#讀取內容
10873
							$buf = @socket_read($con["connect"], 2048, PHP_NORMAL_READ);
10874
 
10875
							}#else end
10876
 
10877
						#如果讀取出錯
10878
						if($buf===false){
10879
 
10880
							#印出錯誤訊息
10881
							echo "socket_recv() failed: reason: " . socket_strerror(socket_last_error($con["connect"])) . PHP_EOL;
10882
 
10883
							#移除該連線的資料
10884
							unset($connections[$conIndex]);	
10885
 
10886
							#跳到下一輪
10887
							continue;
10888
 
10889
							}#if end
10890
 
10891
						#如果收到的資料長度為 0 bytes
10892
						if($buf===""){
10893
 
10894
							#關閉 socket msg
10895
							socket_close($con["connect"]);	
10896
 
10897
							#移除該連線的資料
10898
							unset($connections[$conIndex]);
10899
 
10900
							#跳到下一輪
10901
							continue;
10902
 
10903
							}#if end
10904
 
10905
						#印出接受的非換行符號內容
10906
						if($buf!==PHP_EOL){
10907
 
10908
							#debug
10909
							echo "received:".$buf.PHP_EOL;
66 liveuser 10910
 
3 liveuser 10911
							}#if end
10912
 
10913
						#如果無 handshaked
10914
						if($con["handshaked"]!=="true"){
10915
 
10916
							#清除換行字元
10917
							$buf=trim($buf);
10918
 
10919
							}#if end
10920
 
10921
						#web socket mode
10922
						if($conf["wsMode"]==="true"){
10923
 
10924
							#如果不需要 unmask
10925
							if($connections[$conIndex]["unmask"]==="false"){
66 liveuser 10926
 
3 liveuser 10927
								#提示還不用 unmask
10928
								echo "don't need unmask now".PHP_EOL;
66 liveuser 10929
 
3 liveuser 10930
								#重新計數 \r\n
10931
								$connections[$conIndex]["3rn"]=0;
66 liveuser 10932
 
3 liveuser 10933
								}#if end
10934
 
10935
							}#if end
66 liveuser 10936
 
3 liveuser 10937
						#如果有內容(不是換行符號)
10938
						$st=trim($buf);
10939
 
10940
						#如果是 ws 模式
10941
						if($conf["wsMode"]==="true"){
10942
 
10943
							#如果尚未 handshake
10944
							if($connections[$conIndex]["handshaked"]==="false"){
66 liveuser 10945
 
3 liveuser 10946
								#提示 server 在檢查 handshake 用的 key 是否存在.
10947
								echo "check Sec-WebSocket-Key ..".PHP_EOL;
66 liveuser 10948
 
3 liveuser 10949
								#handshake
10950
								#如果收到的內容$buf含有 Sec-WebSocket-Key: 字串開頭,擷取後面的內容存到$matchs裡面.
10951
								if(preg_match("/Sec-WebSocket-Key: (.*)/",$buf,$matchs)){
66 liveuser 10952
 
3 liveuser 10953
									#提示serve在handshake
10954
									echo "do handshake...".PHP_EOL.PHP_EOL;
66 liveuser 10955
 
3 liveuser 10956
									#handshake
10957
									$key = $matchs[1].'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
10958
									$key =  base64_encode(sha1($key, true)); 
66 liveuser 10959
 
3 liveuser 10960
									#設置 handshake 的 header
10961
									$headers = 
10962
									"HTTP/1.1 101 Switching Protocols".PHP_EOL.
10963
									"Upgrade: websocket".PHP_EOL.
10964
									"Connection: Upgrade".PHP_EOL.
10965
									"Sec-WebSocket-Accept: ".$key.PHP_EOL.
10966
									"X-Powered-By: qbpwcf".PHP_EOL.
10967
									PHP_EOL;
66 liveuser 10968
 
3 liveuser 10969
									#傳送header給client
10970
									socket_write($con["connect"], $headers);
66 liveuser 10971
 
3 liveuser 10972
									#儲存server傳送給client的訊息
10973
									#$connections[$conIndex]["receivedMsgFromServer"][]=$headers;
66 liveuser 10974
 
3 liveuser 10975
									#提示serve handshake 完畢
10976
									echo "handshak done...".PHP_EOL;
66 liveuser 10977
 
3 liveuser 10978
									#設置已經 handshake
10979
									$connections[$conIndex]["handshaked"]="true";
66 liveuser 10980
 
3 liveuser 10981
									}#if end
10982
 
10983
								}#if end
10984
 
10985
							}#if end
10986
 
10987
						#如果是 ws 模式
10988
						if($conf["wsMode"]==="true"){
66 liveuser 10989
 
3 liveuser 10990
							#如果尚未 handshake 過
10991
							if($connections[$conIndex]["handshaked"]==="false"){
10992
 
10993
								#跳過
10994
								continue;
10995
 
10996
								}#if end
66 liveuser 10997
 
10998
							#如果還不用要 unmask
3 liveuser 10999
							if($connections[$conIndex]["unmask"]==="false"){
11000
 
11001
								#跳過
11002
								continue;
11003
 
11004
								}#if end
11005
 
11006
							}#if end
11007
 
11008
						#如果是 ws 模式
11009
						if($conf["wsMode"]==="true"){
66 liveuser 11010
 
3 liveuser 11011
							#debug
11012
							#var_dump(__LINE__,$connections[$conIndex]);
66 liveuser 11013
 
3 liveuser 11014
							#如果已經 handshake 過
11015
							if($connections[$conIndex]["handshaked"]==="true"){
11016
 
11017
								#如果要 unmask	
11018
								if($connections[$conIndex]["unmask"]==="true"){
11019
 
11020
									#如果收到的訊息不為空
11021
									if(!empty($buf)){
66 liveuser 11022
 
3 liveuser 11023
										echo "start unmask...".PHP_EOL;
11024
 
11025
										#debug
11026
										#var_dump(__LINE__,$buf);
11027
 
11028
										#解密 $buf
11029
										#回傳結果:
11030
										#$result["function"],當前函式的名稱.
11031
										#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
11032
										#$result["content"],unmask後的內容.
11033
										#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong.
11034
										#$result["error"],錯誤訊息陣列.
11035
										$conf["self::unmask"]["payload"]=$buf;
11036
										#$conf["self::unmask"]["debug"]="true";
11037
										$buf=webSock::unmask($conf["self::unmask"]);
11038
										unset($conf["self::unmask"]);
11039
 
11040
										#如果執行失敗
11041
										if($buf["status"]==="false"){
66 liveuser 11042
 
3 liveuser 11043
											#印出結果
11044
											var_dump($buf);
11045
 
11046
											#結束執行
11047
											exit;
66 liveuser 11048
 
3 liveuser 11049
											}#if end
11050
 
11051
										#如果是 ping 的回應 pong
11052
										if($buf["type"]==="pong"){
66 liveuser 11053
 
3 liveuser 11054
											#提示收到 pong
11055
											echo "got pong".PHP_EOL;
11056
 
11057
											#更新的連線的 last pong time
11058
											$connections[$conIndex]["lastPongTime"]=time();
11059
 
11060
											#換處理下一則訊息
11061
											continue;
66 liveuser 11062
 
3 liveuser 11063
											}#if end
11064
 
11065
										#如果不是 web socket frame
11066
										if($buf["type"]==="invalid"){
11067
 
11068
											#提示收到非 web socket frame
11069
											echo "not web socket frame".PHP_EOL;
11070
 
11071
											#debug
11072
											#var_dump(__LINE__,$buf);
11073
 
11074
											#換處理下一則訊息
11075
											continue;
11076
 
11077
											}#if end
11078
 
11079
										#取得umask後的內容
11080
										$buf=$buf["content"];
11081
 
11082
										#提示 unmask 結束
11083
										echo "end unmask()".PHP_EOL;
11084
 
11085
										#提示 web socket server 收到訊息的長度(bytes)
11086
										echo "Server receviced plain content(".strlen($buf)."):".PHP_EOL;
11087
 
11088
										#提示 web socket server 收到的訊息內容
11089
										echo $buf.PHP_EOL;
11090
 
11091
										}#if end
11092
 
11093
									}#if end
11094
 
11095
								}#if end
11096
 
11097
							}#if end
66 liveuser 11098
 
11099
						/*
11100
 
3 liveuser 11101
						#如果收到的是 id?
11102
						if($buf === 'id?'){
11103
 
66 liveuser 11104
							#如果尚未認證
11105
							if($connections[$conIndex]["auth"]==="false"){
11106
 
11107
								#設置要回傳的訊息
11108
								$talkback="permission denied";
11109
 
11110
								}#if end
11111
 
11112
							else{
11113
 
11114
								#設置要回傳的訊息
11115
								$talkback=$connections[$conIndex]["id"];
11116
 
11117
								}#else end
3 liveuser 11118
 
11119
							#debug
11120
							#var_dump(__LINE__,$talkback);
11121
 
11122
							#json encode 要回傳的訊息
11123
							$talkback=json_encode($talkback);
11124
 
11125
							#debug
11126
							#var_dump(__LINE__,$talkback);
11127
 
11128
							#如果是 ws 模式
11129
							if($conf["wsMode"]==="true"){
11130
 
11131
								#如果已經 handshake 過
11132
								if($connections[$conIndex]["handshaked"]==="true"){
11133
 
11134
									#如果要 unmask	
11135
									if($connections[$conIndex]["unmask"]==="true"){
11136
 
11137
										#函式說明:
11138
										#加密 handshake 後要傳送的訊息 
11139
										#回傳結果:
11140
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11141
										#$result["error"],執行不正常結束的錯訊息陣列.
11142
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11143
										#$result["argu"],陣列,使用的參數.
11144
										#必填參數:
11145
										#$conf["text"],字串,要加密的訊息.
11146
										$conf["webSock::encode"]["text"]=$talkback; 
11147
										#可省略參數:
11148
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11149
										#$conf["payloadIsBin"]="false";
11150
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11151
										#$conf["ping"]="false";
11152
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11153
										#$conf["pong"]="false";
11154
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11155
										#$conf["frames"]=array();
11156
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11157
										#$conf["mask"]="false";
11158
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11159
										#$conf["debug"]="false";
11160
										#參考資料:
11161
										#無.
11162
										#備註:
11163
										#目前$conf["text"]長度超過125會出錯.
11164
										$talkback=webSock::encode($conf["webSock::encode"]);
11165
										unset($conf["webSock::encode"]);
11166
 
11167
										#如果執行失敗
11168
										if($talkback["status"]==="false"){
11169
 
11170
											#印出結果
11171
											var_dump($talkback);
11172
 
11173
											#結束執行
11174
											exit;
11175
 
11176
											}#if end
11177
 
11178
										#debug
11179
										#var_dump(__LINE__,$talkback);
11180
 
11181
										}#if end
11182
 
11183
									}#if end
11184
 
11185
								}#if end
11186
 
11187
							#反之不為 web socket 訊息
11188
							else{
11189
 
11190
								#儲存成只有一個訊息
11191
								$talkback["content"][]=$talkback;
11192
 
11193
								}#else
11194
 
11195
							#針對每個訊息的分段
11196
							foreach($talkback["content"] as $msg){
11197
 
11198
								#debug
11199
								var_dump(__LINE__,$msg);
11200
 
11201
								#回傳訊息
11202
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11203
 
11204
								#debug
11205
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11206
 
11207
								}#foreach end
11208
 
11209
							#跳到下一輪
11210
							continue;
11211
 
11212
							}#if end
11213
 
66 liveuser 11214
						*/	
11215
 
11216
						/*
11217
 
3 liveuser 11218
						#如果收到的是 ids?
11219
						if($buf === 'ids?'){
11220
 
66 liveuser 11221
							#如果尚未認證
11222
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11223
 
66 liveuser 11224
								#設置要回傳的訊息
11225
								$talkback=json_encode("permission denied");
11226
 
11227
								}#if end
3 liveuser 11228
 
66 liveuser 11229
							#反之
11230
							else{
3 liveuser 11231
 
66 liveuser 11232
								#設置要回傳的訊息
11233
								$talkback=array();
3 liveuser 11234
 
66 liveuser 11235
								#針對每個連線
11236
								foreach($connections as $conIndex_ids => $con_ids){
11237
 
11238
									#如果不是自己
11239
									if($con_ids["connect"]!==$connections[$conIndex]["connect"]){
11240
 
11241
										#記錄其他人的id
11242
										$talkback[]=$con_ids["id"];
11243
 
11244
										}#if end
11245
 
11246
									}#foreach end
11247
 
11248
								#json encode要回傳的id陣列
11249
								$talkback=json_encode($talkback);
3 liveuser 11250
 
66 liveuser 11251
								}#else end
11252
 
3 liveuser 11253
							#如果是 ws 模式
11254
							if($conf["wsMode"]==="true"){
11255
 
11256
								#如果已經 handshake 過
11257
								if($connections[$conIndex]["handshaked"]==="true"){
11258
 
66 liveuser 11259
									#如果要 unmask
3 liveuser 11260
									if($connections[$conIndex]["unmask"]==="true"){
11261
 
11262
										#函式說明:
11263
										#加密 handshake 後要傳送的訊息 
11264
										#回傳結果:
11265
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11266
										#$result["error"],執行不正常結束的錯訊息陣列.
11267
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11268
										#$result["argu"],陣列,使用的參數.
11269
										#必填參數:
11270
										#$conf["text"],字串,要加密的訊息.
11271
										$conf["webSock::encode"]["text"]=$talkback; 
11272
										#可省略參數:
11273
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11274
										#$conf["payloadIsBin"]="false";
11275
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11276
										#$conf["ping"]="false";
11277
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11278
										#$conf["pong"]="false";
11279
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11280
										#$conf["frames"]=array();
11281
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11282
										#$conf["mask"]="false";
11283
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11284
										#$conf["debug"]="false";
11285
										#參考資料:
11286
										#無.
11287
										#備註:
11288
										#目前$conf["text"]長度超過125會出錯.
11289
										$talkback=webSock::encode($conf["webSock::encode"]);
11290
										unset($conf["webSock::encode"]);
11291
 
11292
										#如果執行失敗
11293
										if($talkback["status"]==="false"){
11294
 
11295
											#印出結果
11296
											var_dump($talkback);
11297
 
11298
											#結束執行
11299
											exit;
11300
 
11301
											}#if end
11302
 
11303
										#debug
11304
										#var_dump(__LINE__,$talkback);
11305
 
11306
										}#if end
11307
 
11308
									}#if end
11309
 
11310
								}#if end
11311
 
11312
							#反之不為 web socket 訊息
11313
							else{
11314
 
11315
								#儲存成只有一個訊息
11316
								$talkback["content"][]=$talkback;
11317
 
11318
								}#else
11319
 
11320
							#針對每個訊息的分段
11321
							foreach($talkback["content"] as $msg){
11322
 
11323
								#回傳訊息
11324
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11325
 
11326
								#debug
11327
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11328
 
11329
								}#foreach end
11330
 
11331
							#跳到下一輪
11332
							continue;
11333
 
11334
							}#if end
11335
 
11336
						#如果收到 "talkTo?"
11337
						if($buf==="talkTo?"){
11338
 
66 liveuser 11339
							#如果尚未認證
11340
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11341
 
66 liveuser 11342
								#設置要回傳的訊息
11343
								$talkback=json_encode("permission denied");
11344
 
11345
								}#if end
11346
 
11347
							#反之
11348
							else{
11349
 
11350
								#初始化要講話的id陣列
11351
								$talkback=array();
3 liveuser 11352
 
66 liveuser 11353
								#有幾個要講話的人就執行幾次
11354
								foreach($connections[$conIndex]["talkTo"] as $to){
11355
 
11356
									#串街要講話的人
11357
									$talkback[]=$to;
11358
 
11359
									}#foreach end
3 liveuser 11360
 
66 liveuser 11361
								#設置要回傳的訊息
11362
								$talkback=json_encode($talkback).PHP_EOL;
3 liveuser 11363
 
66 liveuser 11364
								}#else end
3 liveuser 11365
 
11366
							#如果是 ws 模式
11367
							if($conf["wsMode"]==="true"){
11368
 
11369
								#如果已經 handshake 過
11370
								if($connections[$conIndex]["handshaked"]==="true"){
11371
 
11372
									#如果要 unmask	
11373
									if($connections[$conIndex]["unmask"]==="true"){
11374
 
11375
										#函式說明:
11376
										#加密 handshake 後要傳送的訊息 
11377
										#回傳結果:
11378
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11379
										#$result["error"],執行不正常結束的錯訊息陣列.
11380
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11381
										#$result["argu"],陣列,使用的參數.
11382
										#必填參數:
11383
										#$conf["text"],字串,要加密的訊息.
11384
										$conf["webSock::encode"]["text"]=$talkback; 
11385
										#可省略參數:
11386
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11387
										#$conf["payloadIsBin"]="false";
11388
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11389
										#$conf["ping"]="false";
11390
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11391
										#$conf["pong"]="false";
11392
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11393
										#$conf["frames"]=array();
11394
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11395
										#$conf["mask"]="false";
11396
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11397
										#$conf["debug"]="false";
11398
										#參考資料:
11399
										#無.
11400
										#備註:
11401
										#目前$conf["text"]長度超過125會出錯.
11402
										$talkback=webSock::encode($conf["webSock::encode"]);
11403
										unset($conf["webSock::encode"]);
11404
 
11405
										#如果執行失敗
11406
										if($talkback["status"]==="false"){
11407
 
11408
											#印出結果
11409
											var_dump($talkback);
11410
 
11411
											#結束執行
11412
											exit;
11413
 
11414
											}#if end
11415
 
11416
										#debug
11417
										#var_dump(__LINE__,$talkback);
11418
 
11419
										}#if end
11420
 
11421
									}#if end
11422
 
11423
								}#if end
11424
 
11425
							#反之不為 web socket 訊息
11426
							else{
11427
 
11428
								#儲存成只有一個訊息
11429
								$talkback["content"][]=$talkback;
11430
 
11431
								}#else
11432
 
11433
							#針對每個訊息的分段
11434
							foreach($talkback["content"] as $msg){
11435
 
11436
								#回傳訊息
11437
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11438
 
11439
								#debug
11440
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11441
 
11442
								}#foreach end
11443
 
11444
							#跳到下一輪
11445
							continue;
11446
 
11447
							}#if end
11448
 
11449
						#如果收到的$buf長度大於 "talkTo:"
11450
						if(strlen($buf)>strlen("talkTo:")){
11451
 
11452
							#如果收到開頭為 "talkTo:"
11453
							#涵式說明:
11454
							#取得符合特定字首與字尾的字串
11455
							#回傳的結果:
11456
							#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
11457
							#$result["function"],當前執行的函數名稱.
11458
							#$result["error"],錯誤訊息陣列.
11459
							#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
11460
							#$result["returnString"],爲符合字首條件的字串內容。
11461
							#必填參數:
11462
							#$conf["checkString"],字串,要檢查的字串.
11463
							$conf["search::getMeetConditionsString"]["checkString"]=$buf;
11464
							#可省略參數:
11465
							#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
11466
							$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
11467
							#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
11468
							#$conf["tailWord"]="";
11469
							#參考資料:
11470
							#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
11471
							$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
11472
							unset($conf["search::getMeetConditionsString"]);
11473
 
11474
							#如果選找前置字串 "talkTo:" 失敗
11475
							if($getMeetConditionsString["status"]==="false"){
11476
 
11477
								#設置執行失敗
11478
								$result["status"]="false";
11479
 
11480
								#設置執行錯誤訊息
11481
								$result["error"]=$getMeetConditionsString;
11482
 
11483
								#回傳結果
11484
								return $result;
11485
 
11486
								}#if end
11487
 
11488
							#如果存在 "talkTo:" 前置字串
11489
							if($getMeetConditionsString["founded"]==="true"){
11490
 
66 liveuser 11491
								#如果尚未認證
11492
								if($connections[$conIndex]["auth"]==="false"){
11493
 
11494
									#設置要回傳的訊息
11495
									$talkback=json_encode("permission denied");
11496
 
11497
									#如果是 ws 模式
11498
									if($conf["wsMode"]==="true"){
11499
 
11500
										#如果已經 handshake 過
11501
										if($connections[$conIndex]["handshaked"]==="true"){
11502
 
11503
											#如果要 unmask	
11504
											if($connections[$conIndex]["unmask"]==="true"){
11505
 
11506
												#函式說明:
11507
												#加密 handshake 後要傳送的訊息 
11508
												#回傳結果:
11509
												#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11510
												#$result["error"],執行不正常結束的錯訊息陣列.
11511
												#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11512
												#$result["argu"],陣列,使用的參數.
11513
												#必填參數:
11514
												#$conf["text"],字串,要加密的訊息.
11515
												$conf["webSock::encode"]["text"]=$talkback; 
11516
												#可省略參數:
11517
												#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11518
												#$conf["payloadIsBin"]="false";
11519
												#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11520
												#$conf["ping"]="false";
11521
												#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11522
												#$conf["pong"]="false";
11523
												#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11524
												#$conf["frames"]=array();
11525
												#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11526
												#$conf["mask"]="false";
11527
												#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11528
												#$conf["debug"]="false";
11529
												#參考資料:
11530
												#無.
11531
												#備註:
11532
												#目前$conf["text"]長度超過125會出錯.
11533
												$talkback=webSock::encode($conf["webSock::encode"]);
11534
												unset($conf["webSock::encode"]);
11535
 
11536
												#如果執行失敗
11537
												if($talkback["status"]==="false"){
11538
 
11539
													#印出結果
11540
													var_dump($talkback);
11541
 
11542
													#結束執行
11543
													exit;
11544
 
11545
													}#if end
11546
 
11547
												#debug
11548
												#var_dump(__LINE__,$talkback);
11549
 
11550
												}#if end
11551
 
11552
											}#if end
11553
 
11554
										}#if end
11555
 
11556
									#反之不為 web socket 訊息
11557
									else{
11558
 
11559
										#儲存成只有一個訊息
11560
										$talkback["content"][]=$talkback;
11561
 
11562
										}#else
11563
 
11564
									#針對每個訊息的分段
11565
									foreach($talkback["content"] as $msg){
11566
 
11567
										#回傳訊息
11568
										$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11569
 
11570
										#debug
11571
										#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11572
 
11573
										}#foreach end
11574
 
11575
									#跳到下一輪
11576
									continue;
11577
 
11578
									}#if end
11579
 
3 liveuser 11580
								#用 "talkTo:" 分割 $buf
11581
								#涵式說明:
11582
								#將固定格式的字串分開,並回傳分開的結果。
11583
								#回傳結果:
11584
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11585
								#$result["error"],錯誤訊息陣列
11586
								#$result["function"],當前執行的函數名稱.
11587
								#$result["oriStr"],要分割的原始字串內容
11588
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
11589
								#$result["dataCounts"],爲總共分成幾段
11590
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
11591
								#必填的參數:
11592
								$conf["stringProcess::spiltString"]["stringIn"]=$buf;#要處理的字串。
11593
								$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
11594
								#可省略參數:
11595
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
11596
								$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
11597
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
11598
								unset($conf["stringProcess::spiltString"]);
11599
 
11600
								#如果分割字串失敗
11601
								if($spiltString["status"]==="false"){
11602
 
11603
									#設置執行失敗
11604
									$result["status"]="false";
11605
 
11606
									#設置執行錯誤訊息
11607
									$result["error"]=$spiltString;
11608
 
11609
									#回傳結果
11610
									return $result;
11611
 
11612
									}#if end
11613
 
11614
								#如果剛好分割出一筆資料
11615
								if($spiltString["dataCounts"]===1){
11616
 
11617
									#取得自己的id
11618
									$myId=$connections[$conIndex]["id"];
11619
 
11620
									#取得講話對象的id
11621
									$toId=$spiltString["dataArray"][0];
11622
 
11623
									#設置對象不存在的識別
11624
									$targetExist=false;
11625
 
11626
									#設置通話對象的key
11627
									$targetKey="";
11628
 
11629
									#取得除了自己的id以外的所有連線
11630
									foreach($connections as $index=>$talkInfo){
11631
 
11632
										#除了自己的id
11633
										if($talkInfo["id"]!==$myId){
11634
 
11635
											#如果存在要對話的對象
11636
											if($talkInfo["id"]===$toId){
11637
 
11638
												#設置對象存在的識別
11639
												$targetExist=true;
11640
 
11641
												#通話對象的key
11642
												$targetKey=$index;
11643
 
11644
												}#if end
11645
 
11646
											}#if end
11647
 
11648
										}#for each end
11649
 
11650
									#如果通話對象存在
11651
									if($targetExist){
11652
 
11653
										#保存自己的通話對象
11654
										$connections[$conIndex]["talkTo"][]=$toId;
11655
 
11656
										#設置要給自己看的訊息
11657
										$talkback="您與 ".$toId." 展開對話";
11658
 
11659
										#json encode 要給自己看的訊息
11660
										$talkback=json_encode($talkback).PHP_EOL;
11661
 
11662
										#如果是 ws 模式
11663
										if($conf["wsMode"]==="true"){
11664
 
11665
											#如果已經 handshake 過
11666
											if($connections[$conIndex]["handshaked"]==="true"){
11667
 
11668
												#如果要 unmask	
11669
												if($connections[$conIndex]["unmask"]==="true"){
11670
 
11671
													#函式說明:
11672
													#加密 handshake 後要傳送的訊息 
11673
													#回傳結果:
11674
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11675
													#$result["error"],執行不正常結束的錯訊息陣列.
11676
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11677
													#$result["argu"],陣列,使用的參數.
11678
													#必填參數:
11679
													#$conf["text"],字串,要加密的訊息.
11680
													$conf["webSock::encode"]["text"]=$talkback; 
11681
													#可省略參數:
11682
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11683
													#$conf["payloadIsBin"]="false";
11684
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11685
													#$conf["ping"]="false";
11686
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11687
													#$conf["pong"]="false";
11688
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11689
													#$conf["frames"]=array();
11690
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11691
													#$conf["mask"]="false";
11692
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11693
													#$conf["debug"]="false";
11694
													#參考資料:
11695
													#無.
11696
													#備註:
11697
													#目前$conf["text"]長度超過125會出錯.
11698
													$talkback=webSock::encode($conf["webSock::encode"]);
11699
													unset($conf["webSock::encode"]);
11700
 
11701
													#如果執行失敗
11702
													if($talkback["status"]==="false"){
11703
 
11704
														#印出結果
11705
														var_dump($talkback);
11706
 
11707
														#結束執行
11708
														exit;
11709
 
11710
														}#if end
11711
 
11712
													#debug
11713
													#var_dump(__LINE__,$talkback);
11714
 
11715
													}#if end
66 liveuser 11716
 
3 liveuser 11717
												}#if end
11718
 
11719
											}#if end
11720
 
11721
										#反之不為 web socket 訊息
11722
										else{
11723
 
11724
											#儲存成只有一個訊息
11725
											$talkback["content"][]=$talkback;
11726
 
11727
											}#else
11728
 
11729
										#針對每個訊息的分段
11730
										foreach($talkback["content"] as $msg){
11731
 
11732
											#回傳訊息
11733
											$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11734
 
11735
											#debug
11736
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
66 liveuser 11737
 
3 liveuser 11738
											}#foreach end
11739
 
11740
										#讓對方可以跟自己對話
11741
										$connections[$targetKey]["talkTo"][]=$myId;
11742
 
11743
										#設置要給對方看的訊息
11744
										$talkback=$connections[$conIndex]["id"]." 與您展開對話";
11745
 
11746
										#json encode 設置要給對方看的訊息
11747
										$talkback=json_encode($talkback);
11748
 
11749
										#如果是 ws 模式
11750
										if($conf["wsMode"]==="true"){
11751
 
11752
											#如果已經 handshake 過
11753
											if($connections[$conIndex]["handshaked"]==="true"){
11754
 
11755
												#如果要 unmask	
11756
												if($connections[$conIndex]["unmask"]==="true"){
11757
 
11758
													#函式說明:
11759
													#加密 handshake 後要傳送的訊息 
11760
													#回傳結果:
11761
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11762
													#$result["error"],執行不正常結束的錯訊息陣列.
11763
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11764
													#$result["argu"],陣列,使用的參數.
11765
													#必填參數:
11766
													#$conf["text"],字串,要加密的訊息.
11767
													$conf["webSock::encode"]["text"]=$talkback; 
11768
													#可省略參數:
11769
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11770
													#$conf["payloadIsBin"]="false";
11771
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11772
													#$conf["ping"]="false";
11773
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11774
													#$conf["pong"]="false";
11775
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11776
													#$conf["frames"]=array();
11777
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11778
													#$conf["mask"]="false";
11779
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11780
													#$conf["debug"]="false";
11781
													#參考資料:
11782
													#無.
11783
													#備註:
11784
													#目前$conf["text"]長度超過125會出錯.
11785
													$talkback=webSock::encode($conf["webSock::encode"]);
11786
													unset($conf["webSock::encode"]);
11787
 
11788
													#如果執行失敗
11789
													if($talkback["status"]==="false"){
11790
 
11791
														#印出結果
11792
														var_dump($talkback);
11793
 
11794
														#結束執行
11795
														exit;
11796
 
11797
														}#if end
11798
 
11799
													#debug
11800
													#var_dump(__LINE__,$talkback);
11801
 
11802
													}#if end
66 liveuser 11803
 
3 liveuser 11804
												}#if end
11805
 
11806
											}#if end
11807
 
11808
										#反之不為 web socket 訊息
11809
										else{
11810
 
11811
											#儲存成只有一個訊息
11812
											$talkback["content"][]=$talkback;
11813
 
11814
											}#else
11815
 
11816
										#針對每個訊息的分段
11817
										foreach($talkback["content"] as $msg){
11818
 
11819
											#給對方看的訊息
11820
											$socket_write=socket_write($connections[$targetKey]["connect"], $msg, strlen($msg));
11821
 
11822
											#debug
11823
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11824
 
11825
											}#foreach end
11826
 
11827
										#換一個連線
11828
										continue;
11829
 
11830
										}#if end
11831
 
11832
									}#if end
11833
 
11834
								}#if end
11835
 
11836
							}#if end
66 liveuser 11837
 
11838
						*/
11839
 
11840
						#如果收到的訊息是 runPhpWhenIdle: 開頭
11841
						if(strpos($buf,"runPhpWhenIdle:")===0){
11842
 
11843
							#如果尚未認證
11844
							if($connections[$conIndex]["auth"]==="false"){
3 liveuser 11845
 
66 liveuser 11846
								#設置要回傳的訊息
11847
								$talkback=json_encode("permission denied");
11848
 
11849
								#如果是 ws 模式
11850
								if($conf["wsMode"]==="true"){
11851
 
11852
									#如果已經 handshake 過
11853
									if($connections[$conIndex]["handshaked"]==="true"){
11854
 
11855
										#如果要 unmask	
11856
										if($connections[$conIndex]["unmask"]==="true"){
11857
 
11858
											#函式說明:
11859
											#加密 handshake 後要傳送的訊息 
11860
											#回傳結果:
11861
											#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11862
											#$result["error"],執行不正常結束的錯訊息陣列.
11863
											#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11864
											#$result["argu"],陣列,使用的參數.
11865
											#必填參數:
11866
											#$conf["text"],字串,要加密的訊息.
11867
											$conf["webSock::encode"]["text"]=$talkback; 
11868
											#可省略參數:
11869
											#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11870
											#$conf["payloadIsBin"]="false";
11871
											#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11872
											#$conf["ping"]="false";
11873
											#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11874
											#$conf["pong"]="false";
11875
											#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11876
											#$conf["frames"]=array();
11877
											#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11878
											#$conf["mask"]="false";
11879
											#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11880
											#$conf["debug"]="false";
11881
											#參考資料:
11882
											#無.
11883
											#備註:
11884
											#目前$conf["text"]長度超過125會出錯.
11885
											$talkback=webSock::encode($conf["webSock::encode"]);
11886
											unset($conf["webSock::encode"]);
11887
 
11888
											#如果執行失敗
11889
											if($talkback["status"]==="false"){
11890
 
11891
												#印出結果
11892
												var_dump($talkback);
11893
 
11894
												#結束執行
11895
												exit;
11896
 
11897
												}#if end
11898
 
11899
											#debug
11900
											#var_dump(__LINE__,$talkback);
11901
 
11902
											}#if end
11903
 
11904
										}#if end
11905
 
11906
									}#if end
11907
 
11908
								#反之不為 web socket 訊息
11909
								else{
11910
 
11911
									#儲存成只有一個訊息
11912
									$talkback["content"][]=$talkback;
11913
 
11914
									}#else
11915
 
11916
								#針對每個訊息的分段
11917
								foreach($talkback["content"] as $msg){
11918
 
11919
									#回傳訊息
11920
									$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11921
 
11922
									#debug
11923
									#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11924
 
11925
									}#foreach end
11926
 
11927
								#跳到下一輪
11928
								continue;
11929
 
11930
								}#if end
11931
 
11932
							#剔除開頭的 "runPhpWhenIdle:"
11933
							#函式說明:
11934
							#將字串特定關鍵字與其前面的內容剔除
11935
							#回傳結果:
11936
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11937
							#$result["error"],錯誤訊息陣列.
11938
							#$result["warning"],警告訊息鎮列.
11939
							#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
11940
							#$result["function"],當前執行的函數名稱.
11941
							#$result["argu"],使用的參數.
11942
							#$result["oriStr"],要處理的原始字串內容.
11943
							#$result["content"],處理好的的字串內容.
11944
							#$result["deleted"],被移除的內容.
11945
							#必填參數:
11946
							#$conf["stringIn"],字串,要處理的字串.
11947
							$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$buf;
11948
							#$conf["keyWord"],字串,特定字串.
11949
							$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="runPhpWhenIdle:";
11950
							#可省略參數:
11951
							#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
11952
							#$conf["recursive"]="true";
11953
							#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
11954
							#$conf["lastResult"]=$delStrBeforeKeyWord;
11955
							#參考資料:
11956
							#無.
11957
							#備註:
11958
							#無.
11959
							$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
11960
							unset($conf["stringProcess::delStrBeforeKeyWord"]);
11961
 
11962
							#如果執行失敗
11963
							if($delStrBeforeKeyWord["status"]==="false"){
11964
 
11965
								#印出結果
11966
								var_dump($delStrBeforeKeyWord);
11967
 
11968
								#結束執行
11969
								exit;
11970
 
11971
								}#if end
11972
 
11973
							#設置要執行的php程式
11974
							$php2runWhenIdle[]=$delStrBeforeKeyWord["content"];
11975
 
11976
							#跳到下一輪
11977
							continue;
11978
 
11979
							}#if end
11980
 
11981
						/* 舊的寫法
11982
 
3 liveuser 11983
						#如果收到的是 quit
11984
						if ($buf === 'quit' ) {
11985
 
11986
							#設置要回傳的訊息
11987
							$talkback="結束與 server 的連線";
11988
 
11989
							#json encode 要回傳的訊息
11990
							$talkback=json_encode($talkback).PHP_EOL;
11991
 
11992
							#如果是 ws 模式
11993
							if($conf["wsMode"]==="true"){
11994
 
11995
								#如果已經 handshake 過
11996
								if($connections[$conIndex]["handshaked"]==="true"){
11997
 
11998
									#如果要 unmask	
11999
									if($connections[$conIndex]["unmask"]==="true"){
12000
 
12001
										#函式說明:
12002
										#加密 handshake 後要傳送的訊息 
12003
										#回傳結果:
12004
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12005
										#$result["error"],執行不正常結束的錯訊息陣列.
12006
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12007
										#$result["argu"],陣列,使用的參數.
12008
										#必填參數:
12009
										#$conf["text"],字串,要加密的訊息.
12010
										$conf["webSock::encode"]["text"]=$talkback; 
12011
										#可省略參數:
12012
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12013
										#$conf["payloadIsBin"]="false";
12014
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12015
										#$conf["ping"]="false";
12016
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12017
										#$conf["pong"]="false";
12018
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12019
										#$conf["frames"]=array();
12020
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12021
										#$conf["mask"]="false";
12022
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12023
										#$conf["debug"]="false";
12024
										#參考資料:
12025
										#無.
12026
										#備註:
12027
										#目前$conf["text"]長度超過125會出錯.
12028
										$talkback=webSock::encode($conf["webSock::encode"]);
12029
										unset($conf["webSock::encode"]);
12030
 
12031
										#如果執行失敗
12032
										if($talkback["status"]==="false"){
12033
 
12034
											#印出結果
12035
											var_dump($talkback);
12036
 
12037
											#結束執行
12038
											exit;
12039
 
12040
											}#if end
12041
 
12042
										#debug
12043
										#var_dump(__LINE__,$talkback);
12044
 
12045
										}#if end
12046
 
12047
									}#if end
12048
 
12049
								}#if end
12050
 
12051
							#反之不為 web socket 訊息
12052
							else{
12053
 
12054
								#儲存成只有一個訊息
12055
								$talkback["content"][]=$talkback;
12056
 
12057
								}#else
12058
 
12059
							#針對每個訊息的分段
12060
							foreach($talkback["content"] as $msg){
12061
 
12062
								#回傳訊息
12063
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
12064
 
12065
								#debug
12066
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12067
 
12068
								}#foreach end
12069
 
12070
							#關閉被 client 的連線	
12071
							socket_close($con["connect"]);
12072
 
12073
							#清理連線的陣列
12074
							unset($connections[$conIndex]);
12075
 
12076
							#跳到下一輪
12077
							continue;
12078
 
12079
							}#if end
12080
 
66 liveuser 12081
						*/
12082
 
12083
						/* 舊的寫法
12084
 
3 liveuser 12085
						#如果收到的是 shutdown	
12086
						if ($buf === 'shutdown') {
12087
 
66 liveuser 12088
							#如果尚未認證
12089
							if($connections[$conIndex]["auth"]==="false"){
12090
 
12091
								#設置要回傳的訊息
12092
								$talkback=json_encode("permission denied");
12093
 
12094
								#如果是 ws 模式
12095
								if($conf["wsMode"]==="true"){
12096
 
12097
									#如果已經 handshake 過
12098
									if($connections[$conIndex]["handshaked"]==="true"){
12099
 
12100
										#如果要 unmask	
12101
										if($connections[$conIndex]["unmask"]==="true"){
12102
 
12103
											#函式說明:
12104
											#加密 handshake 後要傳送的訊息 
12105
											#回傳結果:
12106
											#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12107
											#$result["error"],執行不正常結束的錯訊息陣列.
12108
											#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12109
											#$result["argu"],陣列,使用的參數.
12110
											#必填參數:
12111
											#$conf["text"],字串,要加密的訊息.
12112
											$conf["webSock::encode"]["text"]=$talkback; 
12113
											#可省略參數:
12114
											#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12115
											#$conf["payloadIsBin"]="false";
12116
											#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12117
											#$conf["ping"]="false";
12118
											#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12119
											#$conf["pong"]="false";
12120
											#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12121
											#$conf["frames"]=array();
12122
											#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12123
											#$conf["mask"]="false";
12124
											#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12125
											#$conf["debug"]="false";
12126
											#參考資料:
12127
											#無.
12128
											#備註:
12129
											#目前$conf["text"]長度超過125會出錯.
12130
											$talkback=webSock::encode($conf["webSock::encode"]);
12131
											unset($conf["webSock::encode"]);
12132
 
12133
											#如果執行失敗
12134
											if($talkback["status"]==="false"){
12135
 
12136
												#印出結果
12137
												var_dump($talkback);
12138
 
12139
												#結束執行
12140
												exit;
12141
 
12142
												}#if end
12143
 
12144
											#debug
12145
											#var_dump(__LINE__,$talkback);
12146
 
12147
											}#if end
12148
 
12149
										}#if end
12150
 
12151
									}#if end
12152
 
12153
								#反之不為 web socket 訊息
12154
								else{
12155
 
12156
									#儲存成只有一個訊息
12157
									$talkback["content"][]=$talkback;
12158
 
12159
									}#else
12160
 
12161
								#針對每個訊息的分段
12162
								foreach($talkback["content"] as $msg){
12163
 
12164
									#回傳訊息
12165
									$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
12166
 
12167
									#debug
12168
									#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12169
 
12170
									}#foreach end
12171
 
12172
								#跳到下一輪
12173
								continue;
12174
 
12175
								}#if end
12176
 
3 liveuser 12177
							#設置要回傳的訊息
12178
							$talkback="Server 即將關閉";
12179
 
12180
							#json encode 要回傳的訊息
12181
							$talkback=json_encode($talkback);
12182
 
12183
							#如果是 ws 模式
12184
							if($conf["wsMode"]==="true"){
12185
 
12186
								#如果已經 handshake 過
12187
								if($connections[$conIndex]["handshaked"]==="true"){
12188
 
12189
									#如果要 unmask	
12190
									if($connections[$conIndex]["unmask"]==="true"){
12191
 
12192
										#函式說明:
12193
										#加密 handshake 後要傳送的訊息 
12194
										#回傳結果:
12195
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12196
										#$result["error"],執行不正常結束的錯訊息陣列.
12197
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12198
										#$result["argu"],陣列,使用的參數.
12199
										#必填參數:
12200
										#$conf["text"],字串,要加密的訊息.
12201
										$conf["webSock::encode"]["text"]=$talkback; 
12202
										#可省略參數:
12203
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12204
										#$conf["payloadIsBin"]="false";
12205
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12206
										#$conf["ping"]="false";
12207
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12208
										#$conf["pong"]="false";
12209
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12210
										#$conf["frames"]=array();
12211
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12212
										#$conf["mask"]="false";
12213
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12214
										#$conf["debug"]="false";
12215
										#參考資料:
12216
										#無.
12217
										#備註:
12218
										#無.
12219
										$talkback=webSock::encode($conf["webSock::encode"]);
12220
										unset($conf["webSock::encode"]);
12221
 
12222
										#如果執行失敗
12223
										if($talkback["status"]==="false"){
12224
 
12225
											#印出結果
12226
											var_dump($talkback);
12227
 
12228
											#結束執行
12229
											exit;
12230
 
12231
											}#if end
12232
 
12233
										#debug
12234
										#var_dump(__LINE__,$talkback);
12235
 
12236
										}#if end
12237
 
12238
									}#if end
12239
 
12240
								}#if end
12241
 
12242
							#反之不為 web socket 訊息
12243
							else{
12244
 
12245
								#儲存成只有一個訊息
12246
								$talkback["content"][]=$talkback;
12247
 
12248
								}#else
12249
 
12250
							#針對每個訊息的分段
12251
							foreach($talkback["content"] as $msg){
12252
 
12253
								#回傳訊息
12254
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
12255
 
12256
								#debug
12257
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12258
 
12259
								}#foreach end
12260
 
12261
							#關閉用戶的連線
12262
							socket_close($con["connect"]);
12263
 
12264
							#跳到最外層,結束webSocket server
12265
							break 2;
12266
 
12267
							}#if end
12268
 
66 liveuser 12269
						*/
12270
 
12271
						/* 舊的寫法
12272
 
12273
						#如果收到的訊息為"auth:"開頭
12274
						if(strpos($buf,"auth:")){
12275
 
12276
							#剔除 "auth:" 前面的內容
12277
							#函式說明:
12278
							#將字串特定關鍵字與其前面的內容剔除
12279
							#回傳結果:
12280
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12281
							#$result["error"],錯誤訊息陣列.
12282
							#$result["warning"],警告訊息鎮列.
12283
							#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
12284
							#$result["function"],當前執行的函數名稱.
12285
							#$result["argu"],使用的參數.
12286
							#$result["oriStr"],要處理的原始字串內容.
12287
							#$result["content"],處理好的的字串內容.
12288
							#$result["deleted"],被移除的內容.
12289
							#必填參數:
12290
							#$conf["stringIn"],字串,要處理的字串.
12291
							$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$buf;
12292
							#$conf["keyWord"],字串,特定字串.
12293
							$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="auth:";
12294
							#可省略參數:
12295
							#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
12296
							#$conf["recursive"]="true";
12297
							#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
12298
							#$conf["lastResult"]=$delStrBeforeKeyWord;
12299
							#參考資料:
12300
							#無.
12301
							#備註:
12302
							#無.
12303
							$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
12304
							unset($conf["stringProcess::delStrBeforeKeyWord"]);
12305
 
12306
							#如果執行失敗
12307
							if($delStrBeforeKeyWord["status"]==="false"){
12308
 
12309
								#印出結果
12310
								var_dump($delStrBeforeKeyWord);
12311
 
12312
								#結束執行
12313
								exit;
12314
 
12315
								}#if end
12316
 
12317
							#還原編碼
12318
							#$delStrBeforeKeyWord["content"];
12319
 
12320
							#gpg解密
12321
							#...
12322
 
12323
							#檢查賬號密碼
12324
							#...
12325
 
12326
							}#if end
12327
 
12328
						*/
12329
 
12330
						#以下為其他收到的訊息內容
12331
 
12332
						/* 舊的寫法
12333
 
12334
						#如果尚未認證
12335
						if($connections[$conIndex]["auth"]==="false"){
12336
 
12337
							#設置要回傳的訊息
12338
							$talkback=json_encode("permission denied");
12339
 
12340
							#如果是 ws 模式
12341
							if($conf["wsMode"]==="true"){
12342
 
12343
								#如果已經 handshake 過
12344
								if($connections[$conIndex]["handshaked"]==="true"){
12345
 
12346
									#如果要 unmask	
12347
									if($connections[$conIndex]["unmask"]==="true"){
12348
 
12349
										#函式說明:
12350
										#加密 handshake 後要傳送的訊息 
12351
										#回傳結果:
12352
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12353
										#$result["error"],執行不正常結束的錯訊息陣列.
12354
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12355
										#$result["argu"],陣列,使用的參數.
12356
										#必填參數:
12357
										#$conf["text"],字串,要加密的訊息.
12358
										$conf["webSock::encode"]["text"]=$talkback; 
12359
										#可省略參數:
12360
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
12361
										#$conf["payloadIsBin"]="false";
12362
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12363
										#$conf["ping"]="false";
12364
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
12365
										#$conf["pong"]="false";
12366
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12367
										#$conf["frames"]=array();
12368
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12369
										#$conf["mask"]="false";
12370
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12371
										#$conf["debug"]="false";
12372
										#參考資料:
12373
										#無.
12374
										#備註:
12375
										#目前$conf["text"]長度超過125會出錯.
12376
										$talkback=webSock::encode($conf["webSock::encode"]);
12377
										unset($conf["webSock::encode"]);
12378
 
12379
										#如果執行失敗
12380
										if($talkback["status"]==="false"){
12381
 
12382
											#印出結果
12383
											var_dump($talkback);
12384
 
12385
											#結束執行
12386
											exit;
12387
 
12388
											}#if end
12389
 
12390
										#debug
12391
										#var_dump(__LINE__,$talkback);
12392
 
12393
										}#if end
12394
 
12395
									}#if end
12396
 
12397
								}#if end
12398
 
12399
							#反之不為 web socket 訊息
12400
							else{
12401
 
12402
								#儲存成只有一個訊息
12403
								$talkback["content"][]=$talkback;
12404
 
12405
								}#else
12406
 
12407
							#針對每個訊息的分段
12408
							foreach($talkback["content"] as $msg){
12409
 
12410
								#回傳訊息
12411
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
12412
 
12413
								#debug
12414
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
12415
 
12416
								}#foreach end
12417
 
12418
							#跳到下一輪
12419
							continue;
12420
 
12421
							}#if end
12422
 
12423
						*/
12424
 
3 liveuser 12425
						#如果有指定的外掛函式
12426
						if(isset($conf["processFuncs"])){
12427
 
12428
							#針對每個用來處理輸入字串的函式
12429
							foreach($conf["processFuncs"] as $proFunc){
66 liveuser 12430
 
3 liveuser 12431
								#debug
12432
								#var_dump(__LINE__,$proFunc);
66 liveuser 12433
 
12434
								#函式說明:
12435
								#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
12436
								#回傳結果:
12437
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12438
								#$result["error"],執行不正常結束的錯訊息陣列.
12439
								#$result["argu"],陣列,使用的參數.
12440
								#必填參數:
12441
								#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
12442
								$conf["webSocket::checkAuth"]["data"]=&$buf;
12443
								#$conf["serverSock"],resource,web socket server socket
12444
								$conf["webSocket::checkAuth"]["serverSock"]=&$sock;
12445
								#$conf["clientSock"],$resource,web socket client socket
12446
								$conf["webSocket::checkAuth"]["clientSock"]=&$con["connect"];
12447
								#$conf["clientInfo"],陣列,web socket client info.
12448
								$conf["webSocket::checkAuth"]["clientInfo"]=&$connections[$conIndex];
12449
								#$conf["clientIndex"],整數.web socket client index.
12450
								$conf["webSocket::checkAuth"]["clientIndex"]=&$conIndex;
12451
								#$conf["allConn"],陣列,all web socket client info.
12452
								$conf["webSocket::checkAuth"]["allConn"]=&$connections;
12453
								#$conf["func"],字串,要檢查的是否具備權限的函式.
12454
								$conf["webSocket::checkAuth"]["func"]=$proFunc;
12455
								#可省略參數:
12456
								#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
12457
								#$conf["wsMode"]="true";
12458
								#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
12459
								#$conf["gpgId"]=gnupgId;
12460
								#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
12461
								#$conf["falseAllowFuncPlus"]=array();
12462
								#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
12463
								#$conf["publicAllowFuncPlus"]=array();
12464
								#參考資料:
12465
								#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
12466
								#備註:
12467
								#無.
12468
								$checkAuth=webSocket::checkAuth($conf["webSocket::checkAuth"]);
12469
								unset($conf["webSocket::checkAuth"]);
3 liveuser 12470
 
66 liveuser 12471
								#如果沒有權限
12472
								if($checkAuth["status"]==="false"){
12473
 
12474
									#換看下個 $proFunc
12475
									continue;
12476
 
12477
									}#if end
12478
 
3 liveuser 12479
								#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket
12480
								#https://www.php.net/manual/en/function.call-user-func.php
12481
								$param=array("data"=>&$buf,"serverSock"=>&$sock,"clientSock"=>&$con["connect"],"clientInfo"=>&$connections[$conIndex],"clientIndex"=>&$conIndex,"allConn"=>&$connections);
12482
								$params=array();
66 liveuser 12483
								$params[]=&$param;
12484
								$result=call_user_func_array($proFunc,$params);
3 liveuser 12485
 
12486
								#debug
12487
								#var_dump(__LINE__,$result);
12488
 
12489
								#如果有回傳結果
12490
								if($result!==NULL){
12491
 
12492
									#如果回傳的形態為陣列
12493
									if(gettype($result)==="array"){
12494
 
12495
										#如果執行出錯
12496
										if($result["status"]==="false"){
12497
 
12498
											#提示錯誤
12499
											echo "run function ".$proFunc." with params:".print_r($params,true)." failed!".PHP_EOL;
12500
 
12501
											#提示會往後面執行
12502
											echo "go next function.".PHP_EOL;
12503
 
12504
											#跳到下一輪
12505
											#continue;
12506
 
12507
											}#if end
12508
 
12509
										#如果結果為跳下一輪
12510
										else if($result["status"]==="continue"){
12511
 
12512
											#提示成功
12513
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
12514
 
12515
											#提示會往後面執行
12516
											echo "go next function.".PHP_EOL;
12517
 
12518
											#跳下一輪
12519
											#continue;
12520
 
12521
											}#if end
12522
 
12523
										#如果已經被處理好了且不准移交給後面的處理
12524
										else if($result["status"]==="true"){
12525
 
12526
											#提示成功
12527
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
12528
 
12529
											#提示在此打住.
12530
											echo "end process,".PHP_EOL;
12531
 
12532
											#後面就不做了
12533
											break;
12534
 
12535
											}#if end
12536
 
12537
										}#if end
12538
 
12539
									#反之回傳形態錯誤
12540
									else{
12541
 
12542
										#提示錯誤
12543
										echo "run function ".$proFunc." with params:".print_r($params,true)." success, but format of return is incorrect!".PHP_EOL;
12544
 
12545
										#提示會往後面執行
12546
										echo "go next function.".PHP_EOL;
12547
 
12548
										}#else end
12549
 
12550
									}#if end
12551
 
12552
								#如果沒有回傳結果
12553
								else{
12554
 
12555
									#提示錯誤
12556
									echo "run function ".$proFunc." with params:".print_r($params,true)." success, but there is no return!".PHP_EOL;
12557
 
12558
									#跳下一輪
12559
									#continue;
12560
 
12561
									}#else end
12562
 
12563
								}#foreach end
12564
 
12565
							}#if end
12566
 
12567
						#如果有要接收訊息的id
12568
						if(count($connections[$conIndex]["talkTo"])>0){
12569
 
12570
							#初始化要傳送給哪些id
12571
							$broadcastId=array();
12572
 
12573
							#依據每個連線資訊
12574
							foreach($connections as $index=>$broadcast){
12575
 
12576
								#儲存每個
12577
								$broadcastId[$index]=$broadcast["id"];
12578
 
12579
								}#foreach end
12580
 
12581
							#檢查哪些人是要接收到訊息的	
12582
							#涵式說明:
12583
							#檢查多個數值,是否與陣列裏面的某些元素相同。
12584
							#回傳的結果:
12585
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12586
							#$result["function"],當前執行的函數
12587
							#$result["error"],涵式錯誤訊息,若爲""則表示沒有錯誤 
12588
							#$result["founded"][$i],若爲"false"代表沒有相同的元素;反之"true"代表有相同的元素,$i爲第i+1個$conf["inputElement"]參數判斷後的結果.
12589
							#$result["key"][$i],為找到$conf["inputElement"]第$i+1個元素的值是在$conf["blackBoxElement"]中的哪個元素.
12590
							#必填的參數:
12591
							$conf["search::checkEquality"]["inputElement"]=$connections[$conIndex]["talkTo"];#想要找到的變數/數值.
12592
							$conf["search::checkEquality"]["blackBoxElement"]=$broadcastId;#要從哪些變數/數值去尋找.
12593
							$checkEquality=search::checkEquality($conf["search::checkEquality"]);
12594
							unset($conf["search::checkEquality"]);
12595
 
12596
							#如果檢查失敗
12597
							if($checkEquality["status"]==="false"){
12598
 
12599
								#設置執行失敗
12600
								$result["status"]="false";
12601
 
12602
								#設置執行錯誤訊息
12603
								$result["error"]=$checkEquality;
12604
 
12605
								#回傳結果
12606
								return $result;
12607
 
12608
								}#if end
12609
 
12610
							#針對每個搜尋的結果
12611
							foreach($checkEquality["founded"] as $key=>$found){
12612
 
12613
								#如果有找到
12614
								if($found==="true"){
12615
 
12616
									#取得要接收訊息的msgSock
12617
									$receiveMsgSock=$connections[$checkEquality["key"][$key]]["connect"];
12618
 
12619
									#設置要傳送的訊息
12620
									$talkback = $connections[$conIndex]["id"]." said ".$buf;
12621
 
12622
									#json encode 要傳送的訊息
12623
									$talkback=json_encode($talkback).PHP_EOL;
12624
 
12625
									#如果是 ws 模式
12626
									if($conf["wsMode"]==="true"){
12627
 
12628
										#如果已經 handshake 過
12629
										if($connections[$conIndex]["handshaked"]==="true"){
12630
 
12631
											#如果要 unmask	
12632
											if($connections[$conIndex]["unmask"]==="true"){
12633
 
12634
												#加密
12635
												$conf["webSock::encode"]["text"]=$talkback;
12636
												$talkback=webSock::encode($conf["webSock::encode"]);
12637
												unset($conf["webSock::encode"]);
12638
 
12639
												}#if end
12640
 
12641
											}#if end
12642
 
12643
										}#if end
12644
 
12645
									#反之不為 web socket 訊息
12646
									else{
12647
 
12648
										#儲存成只有一個訊息
12649
										$talkback["content"][]=$talkback;
12650
 
12651
										}#else
12652
 
12653
 
12654
									#針對每個訊息的分段
12655
									foreach($talkback["content"] as $msg){
12656
 
12657
										#回傳訊息
12658
										$socket_write=socket_write($receiveMsgSock, $msg, strlen($msg));
12659
 
12660
										#debug
12661
										#var_dump(__LINE__,$receiveMsgSock,socket_strerror(socket_last_error($receiveMsgSock)));
12662
 
12663
										}#foreach end
12664
 
12665
									}#if end
12666
 
12667
								}#foreach end
12668
 
12669
							}#if end
12670
 
12671
						}#if end
12672
 
12673
					}#foreach end
12674
 
12675
				#do end 
12676
				}while(true);
12677
 
12678
			#提示關閉 server socket
12679
			echo "關閉 server socket".PHP_EOL;
12680
 
12681
			#關閉 socket
12682
			socket_close($sock);
12683
 
12684
			#do end
12685
			}while(true);
12686
 
12687
		#設置執行正常
12688
		$result["status"]="true";
12689
 
12690
		#回傳結果
12691
		return $result;
12692
 
12693
		}#function nativeSocketTcpIpServer end
12694
 
12695
	/*	
12696
	#函式說明:
12697
	#連線到webSocket,會印出建立好的unixDomainSocket位置與名稱.
12698
	#回傳結果:
12699
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
12700
	#$result["error"],錯誤訊息陣列.
12701
	#$resutl["function"],當前執行的涵式名稱.
12702
	#$result["content"],取得的回應.
12703
	#$result["argu"],所使用的參數.
12704
	#$result["Sec-WebSocket-Accept"],所得到的Sec-WebSocket-Accept.
12705
	#必填參數:
12706
	#無.
12707
	#可省略參數:
12708
	#$conf["targetServr"],字串,要連線的目標,預設為"localhost".
12709
	#$conf["targetServr"]="";
12710
	#$conf["targetPort"],字串,要連線的目標port.
12711
	#$conf["targetPort"]="";
12712
	#$conf["ssl"],字串,是否要走wss,預設為"false",不走wss;反之為"true".
12713
	#$conf["ssl"]="false";
12714
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12715
	#$conf["debug"]="false";
12716
	#參考資料:
12717
	#https://www.php.net/manual/en/function.stream-socket-client.php
12718
	#https://www.php.net/manual/en/function.stream-context-create.php
12719
	#https://www.php.net/manual/en/context.ssl.php
12720
	#備註:
12721
	#建構中...
12722
	*/
12723
	public static function clientDaemon(&$conf){
12724
 
12725
		#初始化要回傳的結果
12726
		$result=array();
12727
 
12728
		#取得當前執行的函數名稱
12729
		$result["function"]=__FUNCTION__;
12730
 
12731
		#涵式說明:
12732
		#判斷當前環境為web還是cmd
12733
		#回傳結果:
12734
		#$result,"web"或"cmd"
12735
		if(csInformation::getEnv()==="web"){
12736
 
12737
			#設置執行失敗
12738
			$result["status"]="false";
12739
 
12740
			#設置執行錯誤訊息
12741
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
12742
 
12743
			#回傳結果
12744
			return $result;
12745
 
12746
			}#if end
12747
 
12748
		#取得參數
12749
		$result["argu"]=$conf;
12750
 
12751
		#如果 $conf 不為陣列
12752
		if(gettype($conf)!="array"){
12753
 
12754
			#設置執行失敗
12755
			$result["status"]="false";
12756
 
12757
			#設置執行錯誤訊息
12758
			$result["error"][]="\$conf變數須為陣列形態";
12759
 
12760
			#如果傳入的參數為 null
12761
			if($conf==null){
12762
 
12763
				#設置執行錯誤訊息
12764
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
12765
 
12766
				}#if end
12767
 
12768
			#回傳結果
12769
			return $result;
12770
 
12771
			}#if end
12772
 
12773
		#檢查參數
12774
		#函式說明:
12775
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
12776
		#回傳結果:
12777
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12778
		#$result["error"],執行不正常結束的錯訊息陣列.
12779
		#$result["simpleError"],簡單表示的錯誤訊息.
12780
		#$result["function"],當前執行的函式名稱.
12781
		#$result["argu"],設置給予的參數.
12782
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
12783
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
12784
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
12785
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
12786
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
12787
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
12788
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
12789
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
12790
		#必填參數:
12791
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
12792
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
12793
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
12794
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
12795
		#可省略參數:
12796
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
12797
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array();
12798
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
12799
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array();
12800
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
12801
		#$conf["canBeEmptyString"]="false";
12802
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
12803
		#$conf["canNotBeEmpty"]=array();
12804
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
12805
		#$conf["canBeEmpty"]=array();
12806
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
12807
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("targetServr","targetPort","ssl","debug");
12808
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
12809
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("targetServr","targetPort","ssl","debug");
12810
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
12811
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","string");
12812
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
12813
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("localhost",null,"false","false");
12814
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
12815
		#$conf["disallowAllSkipableVarIsEmpty"]="";
12816
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
12817
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
12818
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
12819
		#$conf["disallowAllSkipableVarNotExist"]="";
12820
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
12821
		#$conf["arrayCountEqualCheck"][]=array();
12822
		#參考資料:
12823
		#array_keys=>http://php.net/manual/en/function.array-keys.php
12824
		#備註:
12825
		#無.
12826
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
12827
		unset($conf["variableCheck::checkArguments"]);
12828
 
12829
		#如果檢查參數失敗
12830
		if($checkArguments["status"]==="false"){
12831
 
12832
			#設置執行失敗
12833
			$result["status"]="false";
12834
 
12835
			#設置執行錯誤訊息
12836
			$result["error"]=$checkArguments;
12837
 
12838
			#回傳結果
12839
			return $result;
12840
 
12841
			}#if end
12842
 
12843
		#如果檢查參數不通過
12844
		if($checkArguments["passed"]==="false"){
12845
 
12846
			#設置執行失敗
12847
			$result["status"]="false";
12848
 
12849
			#設置執行錯誤訊息
12850
			$result["error"]=$checkArguments;
12851
 
12852
			#回傳結果
12853
			return $result;
12854
 
12855
			}#if end
12856
 
12857
		#如果targetPort沒有設置
12858
		if(!isset($conf["targetPort"])){
12859
 
12860
			#port預設為80
12861
			$conf["targetPort"]="80";
12862
 
12863
			#如果有啟用 ssl
12864
			if($conf["ssl"]==="true"){
12865
 
12866
				#port預設為443
12867
				$conf["targetPort"]="443";
12868
 
12869
				}#if end
12870
 
12871
			}#if end
12872
 
12873
		#回報任何錯誤
12874
		#error_reporting(E_ALL);
12875
 
12876
		#如果要使用 ssl
12877
		if($conf["ssl"]==="true"){
12878
 
12879
			#預設的path
12880
			$path="/";
12881
 
12882
			#分割出server位置與對應GET的path
12883
			#函式說明:
12884
			#將固定格式的字串分開,並回傳分開的結果.
12885
			#回傳結果:
12886
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12887
			#$result["error"],錯誤訊息陣列
12888
			#$result["function"],當前執行的函數名稱.
12889
			#$result["argu"],使用的參數.
12890
			#$result["oriStr"],要分割的原始字串內容
12891
			#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
12892
			#$result["dataCounts"],爲總共分成幾段
12893
			#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
12894
			#必填參數:
12895
			#$conf["stringIn"],字串,要處理的字串.
12896
			$conf["stringProcess::spiltString"]["stringIn"]=$conf["targetServr"];
12897
			#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
12898
			$conf["stringProcess::spiltString"]["spiltSymbol"]="/";
12899
			#可省略參數:
12900
			#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
12901
			$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
12902
			#參考資料:
12903
			#無.
12904
			#備註:
12905
			#無.
12906
			$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
12907
			unset($conf["stringProcess::spiltString"]);
12908
 
12909
			#如果檢查執行失敗
12910
			if($spiltString["status"]==="false"){
12911
 
12912
				#設置執行失敗
12913
				$result["status"]="false";
12914
 
12915
				#設置執行錯誤訊息
12916
				$result["error"]=$spiltString;
12917
 
12918
				#回傳結果
12919
				return $result;
12920
 
12921
				}#if end
12922
 
12923
			#如果含有 /
12924
			if($spiltString["found"]==="true"){
12925
 
12926
				#函式說明:
12927
				#將字串特定關鍵字與其前面的內容剔除
12928
				#回傳結果:
12929
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12930
				#$result["error"],錯誤訊息陣列.
12931
				#$result["warning"],警告訊息鎮列.
12932
				#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
12933
				#$result["function"],當前執行的函數名稱.
12934
				#$result["argu"],使用的參數.
12935
				#$result["oriStr"],要處理的原始字串內容.
12936
				#$result["content"],處理好的的字串內容.	
12937
				#必填參數:
12938
				#$conf["stringIn"],字串,要處理的字串.
12939
				$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$conf["targetServr"];
12940
				#$conf["keyWord"],字串,特定字串.
12941
				$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="/";
12942
				#可省略參數:
12943
				#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
12944
				#$conf["recursive"]="true";
12945
				#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
12946
				#$conf["lastResult"]=$delStrBeforeKeyWord;
12947
				#參考資料:
12948
				#無.
12949
				#備註:
12950
				#無.
12951
				$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
12952
				unset($conf["stringProcess::delStrBeforeKeyWord"]);
12953
 
12954
				#如果檢查執行失敗
12955
				if($delStrBeforeKeyWord["status"]==="false"){
12956
 
12957
					#設置執行失敗
12958
					$result["status"]="false";
12959
 
12960
					#設置執行錯誤訊息
12961
					$result["error"]=$delStrBeforeKeyWord;
12962
 
12963
					#回傳結果
12964
					return $result;
12965
 
12966
					}#if end
12967
 
12968
				#如果該存在的 / 不存在
12969
				if($delStrBeforeKeyWord["founded"]==="false"){
12970
 
12971
					#設置執行失敗
12972
					$result["status"]="false";
12973
 
12974
					#設置執行錯誤訊息
12975
					$result["error"]=$delStrBeforeKeyWord;
12976
 
12977
					#回傳結果
12978
					return $result;
12979
 
12980
					}#if end
12981
 
12982
				#設置 path
12983
				$path="/".$delStrBeforeKeyWord["content"];
12984
 
12985
				#如果有切出 path
12986
				if($spiltString["dataCounts"]>=2){
12987
 
12988
					#另存peer host name
12989
					$peerHostName=$spiltString["dataArray"][0];
12990
 
12991
					#更新 targetServr
12992
					$conf["targetServr"]=$peerHostName;
12993
 
12994
					}#if end
12995
 
12996
				}#if end
12997
 
12998
			#初始化給 stream_context_create 用的參數
12999
			$paramsForStream_context_create=array();
13000
 
13001
			#設置為http相關的參數
13002
			#$paramsForStream_context_create["http"]=array();
13003
 
13004
			#method為HEAD
13005
			#$paramsForStream_context_create["http"]["method"]="HEAD ".$path;
13006
 
13007
			#HTTP/1.1
13008
			#$paramsForStream_context_create["http"]["protocol_version"]="1.1";
13009
 
13010
			#初始化header
13011
			#$paramsForStream_context_create["http"]["header"]=array();
13012
 
13013
			#設置header Host
13014
			#$paramsForStream_context_create["http"]["header"][]="Host: ".$conf["targetServr"];
13015
 
13016
			#設置header Upgrade
13017
			#$paramsForStream_context_create["http"]["header"][]="Upgrade: websocket";
13018
 
13019
			#設置header Connection
13020
			#$paramsForStream_context_create["http"]["header"][]="Connection: Upgrade";
13021
 
13022
			#設置header Sec-WebSocket-Version
13023
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Version: 13";
13024
 
13025
			#設置header Sec-WebSocket-Key
13026
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==";
13027
 
13028
			#body content
13029
			#$paramsForStream_context_create["http"]["content"]="";
13030
 
13031
			#設置為ssl相關的參數
13032
			$paramsForStream_context_create["ssl"]=array();
13033
 
13034
			#被連線端的網域名稱
13035
			#$paramsForStream_context_create["ssl"]["peer_name"]=$conf["targetServr"];
13036
 
13037
			#verify_peer
13038
			#$paramsForStream_context_create["ssl"]["verify_peer"]=true;
13039
			#$paramsForStream_context_create["ssl"]["verify_peer"]=false;
13040
 
13041
			#verify_peer_name
13042
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=true;
13043
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=false;
13044
 
13045
			#allow_self_signed,允許沒有受到認可的憑證
13046
			#$paramsForStream_context_create["ssl"]["allow_self_signed"]=false; 
13047
 
13048
			#cafile
13049
			$paramsForStream_context_create["ssl"]["cafile"]="/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
13050
 
13051
			#capath
13052
			#$paramsForStream_context_create["ssl"]["capath"]="/etc/pki/ca-trust/extracted/pem/directory-hash/";
13053
 
13054
			#local_cert
13055
			#$paramsForStream_context_create["ssl"]["local_cert"]="/etc/pki/tls/certs/php-selfsigned-and-key.crt";
13056
 
13057
			#local_pk
13058
			#$paramsForStream_context_create["ssl"]["local_pk"]="/etc/pki/tls/private/php-selfsigned.key";
13059
 
13060
			#capture_peer_cert
13061
			$paramsForStream_context_create["ssl"]["capture_peer_cert"]=true;
13062
 
13063
			#capture_peer_cert_chain
13064
			$paramsForStream_context_create["ssl"]["capture_peer_cert_chain"]=true;
13065
 
13066
			#security_level
13067
			#$paramsForStream_context_create["ssl"]["security_level"]=5;
13068
 
13069
			#如果要 debug
13070
			if($conf["debug"]==="true"){
13071
 
13072
				#debug
13073
				var_dump(__LINE__,$paramsForStream_context_create);
13074
 
13075
				}#if end
13076
 
13077
			#建立ssl設定
13078
			$stream_context_create=stream_context_create($paramsForStream_context_create);
13079
 
13080
			#如果要 debug
13081
			if($conf["debug"]==="true"){
13082
 
13083
				#debug
13084
				var_dump(__LINE__,$stream_context_create);
13085
 
13086
				}#if end
13087
 
13088
			#連線到 $conf["targetServr"].":".$conf["targetPort"] ,若有 error 可從 $error_code,$error_message 取得資訊, timeout 為 30 秒, connection flags 為 STREAM_CLIENT_CONNECT, 連線的屬性記載在 $stream_context_create.
13089
			$stream_socket_client=stream_socket_client("ssl://".$conf["targetServr"].":".$conf["targetPort"],$error_code,$error_message,0,STREAM_CLIENT_CONNECT,$stream_context_create);
13090
 
13091
			#如果連線到 peer 失敗
13092
			if($stream_socket_client===false){
13093
 
13094
				#設置執行失敗
13095
				$result["status"]="false";
13096
 
13097
				#設置執行錯誤訊息
13098
				$result["error"][]="stream_socket_client() failed.".PHP_EOL."Reason: ".$error_message."(".$error_code.")".PHP_EOL;
13099
 
13100
				#回傳結果
13101
				return $result;
13102
 
13103
				}#if end
13104
 
13105
			#取得連線的資訊
13106
			$result["info"]=stream_get_meta_data($stream_socket_client);
13107
 
13108
			#write header - start
13109
 
13110
			#initial header
13111
			$header="";
13112
 
13113
			#method、path、protocol
13114
			$header=$header."HEAD ".$path." HTTP/1.1"."\r\n";
13115
 
13116
			#Host
13117
			$header=$header."Host: ".$conf["targetServr"]."\r\n";
13118
 
13119
			#Upgrade
13120
			$header=$header."Upgrade: websocket"."\r\n";
13121
 
13122
			#Connection
13123
			$header=$header."Connection: Upgrade"."\r\n";
13124
 
13125
			#Sec-WebSocket-Version
13126
			$header=$header."Sec-WebSocket-Version: 13"."\r\n";
13127
 
13128
			#Sec-WebSocket-Key
13129
			$header=$header."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
13130
 
13131
			#send header					
13132
			fwrite($stream_socket_client,$header."\r\n");
13133
 
13134
			#write header - close
13135
 
13136
			#GET server reponse
13137
			while(!feof($stream_socket_client)){
13138
 
13139
				#讀取內容
13140
				$fgets=fgets($stream_socket_client, 1024);
13141
 
13142
				#如果要 debug
13143
				if($conf["debug"]==="true"){
13144
 
13145
					#debug
13146
					var_dump(__LINE__,$fgets);
13147
 
13148
					}#if end
13149
 
13150
				#如果 server 已經回應要用 websocket 協定了
13151
				if(trim($fgets)==="Upgrade: websocket"){
13152
 
13153
					#跳出while
13154
					break;
13155
 
13156
					}#if end
13157
 
13158
				}#if end
13159
 
13160
			#將建立的 sock 放到 $master 陣列
13161
			$master[] = $stream_socket_client;
13162
 
13163
			#函式說明:
13164
			#取得目前瀏覽的頁面的路徑或執行的php程式路徑.
13165
			#回傳結果:
13166
			#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
13167
			#$result["error"],錯誤訊息.
13168
			#$result["function"],檔前執行的函數名稱.
13169
			#$result["content"],目前瀏覽的頁面的路徑或執行的php程式路徑.
13170
			#$result["serverIp"],取得伺服器ip.
13171
			#$result["scheme"],取得與伺服器連線所使用的通訊協定.
13172
			#必填參數:
13173
			$conf["csInformation::getPathOfThisPhpFile"]["type"]="pathOnly";#想要取得的路徑類型,"full"代表完整路徑,"pathOnly"代表只要路徑,"lastLayer"代表上一層目錄的名稱
13174
			#必填參數:
13175
			#無.
13176
			#可省略參數:
13177
			#無.
13178
			#參考資料:
13179
			#http://blog.longwin.com.tw/2009/01/php-get-directory-file-path-dirname-2008/
13180
			#備註:
13181
			#無.
13182
			$getPathOfThisPhpFile=csInformation::getPathOfThisPhpFile($conf["csInformation::getPathOfThisPhpFile"]);
13183
			unset($conf["csInformation::getPathOfThisPhpFile"]);
13184
 
13185
			#如果執行失敗
13186
			if($getPathOfThisPhpFile["status"]=="false"){
13187
 
13188
				#設置錯誤識別
13189
				$result["status"]="false";
13190
 
13191
				#設置錯誤訊息
13192
				$result["error"]=$getPathOfThisPhpFile;
13193
 
13194
				#回傳結果
13195
				return $result;
13196
 
13197
				}#if end
13198
 
13199
			#函式說明:
13200
			#使用 linux 的 uuid 指令來產生 uuid 字串
13201
			#回傳結果:
13202
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13203
			#$result["error"],錯誤訊息.
13204
			#$result["function"],當前執行的函式名稱.
13205
			#$result["content"],uuid.
13206
			#必填參數:
13207
			#無.
13208
			#可省略參數:
13209
			#無.
13210
			#參考資料:
13211
			#無.
13212
			#備註:
13213
			#無.
13214
			$uuid=cmd::uuid();
13215
 
13216
			#如果執行失敗
13217
			if($uuid["status"]=="false"){
13218
 
13219
				#設置錯誤識別
13220
				$result["status"]="false";
13221
 
13222
				#設置錯誤訊息
13223
				$result["error"]=$uuid;
13224
 
13225
				#回傳結果
13226
				return $result;
13227
 
13228
				}#if end
13229
 
13230
			#設置存放socket的path
13231
			$socketPath=$getPathOfThisPhpFile["content"]."var/webSock::clientDaemon";
13232
 
13233
			#讓存放unix domain socket的路徑存在
13234
			#函式說明:
13235
			#確保路徑存在.
13236
			#回傳結果:
13237
			#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
13238
			#$result["error"],錯誤訊息陣列.
13239
			#$resutl["function"],當前執行的涵式名稱.
13240
			#$result["path"],建立好的路徑字串.
13241
			#$result["fileName"],檔案名稱,若 $conf["haveFileName"] 為 "true" 則會回傳.
13242
			#$result["argu"],使用的參數.
13243
			#必填參數:
13244
			#$conf["path"],要檢查的路徑
13245
			$conf["fileAccess::validatePath"]["path"]=$socketPath;
13246
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
13247
			$conf["fileAccess::validatePath"]["fileArgu"]=__FILE__;
13248
			#可省略參數:
13249
			#$conf["haveFileName"],字串,"true"代表有$conf["path"]檔案名稱,"false"代表$conf["path"]為純路徑,預設為"false".
13250
			$conf["fileAccess::validatePath"]["haveFileName"]="false";
13251
			#$conf["dirPermission"],字串,新建資料夾的權限設定,預設爲0770,亦即擁有者,同群組者可以讀,寫,存取,其他人無法使用.
13252
			#$conf["dirPermission"]="";
13253
			#$conf["web"],是否為檔案系統,"true"為網頁路徑,"false"為網頁系統,預設為"false".
13254
			$conf["fileAccess::validatePath"]["web"]="false";
13255
			#參考資料:
13256
			#無.
13257
			#備註:
13258
			#無.
13259
			$validatePath=fileAccess::validatePath($conf["fileAccess::validatePath"]);
13260
			unset($conf["fileAccess::validatePath"]);
13261
 
13262
			#如果執行失敗
13263
			if($validatePath["status"]==="false"){
13264
 
13265
				#設置錯誤識別
13266
				$result["status"]="false";
13267
 
13268
				#設置錯誤訊息
13269
				$result["error"]=$validatePath;
13270
 
13271
				#回傳結果
13272
				return $result;
13273
 
13274
				}#if end
13275
 
13276
			#變更 working dir
13277
			$chdir=chdir($socketPath);
13278
 
13279
			#設置sock檔案名稱
13280
			$socketName=$uuid["content"].".sock";
13281
 
13282
			#設置sock檔案位置與名稱
13283
			$socketAddr=$socketPath."/".$socketName;
13284
 
13285
			#如果要 debug
13286
			if($conf["debug"]==="true"){
13287
 
13288
				#debug
13289
				var_dump(__LINE__,$socketAddr);
13290
 
13291
				}#if end
13292
 
13293
			#建立 unix domain socket
13294
			$usock=stream_socket_server("unix://".$socketName, $errno, $errstr);
13295
 
13296
			#如果建立 unix domain socket 失敗
13297
			if(!$usock){
13298
 
13299
				#設置執行失敗
13300
				$result["status"]="false";
13301
 
13302
				#設置錯誤訊息
13303
				$result["error"][]=$errstr." (".$errno.")";
13304
 
13305
				#設置錯誤訊息
13306
				$result["error"][]="建立 unix domain socket(".$socketAddr.") 失敗";
13307
 
13308
				#回傳結果
13309
				return $result;
13310
 
13311
				}#if end
13312
 
13313
			#印出socket addr
13314
			echo "unixDomainSocket:".$socketAddr;
13315
 
13316
			#將建立的 unix domain socket 放到 $master 陣列
13317
			$master[] = $usock;
13318
 
13319
			#永久監聽, 不 timeout
13320
			while(true){
13321
 
13322
				#設置給 stream_select 監控的 sock 變數
13323
				$read = $write = $except = $master;
13324
 
13325
				#等待1秒,看有沒有連線進來讀寫資料
13326
				$mod_fd = stream_select($read, $write, $except, 1);
13327
 
13328
				#如果沒有偵測到讀寫動作失敗
13329
				if($mod_fd===FALSE){
13330
 
13331
					#關閉 web socket 連線
13332
					@fclose($stream_socket_client);
13333
 
13334
					#關閉unix domain socket
13335
					@fclose($usock);
13336
 
13337
					#移除unix domain socket
13338
					@unlink($socketAddr);
13339
 
13340
					#設置執行失敗
13341
					$result["status"]="false";
13342
 
13343
					#設置錯誤訊息
13344
					$result["error"][]="監聽資源異動失敗";
13345
 
13346
					#回傳結果
13347
					return $result;
13348
 
13349
					}#if end
13350
 
13351
				#如果沒有訊息,代表閒置時可以做的事情
13352
				else if($mod_fd===0){
13353
 
13354
					#代表沒收到訊息
13355
					echo ".";
13356
 
13357
					}#if end
13358
 
13359
				#反之有收到來自 web socket server 或 unix socket 的訊息
13360
				else{
13361
 
13362
					#針對每個 sock 陣列
13363
					foreach($read as $readStream){
13364
 
13365
						#如果是來自 web socket server 的訊息
13366
						if($readStream===$stream_socket_client){
13367
 
13368
							#當等待別人連線時,若有人連線進來.
13369
							#$webConn = stream_socket_accept($stream_socket_client);
13370
 
13371
							#如果要 debug
13372
							if($conf["debug"]==="true"){
13373
 
13374
								#debug
13375
								var_dump(__LINE__,"有收到來自 web socket server 的訊息");
13376
 
13377
								}#if end
13378
 
13379
							#讀取內容
13380
							$fread=fread($stream_socket_client,1024);
13381
 
13382
							#如果要 debug
13383
							if($conf["debug"]==="true"){
13384
 
13385
								#debug
13386
								var_dump(__LINE__,strlen($fread),$fread);
13387
 
13388
								}#if end
13389
 
13390
							#函式說明:
13391
							#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
13392
							#回傳結果:
13393
							#$result["function"],當前函式的名稱.
13394
							#$result["argu"],使用的參數.
13395
							#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
13396
							#$result["content"],unmask後的內容.
13397
							#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
13398
							#$result["error"],錯誤訊息陣列.
13399
							#必填參數:
13400
							#$conf["payload"],字串,要解密的訊息.
13401
							$conf["webSock::unmask"]["payload"]=$fread; 
13402
							#可省略參數:
13403
							#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
13404
							$conf["webSock::unmask"]["allowUnmask"]="true";
13405
							#$conf["webSock::unmask"]["debug"]="true";
13406
							#參考資料
13407
							#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
13408
							#https://tools.ietf.org/html/rfc6455
13409
							#https://tools.ietf.org/html/rfc5234
13410
							#備註:
13411
							#無.
13412
							$unmask=webSock::unmask($conf["webSock::unmask"]);
13413
							unset($conf["webSock::unmask"]);
13414
 
13415
							#debug
13416
							#var_dump(__LINE__,$unmask);
13417
 
13418
							#如果出錯
13419
							if($unmask["status"]==="false"){
13420
 
13421
								#關閉 web socket 連線
13422
								@fclose($stream_socket_client);
13423
 
13424
								#關閉unix domain socket
13425
								@fclose($usock);
13426
 
13427
								#移除unix domain socket
13428
								@unlink($socketAddr);
13429
 
13430
								#設置執行失敗
13431
								$result["status"]="false";
13432
 
13433
								#設置執行錯誤訊息
13434
								$result["error"]=$unmask;
13435
 
13436
								#回傳結果
13437
								return $result;
13438
 
13439
								}#if end
13440
 
13441
							#如果收到文字訊息
13442
							if($unmask["type"]==="text"){
13443
 
13444
								#如果有解析出內容
13445
								if(isset($unmask["content"])){
13446
 
13447
									#提示收到的訊息
13448
									echo $unmask["content"];
13449
 
13450
									#傳遞給unix domain client
13451
									$fwrite=fwrite($unixConn,$unmask["content"]);
13452
 
13453
									#如果要 debug
13454
									if($conf["debug"]==="true"){
13455
 
13456
										#debug
13457
										var_dump(__LINE__,$fwrite);
13458
 
13459
										}#if end
13460
 
13461
									#關閉連線
13462
									fclose($unixConn);
13463
 
13464
									}#if end
13465
 
13466
								}#if end
13467
 
13468
							#如果收到ping
13469
							if($unmask["type"]==="ping"){
13470
 
13471
								#函式說明:
13472
								#加密 handshake 後要傳送的 webSocket 訊息 
13473
								#回傳結果:
13474
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13475
								#$result["error"],執行不正常結束的錯訊息陣列.
13476
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
13477
								#$result["argu"],陣列,使用的參數.
13478
								#必填參數:
13479
								#$conf["text"],字串,要加密的訊息.
13480
								$conf["webSock::encode"]["text"]=""; 
13481
								#可省略參數:
13482
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13483
								#$conf["ping"]="true";
13484
								#$conf["pong"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13485
								$conf["webSock::encode"]["pong"]="true";
13486
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
13487
								#$conf["frames"]=array();
13488
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
13489
								$conf["webSock::encode"]["mask"]="true";
13490
								#參考資料:
13491
								#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
13492
								#備註:
13493
								#無.
13494
								$encode=webSock::encode($conf["webSock::encode"]);
13495
								unset($conf["webSock::encode"]);
13496
 
13497
								#如果要 debug
13498
								if($conf["debug"]==="true"){
13499
 
13500
									#debug
13501
									var_dump(__LINE__,$encode);
13502
 
13503
									}#if end
13504
 
13505
								#如果出錯
13506
								if($encode["status"]==="false"){
13507
 
13508
									#設置執行失敗
13509
									$result["status"]="false";
13510
 
13511
									#設置執行錯誤訊息
13512
									$result["error"]=$encode;
13513
 
13514
									#回傳結果
13515
									return $result;
13516
 
13517
									}#if end
13518
 
13519
								#如果要 debug
13520
								if($conf["debug"]==="true"){
13521
 
13522
									#debug
13523
									var_dump(__LINE__,$encode);
13524
 
13525
									}#if end
13526
 
13527
								#針對每個 frame
13528
								foreach($encode["content"] as $fNo => $frame){
13529
 
13530
									#傳遞給 web socket server
13531
									$fwrite=fwrite($stream_socket_client,$frame);
13532
 
13533
									#如果傳遞失敗
13534
									if($fwrite===false){
13535
 
13536
										#關閉 web socket 連線
13537
										@fclose($stream_socket_client);
13538
 
13539
										#關閉unix domain socket
13540
										@fclose($usock);
13541
 
13542
										#移除unix domain socket
13543
										@unlink($socketAddr);
13544
 
13545
										#設置執行失敗
13546
										$result["status"]="false";
13547
 
13548
										#設置執行錯誤訊息
13549
										$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
13550
 
13551
										#回傳結果
13552
										return $result;
13553
 
13554
										}#if end
13555
 
13556
									}#foreach end
13557
 
13558
								}#if end
13559
 
13560
							}#if end
13561
 
13562
						#反之若為來自 unix domain socket 的訊息
13563
						else if($readStream===$usock){
13564
 
13565
							#當等待別人連線時,若有人連線進來.
13566
							$unixConn = stream_socket_accept($usock);
13567
 
13568
							#如果要 debug
13569
							if($conf["debug"]==="true"){
13570
 
13571
								#debug
13572
								var_dump(__LINE__,"有收到來自 unix domain socket 的訊息");
13573
 
13574
								}#if end
13575
 
13576
							#讀取內容
13577
							$fgets=trim(fgets($unixConn,1024));
13578
 
13579
							#如果要 debug
13580
							if($conf["debug"]==="true"){
13581
 
13582
								#debug
13583
								var_dump(__LINE__,strlen($fgets),$fgets);
13584
 
13585
								}#if end
13586
 
13587
							#轉換成 web socket 的格式
13588
							#函式說明:
13589
							#加密 handshake 後要傳送的 webSocket 訊息 
13590
							#回傳結果:
13591
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13592
							#$result["error"],執行不正常結束的錯訊息陣列.
13593
							#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
13594
							#$result["argu"],陣列,使用的參數.
13595
							#必填參數:
13596
							#$conf["text"],字串,要加密的訊息.
13597
							$conf["webSock::encode"]["text"]=$fgets; 
13598
							#可省略參數:
13599
							#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
13600
							#$conf["ping"]="true";
13601
							#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
13602
							#$conf["frames"]=array();
13603
							#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
13604
							$conf["webSock::encode"]["mask"]="true";
13605
							#參考資料:
13606
							#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
13607
							#備註:
13608
							#無.
13609
							$encode=webSock::encode($conf["webSock::encode"]);
13610
							unset($conf["webSock::encode"]);
13611
 
13612
							#如果要 debug
13613
							if($conf["debug"]==="true"){
13614
 
13615
								#debug
13616
								var_dump(__LINE__,$encode);
13617
 
13618
								}#if end
13619
 
13620
							#如果出錯
13621
							if($encode["status"]==="false"){
13622
 
13623
								#設置執行失敗
13624
								$result["status"]="false";
13625
 
13626
								#設置執行錯誤訊息
13627
								$result["error"]=$encode;
13628
 
13629
								#回傳結果
13630
								return $result;
13631
 
13632
								}#if end
13633
 
13634
							#針對每個frame
13635
							foreach($encode["content"] as $fNo => $frame){
13636
 
13637
								#傳遞給 web socket server
13638
								$fwrite=fwrite($stream_socket_client,$frame);
13639
 
13640
								#如果要 debug
13641
								if($conf["debug"]==="true"){
13642
 
13643
									#debug
13644
									var_dump(__LINE__,$fwrite,"傳遞".strlen($frame)."bytes給webSocketServer",$frame);
13645
 
13646
									}#if end
13647
 
13648
								#如果傳遞失敗
13649
								if($fwrite===false){
13650
 
13651
									#關閉 web socket 連線
13652
									@fclose($stream_socket_client);
13653
 
13654
									#關閉unix domain socket
13655
									@fclose($usock);
13656
 
13657
									#移除unix domain socket
13658
									@unlink($socketAddr);
13659
 
13660
									#設置執行失敗
13661
									$result["status"]="false";
13662
 
13663
									#設置執行錯誤訊息
13664
									$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
13665
 
13666
									#回傳結果
13667
									return $result;
13668
 
13669
									}#if end
13670
 
13671
								}#foreach end
13672
 
13673
							}#if end
13674
 
13675
						#例外狀況
13676
						else{
13677
 
13678
							#如果要 debug
13679
							if($conf["debug"]==="true"){
13680
 
13681
								#debug
13682
								var_dump(__LINE__,$readStream);
13683
 
13684
								}#if end
13685
 
13686
							#關閉 web socket 連線
13687
							@fclose($stream_socket_client);
13688
 
13689
							#關閉unix domain socket
13690
							@fclose($usock);
13691
 
13692
							#移除unix domain socket
13693
							@unlink($socketAddr);
13694
 
13695
							#顯示 socket 的狀態
13696
							echo "非預期的錯誤,偵測到不應存在資源有異動".PHP_EOL;
13697
 
13698
							#結束執行並回傳1,代表異常結束
13699
							exit(1);
13700
 
13701
							}#else end
13702
 
13703
						}#foreach end
13704
 
13705
					}#else
13706
 
13707
				#等待1秒
13708
				sleep(1);
13709
 
13710
				}#while end
13711
 
13712
			#設置執行正常
13713
			$result["status"]="true";
13714
 
13715
			#回傳結果
13716
			return $result;
13717
 
13718
			}#if end
13719
 
13720
		#反之不用
13721
		else{
13722
 
13723
			#如果要 debug
13724
			if($conf["debug"]==="true"){
13725
 
13726
				#提示用戶端的文字
13727
				echo "TCP/IP Connection".PHP_EOL;
13728
 
13729
				}#if end
13730
 
13731
			/* Get the port for the WWW service. */
13732
			#http://php.net/manual/en/function.getservbyname.php
13733
			#$service_port = getservbyname('www', 'tcp');
13734
 
13735
			/* Get the IP address for the target host. */
13736
			#http://php.net/manual/en/function.gethostbyname.php
13737
			$ServerAddress = gethostbyname($conf["targetServr"]);
13738
 
13739
			/* Create a TCP/IP socket. */
13740
			$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
13741
 
13742
			#如果建立 socket 失敗
13743
			if ($socket === false) {
13744
 
13745
				#設置執行失敗
13746
				$result["status"]="false";
13747
 
13748
				#設置執行錯誤訊息
13749
				$result["error"][]="socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
13750
 
13751
				#回傳結果
13752
				return $result;
13753
 
13754
				}#if end
13755
 
13756
			#反之
13757
			else {
13758
 
13759
				#如果要 debug
13760
				if($conf["debug"]==="true"){
13761
 
13762
					#印出建立成功訊息
13763
					echo "OK.".PHP_EOL;
13764
 
13765
					}#if end
13766
 
13767
				}#else end
13768
 
13769
			#如果要 debug
13770
			if($conf["debug"]==="true"){
13771
 
13772
				#提示要連線到哪個位址的哪個port
13773
				echo "Attempting to connect to ".$ServerAddress." on port ".$conf["targetPort"]."...";
13774
 
13775
				}#if end
13776
 
13777
			#連線到目標 socket
13778
			$socket_connect=socket_connect($socket, $ServerAddress, $conf["targetPort"]);
13779
 
13780
			#如果連線到 socket 失敗
13781
			if($socket_connect===false){
13782
 
13783
				#設置執行失敗
13784
				$result["status"]="false";
13785
 
13786
				#設置執行錯誤訊息
13787
				$result["error"][]="socket_connect() failed.".PHP_EOL."Reason: ($socket_connect) " . socket_strerror(socket_last_error($socket)) . PHP_EOL;
13788
 
13789
				#回傳結果
13790
				return $result;
13791
 
13792
				}#if end
13793
 
13794
			#反之
13795
			else {
13796
 
13797
				#如果要 debug
13798
				if($conf["debug"]==="true"){
13799
 
13800
					#印出連線成功訊息
13801
					echo "OK.".PHP_EOL;
13802
 
13803
					}#if end
13804
 
13805
				}#else end
13806
 
13807
			}#else end
13808
 
13809
		#初始化要傳送的HEAD資訊
13810
		$in="HEAD / HTTP/1.1"."\r\n";
13811
		$in=$in."Host: ".$ServerAddress.":".$conf["targetPort"]."\r\n";
13812
		$in=$in."Upgrade: websocket"."\r\n";
13813
		$in=$in."Connection: Upgrade"."\r\n";
13814
		$in=$in."Sec-WebSocket-Version: 13"."\r\n";
13815
		$in=$in."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
13816
		$in=$in."\r\n";
13817
 
13818
		#初始化回傳的內容
13819
		$out = '';
13820
 
13821
		#如果連線到 socket 失敗
13822
		if($socket_connect===false){
13823
 
13824
			#提示傳送HTTP HEAD中
13825
			echo "Sending HTTP HEAD request...";
13826
 
13827
			}#if end
13828
 
13829
		#將訊息傳送到socket去
13830
		socket_write($socket, $in, strlen($in));
13831
 
13832
		#如果連線到 socket 失敗
13833
		if($socket_connect===false){
13834
 
13835
			#提示傳送完畢
13836
			echo "OK.".PHP_EOL;
13837
 
13838
			#提示讀取回應中
13839
			echo "Reading response:".PHP_EOL;
13840
 
13841
			}#if end
13842
 
13843
		#無窮迴圈
13844
		while(true){
13845
 
13846
			#一次讀取2048bytes,判斷有無回應,並取得其內容.
13847
			$out = socket_read($socket, 2048);
13848
 
13849
			#如果尚未取得 Sec-WebSocket-Accept
13850
			if(!isset($result["Sec-WebSocket-Accept"])){
13851
 
13852
				#如果連線到 socket 失敗
13853
				if($socket_connect===false){
13854
 
13855
					#印出收到的內容
13856
					echo $out;
13857
 
13858
					}#if end
13859
 
13860
				#如果 $out 有資料
13861
				if($out){
13862
 
13863
					#如果接收到的是字串,且不為空
13864
					if(gettype($out)==="string" && !empty($out)){
13865
 
13866
						#如果有既有的前次回應內容
13867
						if(isset($result["content"])){
13868
 
13869
							#儲存回應的內容
13870
							$result["content"]=$result["content"].$out;
13871
 
13872
							}#if end
13873
 
13874
						#反之
13875
						else{
13876
 
13877
							#儲存回應的內容
13878
							$result["content"]=$out;
13879
 
13880
							}#else end
13881
 
13882
						#涵式說明:
13883
						#將固定格式的字串分開,並回傳分開的結果。
13884
						#回傳結果:
13885
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13886
						#$result["error"],錯誤訊息陣列
13887
						#$result["function"],當前執行的函數名稱.
13888
						#$result["argu"],使用的參數.
13889
						#$result["oriStr"],要分割的原始字串內容
13890
						#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
13891
						#$result["dataCounts"],爲總共分成幾段
13892
						#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
13893
						#必填的參數:
13894
						#$conf["stringIn"],字串,要處理的字串.
13895
						$conf["stringProcess::spiltString"]["stringIn"]=$out;
13896
						#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
13897
						$conf["stringProcess::spiltString"]["spiltSymbol"]="Sec-WebSocket-Accept: ";
13898
						#可省略參數:
13899
						#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
13900
						$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
13901
						$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
13902
						unset($conf["stringProcess::spiltString"]);
13903
 
13904
						#如果執行失敗
13905
						if($spiltString["status"]==="false"){
13906
 
13907
							#設置執行失敗
13908
							$result["status"]="false";
13909
 
13910
							#設置執行錯誤訊息
13911
							$result["error"]=$spiltString;
13912
 
13913
							#回傳結果
13914
							return $result;
13915
 
13916
							}#if end
13917
 
13918
						#取得Sec-WebSocket-Accept
13919
						$result["Sec-WebSocket-Accept"]=trim($spiltString["dataArray"][1]);
13920
 
13921
						#初始化要傳遞的內容			
13922
						$in="id?";
13923
 
13924
						#初始化傳遞的內容長度
13925
						$len=strlen($in);
13926
 
13927
						#設置儲存每個元素為8bit字串的陣列
13928
						$bit8=array();
13929
						$bit8[0]="10000001";
13930
						$bit8[1]="1".sprintf("%07s",base_convert($len,10,2));
13931
 
13932
						#mask key
13933
						$bit8[2]="00000000";
13934
						$bit8[3]="00000000";
13935
						$bit8[4]="00000000";
13936
						$bit8[5]="00000000";
13937
 
13938
						#mask key
13939
						$mask_key=$bit8[2].$bit8[3].$bit8[4].$bit8[5];
13940
 
13941
						#針對每個字,進行mask
13942
						for($i=0;$i<$len;$i++){
13943
 
13944
							$j=$i%4;
13945
 
13946
							$in[$i]=$in[$i] xor $mask_key[$j];
13947
 
13948
							}#for end
13949
 
13950
						#如果連線到 socket 失敗
13951
						if($socket_connect===false){
13952
 
13953
							#提示傳送資料
13954
							echo "Sending Data...".PHP_EOL;
13955
 
13956
							}#if end
13957
 
13958
						#data frame
13959
						$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;
13960
 
13961
						#將訊息傳送到socket去
13962
						socket_write($socket, $in, strlen($in));
13963
 
13964
						}#if end
13965
 
13966
					}#if end	
13967
 
13968
				}#if end
13969
 
13970
			#反之取得了 Sec-WebSocket-Accept 就結束 HTTP/1.1
13971
			else{
13972
 
13973
				#如果連線到 socket 失敗
13974
				if($socket_connect===false){
13975
 
13976
					echo "解密前的內容:".PHP_EOL;
13977
 
13978
					}#if end
13979
 
13980
				#函式說明:
13981
				#將字串中的每個字變成bytes陣列
13982
				#回傳結果:
13983
				#$result...
13984
				#必填參數:
13985
				#$conf["input"],字串,要轉換成bytes陣列的字串
13986
				$conf["stringProcess::str2bytesArray"]["input"]=$out;
13987
				#可省略參數:
13988
				#無
13989
				#建構中...
13990
				$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
13991
				unset($conf["stringProcess::str2bytesArray"]);
13992
 
13993
				#針對每個bytes				
13994
				foreach($str2bytesArray["content"] as $byte){
13995
 
13996
					#函式說明:
13997
					#將bytes數字轉換為bit字串(0跟1來表述)
13998
					#回傳結果:
13999
					#$result...
14000
					#必填參數:
14001
					#$conf["input"],字串,要轉換成byte的字串
14002
					$conf["stringProcess::str2bytesArray"]["bytes"]=$byte;
14003
					#可省略參數:
14004
					#無
14005
					#建構中...
14006
					$bytes2bitString=stringProcess::bytes2bitString($conf["stringProcess::str2bytesArray"]);
14007
					unset($conf["stringProcess::str2bytesArray"]);
14008
 
14009
					#如果連線到 socket 失敗
14010
					if($socket_connect===false){
14011
 
14012
						#debug
14013
						var_dump($bytes2bitString["content"]);
14014
 
14015
						}#if end
14016
 
14017
					}#foreach end
14018
 
14019
				#如果連線到 socket 失敗
14020
				if($socket_connect===false){
14021
 
14022
					echo "解密後接收的內容:".PHP_EOL;
14023
 
14024
					}#if end
14025
 
14026
				#函式說明:
14027
				#解密 handshake 後要接收的訊息
14028
				#回傳結果:
14029
				#$result["function"],當前函式的名稱.
14030
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14031
				#$result["content"],unmask後的內容.
14032
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14033
				#$result["error"],錯誤訊息陣列.
14034
				#必填參數:
14035
				#$conf["payload"],字串,要解密的訊息.
14036
				$conf["webSock::unmask"]["payload"]=$out; 
14037
				#可省略參數:
14038
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14039
				$conf["webSock::unmask"]["allowUnmask"]="true";
14040
				#參考資料
14041
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14042
				#https://tools.ietf.org/html/rfc6455
14043
				#https://tools.ietf.org/html/rfc5234
14044
				#備註:
14045
				#無.
14046
				$unmask=webSock::unmask($conf["webSock::unmask"]);
14047
				unset($conf["webSock::unmask"]);
14048
 
14049
				#如果執行失敗
14050
				if($unmask["status"]==="false"){
14051
 
14052
					#設置執行失敗
14053
					$result["status"]="false";
14054
 
14055
					#設置執行錯誤訊息
14056
					$result["error"]=$unmask;
14057
 
14058
					#回傳結果
14059
					return $result;
14060
 
14061
					}#if end
14062
 
14063
				#記錄接收到的內容
14064
				$received=$unmask["content"];
14065
 
14066
				#如果連線到 socket 失敗
14067
				if($socket_connect===false){	
14068
 
14069
					#debug
14070
					var_dump($received);
14071
 
14072
					}#if end
14073
 
14074
				}#else end
14075
 
14076
			#休息1秒
14077
			sleep(1);
14078
 
14079
			}#while end
14080
 
14081
		#如果連線到 socket 失敗
14082
		if($socket_connect===false){
14083
 
14084
			#提示關閉與 socket 的連線
14085
			echo "Closing socket...";
14086
 
14087
			}#if end
14088
 
14089
		#關閉與 socket 的連線
14090
		socket_close($socket);
14091
 
14092
		#如果連線到 socket 失敗
14093
		if($socket_connect===false){
14094
 
14095
			#提示關閉連線成功
14096
			echo "OK.".PHP_EOL;
14097
 
14098
			}#if end
14099
 
14100
		#設置執行正常
14101
		$result["status"]="true";
14102
 
14103
		#回傳結果
14104
		return $result;
14105
 
14106
		}#function clientDaemon end
14107
 
14108
	/*	
14109
	#函式說明:
14110
	#webSocket的javaScript用戶端
14111
	#回傳結果:
14112
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
14113
	#$result["error"],錯誤訊息陣列.
14114
	#$resutl["function"],當前執行的涵式名稱.
14115
	#$result["argu"],所使用的參數.
14116
	#$result["content"],語法.
14117
	#必填參數:
14118
	#$conf["url"],字串要拜訪的web socket,請省略"ws://".
14119
	$conf["url"]="";
14120
	#可省略參數:
14121
	#$conf["entry"],字串,是否要用加密的wss,預設為"false",代表用ws,若為"true"則為wss.
14122
	#$conf["entry"]="false";
14123
	#$conf["connVar"],字串,用來儲存webSocket連線的物件名稱,預設為"conn".
14124
	#$conf["connVar"]="conn";
14125
	#參考資料:
14126
	#無.
14127
	#備註:
14128
	#無.
14129
	*/
14130
	public static function client(&$conf){
14131
 
14132
		#初始化要回傳的結果
14133
		$result=array();
14134
 
14135
		#取得當前執行的函數名稱
14136
		$result["function"]=__FUNCTION__;
14137
 
14138
		#如果沒有參數
14139
		if(func_num_args()==0){
14140
 
14141
			#設置執行失敗
14142
			$result["status"]="false";
14143
 
14144
			#設置執行錯誤訊息
14145
			$result["error"]="函數".$result["function"]."需要參數";
14146
 
14147
			#回傳結果
14148
			return $result;
14149
 
14150
			}#if end
14151
 
14152
		#取得參數
14153
		$result["argu"]=$conf;
14154
 
14155
		#如果 $conf 不為陣列
14156
		if(gettype($conf)!=="array"){
14157
 
14158
			#設置執行失敗
14159
			$result["status"]="false";
14160
 
14161
			#設置執行錯誤訊息
14162
			$result["error"][]="\$conf變數須為陣列形態";
14163
 
14164
			#如果傳入的參數為 null
14165
			if($conf===null){
14166
 
14167
				#設置執行錯誤訊息
14168
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
14169
 
14170
				}#if end
14171
 
14172
			#回傳結果
14173
			return $result;
14174
 
14175
			}#if end
14176
 
14177
		#檢查參數
14178
		#函式說明:
14179
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
14180
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14181
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
14182
		#$result["function"],當前執行的函式名稱.
14183
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
14184
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
14185
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
14186
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
14187
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
14188
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
14189
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
14190
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
14191
		#必填寫的參數:
14192
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
14193
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
14194
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
14195
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("url");
14196
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
14197
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
14198
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
14199
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
14200
		#可以省略的參數:
14201
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
14202
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
14203
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
14204
		#$conf["canNotBeEmpty"]=array();
14205
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
14206
		#$conf["canBeEmpty"]=array();
14207
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
14208
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
14209
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
14210
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("entry","connVar");
14211
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
14212
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
14213
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
14214
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","conn");
14215
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
14216
		#$conf["arrayCountEqualCheck"][]=array();
14217
		#參考資料來源:
14218
		#array_keys=>http://php.net/manual/en/function.array-keys.php
14219
		#建議:
14220
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
14221
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
14222
		unset($conf["variableCheck::checkArguments"]);
14223
 
14224
		#如果檢查參數失敗
14225
		if($checkArguments["status"]==="false"){
14226
 
14227
			#設置執行失敗
14228
			$result["status"]="false";
14229
 
14230
			#設置執行錯誤訊息
14231
			$result["error"]=$checkArguments;
14232
 
14233
			#回傳結果
14234
			return $result;
14235
 
14236
			}#if end
14237
 
14238
		#如果參數檢查不通過
14239
		if($checkArguments["passed"]==="false"){
14240
 
14241
			#設置執行失敗
14242
			$result["status"]="false";
14243
 
14244
			#設置執行錯誤訊息
14245
			$result["error"]=$checkArguments;
14246
 
14247
			#回傳結果
14248
			return $result;
14249
 
14250
			}#if end		
14251
 
14252
		#初始化 web socket 的協定
14253
		$webSockUrl="ws://";
14254
 
14255
		#如果要加密
14256
		if($conf["entry"]==="true"){
14257
 
14258
			$webSockUrl="wss://";
14259
 
14260
			}#if end
14261
 
14262
		#設置用戶端連線到webSocket的範例
14263
		$script="<script>
14264
 
14265
			//建立 web socket 連線到 ".$webSockUrl.$conf["url"]."
14266
			var ".$conf["connVar"]." = new WebSocket('".$webSockUrl.$conf["url"]."');
14267
 
14268
			//當連線成功後
14269
			".$conf["connVar"].".onopen = function(e)
14270
			{
14271
				//印出連線成功訊息到console
14272
				console.log(\"Connection established!\");
14273
			};
14274
 
14275
			//當有收到訊息時
14276
			".$conf["connVar"].".onmessage = function(e) {
14277
 
14278
				//將訊息顯現在console
14279
				console.log(e.data);
14280
			};
14281
			</script>";
14282
 
14283
		#設置建立webSocket連線的按鈕
14284
		#函式說明:
14285
		#放置按鈕
14286
		#回傳結果:
14287
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14288
		#$result["function"],當前執行的函數.
14289
		#$result["error"],錯誤訊息陣列.
14290
		#$result["content"],按鈕語法. 
14291
		#必要的參數:
14292
		$conf["form::button"]["buttonDisplayValue"]="Send Hello!";#爲按鈕上顯示的文字。
14293
		#可省略的參數:
14294
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
14295
			#其屬性爲   "width","height","font-size","text-align"
14296
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
14297
		$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
14298
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
14299
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
14300
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
14301
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
14302
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
14303
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
14304
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
14305
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
14306
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
14307
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
14308
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
14309
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
14310
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
14311
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
14312
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
14313
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
14314
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
14315
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
14316
		#$conf["formId"],字串,表單的id.
14317
		#$conf["formId"]="";
14318
		#$conf["buttonId"],字串,按鈕的id.
14319
		#$conf["buttonId"]="";
14320
		#參考資料來源:
14321
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
14322
		$button=form::button($conf["form::button"]);
14323
		unset($conf["form::button"]);
14324
 
14325
		#如果建立按鈕失敗
14326
		if($button["status"]==="false"){
14327
 
14328
			#設置執行失敗
14329
			$result["status"]="false";
14330
 
14331
			#設置執行錯誤訊息
14332
			$result["error"]=$button;
14333
 
14334
			#回傳結果
14335
			return $result;
14336
 
14337
			}#if end	
14338
 
14339
		#設置用戶端的html與js語法
14340
		$result["content"]=$button["content"].$script;
14341
 
14342
		#設置執行正常
14343
		$result["status"]="true";
14344
 
14345
		#回傳結果
14346
		return $result;
14347
 
14348
		}#function client end
14349
 
14350
	/*
14351
	#函式說明:
14352
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
14353
	#回傳結果:
14354
	#$result["function"],當前函式的名稱.
14355
	#$result["argu"],使用的參數.
14356
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14357
	#$result["content"],unmask後的內容.
14358
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14359
	#$result["error"],錯誤訊息陣列.
14360
	#必填參數:
14361
	#$conf["payload"],字串,要解密的訊息.
14362
	$conf["payload"]=""; 
14363
	#可省略參數:
14364
	$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14365
	$conf["allowUnmask"]="false";
14366
	#參考資料
14367
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14368
	#https://tools.ietf.org/html/rfc6455
14369
	#https://tools.ietf.org/html/rfc5234
14370
	#備註:
14371
	#無.
14372
	*/
14373
	public static function mask(&$conf){
14374
 
14375
		#改呼叫 webSock::umask
14376
		return webSock::unmask($conf);
14377
 
14378
		}#function mask end
14379
 
14380
	/*
14381
	#函式說明:
14382
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
14383
	#回傳結果:
14384
	#$result["function"],當前函式的名稱.
14385
	#$result["argu"],使用的參數.
14386
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14387
	#$result["content"],unmask後的內容.
14388
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14389
	#$result["error"],錯誤訊息陣列.
14390
	#必填參數:
14391
	#$conf["payload"],字串,要解密的訊息.
14392
	$conf["payload"]=""; 
14393
	#可省略參數:
14394
	#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14395
	#$conf["allowUnmask"]="false";
14396
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
14397
	#$conf["debug"]="false";
14398
	#參考資料
14399
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14400
	#https://tools.ietf.org/html/rfc6455
14401
	#https://tools.ietf.org/html/rfc5234
14402
	#備註:
14403
	#無.
14404
	*/
14405
	public static function unmask(&$conf) {
14406
 
14407
		#初始化要回傳的結果
14408
		$result=array();
14409
 
14410
		#取得當前執行的函數名稱
14411
		$result["function"]=__FUNCTION__;
14412
 
14413
		#取得參數內容
14414
		$result["argu"]=$conf;
14415
 
14416
		#檢查參數
14417
		#函式說明:
14418
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
14419
		#回傳結果:
14420
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14421
		#$result["error"],執行不正常結束的錯訊息陣列.
14422
		#$result["simpleError"],簡單表示的錯誤訊息.
14423
		#$result["function"],當前執行的函式名稱.
14424
		#$result["argu"],設置給予的參數.
14425
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
14426
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
14427
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
14428
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
14429
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
14430
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
14431
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
14432
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
14433
		#必填參數:
14434
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
14435
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
14436
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
14437
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
14438
		#可省略參數:
14439
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
14440
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("payload");
14441
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
14442
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
14443
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
14444
		#$conf["canBeEmptyString"]="false";
14445
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
14446
		#$conf["canNotBeEmpty"]=array();
14447
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
14448
		#$conf["canBeEmpty"]=array();
14449
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
14450
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("allowUnmask","debug");
14451
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
14452
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("allowUnmask","debug");
14453
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
14454
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
14455
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
14456
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false");
14457
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
14458
		#$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="";
14459
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
14460
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
14461
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
14462
		#$conf["disallowAllSkipableVarNotExist"]="";
14463
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
14464
		#$conf["arrayCountEqualCheck"][]=array();
14465
		#參考資料:
14466
		#array_keys=>http://php.net/manual/en/function.array-keys.php
14467
		#備註:
14468
		#無.
14469
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
14470
		unset($conf["variableCheck::checkArguments"]);
14471
 
14472
		#如果檢查參數失敗
14473
		if($checkArguments["status"]==="false"){
14474
 
14475
			#設置執行不正常
14476
			$result["status"]="false";
14477
 
14478
			#設置錯誤訊息
14479
			$result["error"]=$checkArguments;
14480
 
14481
			#回傳結果
14482
			return $result;
14483
 
14484
			}#if end
14485
 
14486
		#如果檢查參數不通過
14487
		if($checkArguments["passed"]==="false"){
14488
 
14489
			#設置執行不正常
14490
			$result["status"]="false";
14491
 
14492
			#設置錯誤訊息
14493
			$result["error"]=$checkArguments;
14494
 
14495
			#回傳結果
14496
			return $result;
14497
 
14498
			}#if end
14499
 
14500
		#取得變數
14501
		$payload=$conf["payload"];
14502
 
14503
		#如果要debug
14504
		if($conf["debug"]==="true"){
14505
 
14506
			#debug payload length
14507
			echo __LINE__." strlen(\$payload)=".strlen($payload).PHP_EOL;
14508
 
14509
			}#if end
14510
 
14511
		#web socket frame 最少為 2bytes
14512
		if(strlen($payload)<2){
14513
 
14514
			#函式說明:
14515
			#將字串中的每個字變成hex的字串陣列
14516
			#回傳結果:
14517
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14518
			#$result["function"],當前執行的函式內容.
14519
			#$result["error"],錯誤訊息陣列.
14520
			#$result["content"],hex的字串陣列.
14521
			#必填參數:
14522
			#$conf["input"],字串,要轉換成bytes陣列的字串.
14523
			$conf["stringProcess::str2bytesArray"]["input"]=$payload;
14524
			#可省略參數:
14525
			#無.
14526
			#參考資料:
14527
			#無.
14528
			#備註:
14529
			#無.
14530
			$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
14531
			unset($conf["stringProcess::str2bytesArray"]);
14532
 
14533
			#如果檢查參數失敗
14534
			if($str2bytesArray["status"]==="false"){
14535
 
14536
				#設置執行不正常
14537
				$result["status"]="false";
14538
 
14539
				#設置錯誤訊息
14540
				$result["error"]=$str2bytesArray;
14541
 
14542
				#回傳結果
14543
				return $result;
14544
 
14545
				}#if end
14546
 
14547
			#設置警告訊息
14548
			$result["warning"][]="web socket frame 最少為 2 bytes,目前收到得為 ".strlen($payload)." bytes";
14549
 
14550
			#設置警告訊息
14551
			$result["warning"][]="接收到的 web socket frame 內容";
14552
 
14553
			#設置警告訊息
14554
			$result["warning"][]="(ASCII):".$payload;
14555
 
14556
			#開始截取輸出
14557
			ob_start();
14558
 
14559
			#針對每個bytes
14560
			for($i=0;$i<count($str2bytesArray["content"]);$i++){
14561
 
14562
				#印出其內容
14563
				echo "[".$str2bytesArray["content"][$i]."]";
14564
 
14565
				#若不是最後一個byte
14566
				if($i===count($str2bytesArray["content"])-1){
14567
 
14568
					#空一格
14569
					echo " ";
14570
 
14571
					}#if end
14572
 
14573
				}#if end
14574
 
14575
			#取得用HEX表示的內容
14576
			$hexStr=ob_get_contents();
14577
 
14578
			#結束截取輸出
14579
			ob_end_clean();
14580
 
14581
			#設置警告訊息
14582
			$result["warning"][]="(HEX):".$hexStr;
14583
 
14584
			#設置為非 web socket frame
14585
			$result["type"]="invalid";
14586
 
14587
			#設置執行正常
14588
			$result["status"]="true";
14589
 
14590
			#回傳結果
14591
			return $result;
14592
 
14593
			}#if end
14594
 
14595
		#如果要debug
14596
		if($conf["debug"]==="true"){
14597
 
14598
			#debug data length
14599
			echo __LINE__." \$length=".(ord($payload[1]) & 127).PHP_EOL;
14600
 
14601
			}#if end
14602
 
14603
		#取得字串長度
14604
		$psl=strlen($payload);
14605
 
14606
		#初始化儲存每個bytes
14607
		$bytes=array();
14608
 
14609
		#函式說明:
14610
		#將字串中的每個字變成bytes陣列
14611
		#回傳結果:
14612
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14613
		#$result["function"],當前執行的函式內容.
14614
		#$result["error"],錯誤訊息陣列.
14615
		#$result["content"],hex的字串陣列.
14616
		#必填參數:
14617
		#$conf["input"],字串,要轉換成bytes陣列的字串
14618
		$conf["stringProcess::str2bytesArray"]["input"]=$payload;
14619
		#可省略參數:
14620
		#無
14621
		$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
14622
		unset($conf["stringProcess::str2bytesArray"]);
14623
 
14624
		#如果執行失敗
14625
		if($str2bytesArray["status"]==="false"){
14626
 
14627
			#設置執行不正常
14628
			$result["status"]="false";
14629
 
14630
			#設置錯誤訊息
14631
			$result["error"]=$str2bytesArray;
14632
 
14633
			#回傳結果
14634
			return $result;
14635
 
14636
			}#if end
14637
 
14638
		#針對每個bytes
14639
		foreach($str2bytesArray["content"] as $bytesNum => $oneByte){
14640
 
14641
			#函式說明:
14642
			#將bytes數字轉換為bit陣列(0跟1來表述)
14643
			#回傳結果:
14644
			#$result...
14645
			#必填參數:
14646
			#$conf["input"],字串,要轉換成byte的字串
14647
			$conf["stringProcess::bytes2byte"]["bytes"]=$oneByte;
14648
			#可省略參數:
14649
			#無
14650
			$bytes2byte=stringProcess::bytes2bitString($conf["stringProcess::bytes2byte"]);
14651
			unset($conf["stringProcess::bytes2byte"]);
14652
 
14653
			#儲存bytes與其bit
14654
			$bytes[$bytesNum]["content"]=$bytes2byte["content"];
14655
 
14656
			}#foreach end
14657
 
14658
		#frame-fin 1 bit
14659
		#%x0 ; more frames of this message follow
14660
		#%x1 ; final frame of this message
14661
		$frameFin=$bytes[0]["content"][0];
14662
 
14663
		#如果不是最後一個 frame
14664
		if($frameFin==="0"){
14665
 
14666
			#如果要debug
14667
			if($conf["debug"]==="true"){
14668
 
14669
				#debug
14670
				echo __LINE__." frame-fin = 0, not supported".PHP_EOL;
14671
 
14672
				}#if end
14673
 
14674
			#設置警告訊息
14675
			$result["warning"][]="目前不支援大於一個frame的mask/unmask功能";
14676
 
14677
			#設置警告訊息
14678
			$result["warning"][]=$bytes;
14679
 
14680
			#設置為非 web socket frame
14681
			$result["type"]="invalid";
14682
 
14683
			#設置執行正常
14684
			$result["status"]="true";
14685
 
14686
			#回傳結果
14687
			return $result;
14688
 
14689
			}#if end
14690
 
14691
		#反之是最後一個 data frame
14692
		else{
14693
 
14694
			#如果要debug
14695
			if($conf["debug"]==="true"){
14696
 
14697
				#debug
14698
				echo __LINE__." frame-fin = 1, means this is a last data frame".PHP_EOL;
14699
 
14700
				}#if end
14701
 
14702
			}#else end
14703
 
14704
		#frame-rsv1 1 bit
14705
		#MUST be 0 unless negotiated otherwise
14706
		$frameRsv1=$bytes[0]["content"][1];
14707
 
14708
		#frame-rsv2 1 bit
14709
		#MUST be 0 unless negotiated otherwise
14710
		$frameRsv2=$bytes[0]["content"][2];
14711
 
14712
		#frame-rsv3 1 bit
14713
		#MUST be 0 unless negotiated otherwise
14714
		$frameRsv3=$bytes[0]["content"][3];
14715
 
14716
		#如果bit[1~3]都為0
14717
		if($frameRsv1===$frameRsv2 && $frameRsv2===$frameRsv3 && $frameRsv3==="0"){
14718
 
14719
			#如果要debug
14720
			if($conf["debug"]==="true"){
14721
 
14722
				#debug
14723
				echo __LINE__." frame-rsv1~3 = 0".PHP_EOL;
14724
 
14725
				}#if end
14726
 
14727
			}#if end
14728
 
14729
		#如果不存在第5個bit
14730
		if(!isset($bytes[0]["content"][4])){
14731
 
14732
			#如果要debug
14733
			if($conf["debug"]==="true"){
14734
 
14735
				#debug
14736
				echo __LINE__." $bytes[0]['content'][4] not set!".PHP_EOL;
14737
 
14738
				}#if end
14739
 
14740
			}#if end
14741
 
14742
		/*
14743
		frame-opcode 4 bit
14744
		frame-opcode-cont       = %x0 ; frame continuation
14745
 
14746
		frame-opcode-non-control= %x1 ; text frame
14747
					/ %x2 ; binary frame
14748
					/ %x3-7
14749
					; 4 bits in length,
14750
					; reserved for further non-control frames
14751
 
14752
		frame-opcode-control    = %x8 ; connection close
14753
					/ %x9 ; ping
14754
					/ %xA ; pong
14755
					/ %xB-F ; reserved for further control
14756
					; frames
14757
					; 4 bits in length
14758
		*/
14759
		#如果 bytes[0] 長度不足 8
14760
		if(gettype($bytes[0]["content"])==="array"){
14761
 
14762
			if(count($bytes[0]["content"])!==8){
14763
 
14764
				#$i為4~7
14765
				for($i=4;$i<8;$i++){
14766
 
14767
					#如果未設置
14768
					if(!isset($bytes[0]["content"][$i])){
14769
 
14770
						#用 "0" 去補
14771
						$bytes[0]["content"][$i]="0";
14772
 
14773
						}#if end
14774
 
14775
					}#for end
14776
 
14777
				}#if end
14778
 
14779
			}#if end
14780
 
14781
		$frameOpcode=$bytes[0]["content"][4].$bytes[0]["content"][5].$bytes[0]["content"][6].$bytes[0]["content"][7];
14782
 
14783
		#如果要debug
14784
		if($conf["debug"]==="true"){
14785
 
14786
			#debug
14787
			echo __LINE__." frame-opcode = ".$frameOpcode.PHP_EOL;
14788
 
14789
			}#if end
14790
 
14791
		$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); 
14792
 
14793
		#設置預設訊息類型為 unknow
14794
		$result["type"]="unknow";
14795
 
14796
		#如果 Opcode 等於 1
14797
		if($frameOpcodeIntX===1){
14798
 
14799
			#如果要debug
14800
			if($conf["debug"]==="true"){
14801
 
14802
				#debug
14803
				echo "It is a text frame".PHP_EOL;
14804
 
14805
				}#if end
14806
 
14807
			#設置該訊息類型為 text
14808
			$result["type"]="text";
14809
 
14810
			}#if end
14811
 
14812
		#如果 Opcode 等於 9
14813
		else if($frameOpcodeIntX===9){
14814
 
14815
			#如果要debug
14816
			if($conf["debug"]==="true"){
14817
 
14818
				#debug
14819
				echo "It is a ping frame".PHP_EOL;
14820
 
14821
				}#if end
14822
 
14823
			#設置該訊息類型為 text
14824
			$result["type"]="ping";
14825
 
14826
			}#if end
14827
 
14828
		#如果是 pong
14829
		else if($frameOpcodeIntX===10){
14830
 
14831
			#如果要debug
14832
			if($conf["debug"]==="true"){
14833
 
14834
				#debug
14835
				echo "It is a pong frame".PHP_EOL;
14836
 
14837
				}#if end
14838
 
14839
			#設置該訊息類型為 pong
14840
			$result["type"]="pong";
14841
 
14842
			}#if end
14843
 
14844
		#frame-masked 1 bit
14845
		#%x0 ;frame is not masked, no frame-masking-key
14846
		#%x1 ;frame is masked, frame-masking-key present 1 bit in lengt
14847
		$frameMasked=$bytes[1]["content"][0]; 
14848
 
14849
		#預設收到的訊息有mask過.
14850
		$masked=true;	
14851
 
14852
		#如果沒有 masked 
14853
		if($frameMasked!=='1'){
14854
 
14855
			#如果不允許沒有設置 masked bit 
14856
			if($conf["allowUnmask"]!=="true"){
14857
 
14858
				#如果要debug
14859
				if($conf["debug"]==="true"){
14860
 
14861
					#debug
14862
					echo __LINE__." frame-masked !== 1, differ with https://tools.ietf.org/html/rfc6455#section-5.3".PHP_EOL;
14863
 
14864
					}#if end
14865
 
14866
				#設置為非 web socket frame
14867
				$result["type"]="invalid";
14868
 
14869
				#設置執行正常
14870
				$result["status"]="true";
14871
 
14872
				#回傳結果
14873
				return $result;
14874
 
14875
				}#if end
14876
 
14877
			#設置收到的訊息沒有mask過.
14878
			$masked=false;
14879
 
14880
			}#if end
14881
 
14882
		#debug
14883
		#echo __LINE__." frame-masked = ".$frameMasked.PHP_EOL;
14884
 
14885
		#frame-payload-length 7 bit, 7+16 bits, or 7+64 bits
14886
		/*
14887
		The length of the "Payload data", in bytes: if 0-125, that is the
14888
		payload length.  If 126, the following 2 bytes interpreted as a
14889
		16-bit unsigned integer are the payload length.  If 127, the
14890
		following 8 bytes interpreted as a 64-bit unsigned integer (the
14891
		most significant bit MUST be 0) are the payload length.  Multibyte
14892
		length quantities are expressed in network byte order.  Note that
14893
		in all cases, the minimal number of bytes MUST be used to encode
14894
		the length, for example, the length of a 124-byte-long string
14895
		can't be encoded as the sequence 126, 0, 124.  The payload length
14896
		is the length of the "Extension data" + the length of the
14897
		"Application data".  The length of the "Extension data" may be
14898
		zero, in which case the payload length is the length of the
14899
		"Application data".
14900
		*/
14901
		if(gettype($bytes[1]["content"])==="array"){
14902
 
14903
			if(count($bytes[1]["content"])!==8){	
14904
 
14905
				#如果要debug
14906
				if($conf["debug"]==="true"){
14907
 
14908
					#debug
14909
					echo __LINE__." payloadLengthBit length !== 8".PHP_EOL;
14910
 
14911
					}#if end
14912
 
14913
				#如果 bit 不存在,用 0 補上
14914
				for($i=1;$i<8;$i++){
14915
 
14916
					#如果未設置
14917
					if(!isset($bytes[1]["content"][$i])){
14918
 
14919
						#用"0"替代
14920
						$bytes[1]["content"][$i]="0";
14921
 
14922
						}#if end
14923
 
14924
					}#for end
14925
 
14926
				#代表是用戶在連線.
14927
				#return "client connected!";
14928
 
14929
				}#if end
14930
 
14931
			}#if end
14932
 
14933
		$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];
14934
 
14935
		#length from 0~127(0~125)
14936
		$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);
14937
 
14938
		#如果長度小於 126
14939
		if($payloadLength<126){
14940
 
14941
			#mask bit start bytes index 
14942
			$maskBitStartBytesIndex=2;
14943
 
14944
			#如果要debug
14945
			if($conf["debug"]==="true"){
14946
 
14947
				#debug
14948
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14949
 
14950
				}#if end
14951
 
14952
			}#if end
14953
 
14954
		#如果長度是 126
14955
		if($payloadLength===126){
14956
 
14957
			$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];
14958
 
14959
			#初始化 payload 長度
14960
			$payloadLength=0;
14961
 
14962
			#2次迴圈,兩個bytes
14963
			for($i=0;$i<2;$i++){
14964
 
14965
				#8次迴圈,1個byte等於8個bit
14966
				for($j=0;$j<8;$j++){
14967
 
14968
					#次方數
14969
					$k=$j+8*$i;
14970
 
14971
					#加總 payload 長度
14972
					$payloadLength=$payloadLength+$bytes[3-$i]["content"][7-$j]*pow(2,$k);
14973
 
14974
					}#for end
14975
 
14976
				}#for end
14977
 
14978
			#mask bit start bytes index 
14979
			$maskBitStartBytesIndex=4;
14980
 
14981
			#如果要debug
14982
			if($conf["debug"]==="true"){
14983
 
14984
				#debug
14985
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14986
 
14987
				}#if end
14988
 
14989
			}#if end
14990
 
14991
		#如果長度是 127	
14992
		else if($payloadLength===127){
14993
 
14994
			$payloadLengthBit="";
14995
 
14996
			#四次迴圈(4個bytes)
14997
			for($i=0;$i<4;$i++){
14998
 
14999
				#8次迴圈,1個byte等於8個bit
15000
				for($j=0;$j<8;$j++){
15001
 
15002
					$payloadLengthBit=$payloadLengthBit.$bytes[4+$i]["content"][0+$j];
15003
 
15004
					}#for end
15005
 
15006
				}#for end
15007
 
15008
			#初始化 payload 長度
15009
			$payloadLength=0;
15010
 
15011
			#四次迴圈(4個bytes)
15012
			for($i=0;$i<4;$i++){
15013
 
15014
				#8次迴圈,1個byte等於8個bit
15015
				for($j=0;$j<8;$j++){
15016
 
15017
					#次方數
15018
					$k=$j+8*$i;
15019
 
15020
					$payloadLength=$payloadLength+$bytes[7-$i]["content"][7-$j]*pow(2,$k);
15021
 
15022
					}#for end
15023
 
15024
				}#for end
15025
 
15026
			#mask bit start bytes index 
15027
			$maskBitStartBytesIndex=8;
15028
 
15029
			#如果要debug
15030
			if($conf["debug"]==="true"){
15031
 
15032
				#debug
15033
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
15034
 
15035
				}#if end
15036
 
15037
			}#if end	
15038
 
15039
		#如果要debug
15040
		if($conf["debug"]==="true"){
15041
 
15042
			#debug
15043
			var_dump(__LINE__,$bytes);
15044
 
15045
			#debug 提示payload的長度的2進位表示法
15046
			echo __LINE__." payload data payloadLengthBit is ".$payloadLengthBit.PHP_EOL;	
15047
 
15048
			#debug 提示payload的長度
15049
			echo __LINE__." payload data length is ".$payloadLength." bytes".PHP_EOL;
15050
 
15051
			}#if end
15052
 
15053
		#如果有mask
15054
		if($masked){
15055
 
15056
			#組合 maskBit 字串
15057
			$maskBitStr=
15058
				chr(base_convert($bytes[$maskBitStartBytesIndex]["content"],2,10)).
15059
				chr(base_convert($bytes[$maskBitStartBytesIndex+1]["content"],2,10)).
15060
				chr(base_convert($bytes[$maskBitStartBytesIndex+2]["content"],2,10)).
15061
				chr(base_convert($bytes[$maskBitStartBytesIndex+3]["content"],2,10));
15062
 
15063
			#如果要debug
15064
			if($conf["debug"]==="true"){
15065
 
15066
				#debug 提示 mask bit 字串
15067
				echo __LINE__." maskBit str is ".$maskBitStr.PHP_EOL;
15068
 
15069
				}#if end
15070
 
15071
			}#if end
15072
 
15073
		#初始化 payload data 字串
15074
		$payloadDataStr="";
15075
 
15076
		#如果有mask
15077
		if($masked){
15078
 
15079
			#有多長就跑幾次
15080
			for($i=0;$i<$payloadLength;$i++){
15081
 
15082
				#串接 masked 的 payload data.
15083
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+4+$i]["content"],2,10));
15084
 
15085
				}#for end
15086
 
15087
			#如果要debug
15088
			if($conf["debug"]==="true"){
15089
 
15090
				#debug 提示 mask bit 字串
15091
				echo __LINE__." masked payload data str is ".$payloadDataStr.PHP_EOL;
15092
 
15093
				}#if end
15094
 
15095
			#unmask payload data
15096
			for($i=0;$i<$payloadLength;$i++){
15097
 
15098
				$payloadDataStr[$i]=$payloadDataStr[$i]^$maskBitStr[$i%4];
15099
 
15100
				}#for end
15101
 
15102
			}#if end
15103
 
15104
		#反之
15105
		else{
15106
 
15107
			#有多長就跑幾次
15108
			for($i=0;$i<$payloadLength;$i++){
15109
 
15110
				#串接 masked 的 payload data.
15111
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+$i]["content"],2,10));
15112
 
15113
				}#for end
15114
 
15115
			}#else end
15116
 
15117
		#取得 umask 後的內容
15118
		$result["content"]=$payloadDataStr;
15119
 
15120
		#設置執行正常
15121
		$result["status"]="true";
15122
 
15123
		#回傳結果	
15124
		return $result;
15125
 
15126
		}#function unmask end
15127
 
15128
	/*
15129
	#函式說明:
15130
	#加密 handshake 後要傳送的 webSocket 訊息 
15131
	#回傳結果:
15132
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15133
	#$result["error"],執行不正常結束的錯訊息陣列.
15134
	#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
15135
	#$result["argu"],陣列,使用的參數.
15136
	#必填參數:
15137
	#$conf["text"],字串,要加密的訊息.
15138
	$conf["text"]=""; 
15139
	#可省略參數:
15140
	#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
15141
	#$conf["payloadIsBin"]="false";
15142
	#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
15143
	#$conf["ping"]="false";
15144
	#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
15145
	#$conf["pong"]="false";
15146
	#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
15147
	#$conf["frames"]=array();
15148
	#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
15149
	#$conf["mask"]="false";
15150
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
15151
	#$conf["debug"]="false";
15152
	#參考資料:
15153
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
15154
	#備註:
15155
	#無.
15156
	*/
15157
	public static function encode(&$conf){
15158
 
15159
		#初始化要回傳的結果
15160
		$result=array();
15161
 
15162
		#設置當其函數名稱
15163
		$result["function"]=__FUNCTION__;
15164
 
15165
		#初始化分割好的 web socket 封包
15166
		$result["content"]=array();
15167
 
15168
		#如果 $conf 不為陣列
15169
		if(gettype($conf)!="array"){
15170
 
15171
			#設置執行失敗
15172
			$result["status"]="false";
15173
 
15174
			#設置執行錯誤訊息
15175
			$result["error"][]="\$conf變數須為陣列形態";
15176
 
15177
			#如果傳入的參數為 null
15178
			if($conf==null){
15179
 
15180
				#設置執行錯誤訊息
15181
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
15182
 
15183
				}#if end
15184
 
15185
			}#if end
15186
 
15187
		#設置放置的參數
15188
		$result["argu"]=$conf;
15189
 
15190
		#函式說明:
15191
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15192
		#回傳結果:
15193
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15194
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
15195
		#$result["simpleError"],簡單表示的錯誤訊息.
15196
		#$result["function"],當前執行的函式名稱.
15197
		#$result["argu"],設置給予的參數.
15198
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15199
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15200
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15201
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15202
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15203
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15204
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15205
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15206
		#必填參數:
15207
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15208
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
15209
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15210
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15211
		#可省略參數:
15212
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15213
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("text");
15214
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
15215
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
15216
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15217
		#$conf["canBeEmptyString"]="false";
15218
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15219
		#$conf["canNotBeEmpty"]=array();
15220
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15221
		#$conf["canBeEmpty"]=array();
15222
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15223
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("payloadIsBin","ping","pong","mask","debug");
15224
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15225
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("payloadIsBin","ping","pong","frames","mask","debug");
15226
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15227
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","string","string");
15228
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15229
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false","false",array(),"false","false");
15230
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15231
		$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="false";
15232
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15233
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15234
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15235
		#$conf["arrayCountEqualCheck"][]=array();
15236
		#參考資料:
15237
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15238
		#備註:
15239
		#無.
15240
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15241
		unset($conf["variableCheck::checkArguments"]);
15242
 
15243
		#如果執行失敗
15244
		if($checkArguments["status"]==="false"){
15245
 
15246
			#設置執行失敗
15247
			$result["status"]="false";
15248
 
15249
			#設置執行錯誤訊息
15250
			$result["error"]=$checkArguments;
15251
 
15252
			#回傳結果
15253
			return $result;
15254
 
15255
			}#if end
15256
 
15257
		#如果參數檢查不通過
15258
		if($checkArguments["passed"]==="false"){
15259
 
15260
			#設置執行失敗
15261
			$result["status"]="false";
15262
 
15263
			#設置執行錯誤訊息
15264
			$result["error"]=$checkArguments;
15265
 
15266
			#回傳結果
15267
			return $result;
15268
 
15269
			}#if end
15270
 
15271
		#如果是要產生 ping/pong 的訊息
15272
		if($conf["ping"]==="true" || $conf["pong"]==="true"){
15273
 
15274
			#強制將payload設置為空
15275
			$conf["text"]="";
15276
 
15277
			}#if end
15278
 
15279
		#取得payload
15280
		$text=$conf["text"];
15281
 
15282
		#取得 payload length
15283
		$length=strlen($text);
15284
 
15285
		#如果沒有payload
15286
		if($length===0){
15287
 
15288
			#初始化第一個 frame 為 最後一個 frame.
15289
			$header="1000";
15290
 
15291
			#如果是ping
15292
			if($conf["ping"]==="true"){
15293
 
15294
				#其訊息類別為 ping
15295
				$header=$header."1001";
15296
 
15297
				}#if end
15298
 
15299
			#如果是pong
15300
			else if($conf["pong"]==="true"){
15301
 
15302
				#其訊息類別為 pong
15303
				$header=$header."1010";
15304
 
15305
				}#if end
15306
 
15307
			#例外狀況
15308
			else{
15309
 
15310
				#設置執行失敗
15311
				$result["status"]="false";
15312
 
15313
				#設置執行錯誤訊息
15314
				$result["error"][]="參數 text 為空時,需要 ping or pong 參數擇一";
15315
 
15316
				#設置執行錯誤訊息
15317
				$result["error"][]=$checkArguments;
15318
 
15319
				#回傳結果
15320
				return $result;
15321
 
15322
				}#else end
15323
 
15324
			}#if end
15325
 
15326
		#反之有payload
15327
		else{
15328
 
15329
			#初始化第一個 frame 為 最後一個 frame.
15330
			$header="1000";
15331
 
15332
			#如果 payload 是 2元碼
15333
			if($conf["payloadIsBin"]==="true"){
15334
 
15335
				#設置 opecode 為 0010
15336
				$header=$header."0010";
15337
 
15338
				}#if end
15339
 
15340
			#反之為 text
15341
			else{
15342
 
15343
				#設置 opecode 為 0001
15344
				$header=$header."0001";
15345
 
15346
				}#else end
15347
 
15348
			}#else end
15349
 
15350
		#如果 payload 長度大於 125
15351
		while($length > 125){
15352
 
15353
			#初始化第一個 frame 為 不為最後一個 frame, 
15354
			$header="0000";
15355
 
15356
			#如果 payload 是 2元碼
15357
			if($conf["payloadIsBin"]==="true"){
15358
 
15359
				#設置 opecode 為 0010
15360
				$header=$header."0010";
15361
 
15362
				}#if end
15363
 
15364
			#反之為 text
15365
			else{
15366
 
15367
				#設置 opecode 為 0001
15368
				$header=$header."0001";
15369
 
15370
				}#else end
15371
 
15372
			#如果已經有前面的內容了
15373
			if(count($result["content"])>0){
15374
 
15375
				#設置為中間的 frame, 其 opcode 為 continue data.
15376
				$header="00000000";
15377
 
15378
				}#if end
15379
 
15380
			#取得125bytes
15381
			$body=substr($text,0,125);
15382
 
15383
			#函式說明:
15384
			#將2進位的8位數字字串,變成bytes字串.
15385
			#回傳結果:
15386
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15387
			#$result["function"],當前執行的函式內容.
15388
			#$result["error"],錯誤訊息陣列.
15389
			#$result["content"],bytes字串,亦即其代表的一個字.
15390
			#必填參數:
15391
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15392
			$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
15393
			#可省略參數:
15394
			#無.
15395
			#參考資料:
15396
			#無.
15397
			#備註:
15398
			#無.
15399
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15400
			unset($conf["stringProcess::bit2byteStr"]);
15401
 
15402
			#如果執行失敗
15403
			if($bit2byteStr["status"]==="false"){
15404
 
15405
				#設置執行失敗
15406
				$result["status"]="false";
15407
 
15408
				#設置執行錯誤訊息
15409
				$result["error"]=$bit2byteStr;
15410
 
15411
				#回傳結果
15412
				return $result;
15413
 
15414
				}#if end
15415
 
15416
			#取得該 byte 字串
15417
			$headerInByte=$bit2byteStr["content"];
15418
 
15419
			#預設不用mask
15420
			$maskBitAndLengthIntString=(string)(125);
15421
 
15422
			#如果需要mask
15423
			if($conf["mask"]==="true"){
15424
 
15425
				$maskBitAndLengthIntString=(string)(125+128);
15426
 
15427
				}#if end
15428
 
15429
			#函式說明:
15430
			#將2進位的8位數字字串,變成bytes字串.
15431
			#回傳結果:
15432
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15433
			#$result["function"],當前執行的函式內容.
15434
			#$result["error"],錯誤訊息陣列.
15435
			#$result["content"],bytes字串,亦即其代表的一個字.
15436
			#必填參數:
15437
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15438
			$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($maskBitAndLengthIntString,10,2);
15439
			#可省略參數:
15440
			#無.
15441
			#參考資料:
15442
			#無.
15443
			#備註:
15444
			#無.
15445
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15446
			unset($conf["stringProcess::bit2byteStr"]);
15447
 
15448
			#如果要 debug
15449
			if($conf["debug"]==="true"){
15450
 
15451
				#debug
15452
				var_dump(__LINE__,$bit2byteStr);
15453
 
15454
				}#if end
15455
 
15456
			#如果執行失敗
15457
			if($bit2byteStr["status"]==="false"){
15458
 
15459
				#設置執行失敗
15460
				$result["status"]="false";
15461
 
15462
				#設置執行錯誤訊息
15463
				$result["error"]=$bit2byteStr;
15464
 
15465
				#回傳結果
15466
				return $result;
15467
 
15468
				}#if end
15469
 
15470
			#取得該 byte 字串
15471
			$lengthInByte=$bit2byteStr["content"];
15472
 
15473
			#初始化 4 bytes mask key.
15474
			$maskKey4bytes="";
15475
 
15476
			#如果需要mask
15477
			if($conf["mask"]==="true"){
15478
 
15479
				#函式說明:
15480
				#隨機產生任意byte(s)組成的字串.
15481
				#回傳結果:
15482
				#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15483
				#$result["function"],當前執行的函式內容.
15484
				#$result["error"],錯誤訊息陣列.
15485
				#$result["content"],用字串來表示的byte(s).
15486
				#必填參數:
15487
				#無.
15488
				#可省略參數:
15489
				#$conf["length"],字串,要產生多少bytes的字串,預設為1.
15490
				$conf["stringProcess::randomByte"]["length"]="4";
15491
				#參考資料:
15492
				#無.
15493
				#備註:
15494
				#無.
15495
				$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
15496
				unset($conf["stringProcess::randomByte"]);
15497
 
15498
				#如果執行失敗
15499
				if($randomByte["status"]==="false"){
15500
 
15501
					#設置執行失敗
15502
					$result["status"]="false";
15503
 
15504
					#設置執行錯誤訊息
15505
					$result["error"]=$randomByte;
15506
 
15507
					#回傳結果
15508
					return $result;
15509
 
15510
					}#if end
15511
 
15512
				#取得隨機產生的 mask key
15513
				$maskKey4bytes=$randomByte["content"];
15514
 
15515
				#函式說明:
15516
				#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
15517
				#回傳結果:
15518
				#$result["function"],當前函式的名稱.
15519
				#$result["argu"],使用的參數.
15520
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
15521
				#$result["content"],unmask後的內容.
15522
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
15523
				#$result["error"],錯誤訊息陣列.
15524
				#必填參數:
15525
				#$conf["payload"],字串,要解密的訊息.
15526
				$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$body; 
15527
				#可省略參數:
15528
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
15529
				$conf["webSock::unmask"]["allowUnmask"]="true";
15530
				#參考資料
15531
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
15532
				#https://tools.ietf.org/html/rfc6455
15533
				#https://tools.ietf.org/html/rfc5234
15534
				#備註:
15535
				#無.
15536
				$unmask=webSock::unmask($conf["webSock::unmask"]);
15537
				unset($conf["webSock::unmask"]);
15538
 
15539
				#debug
15540
				#var_dump(__LINE__,$unmask);
15541
 
15542
				#如果執行失敗
15543
				if($unmask["status"]==="false"){
15544
 
15545
					#設置執行失敗
15546
					$result["status"]="false";
15547
 
15548
					#設置執行錯誤訊息
15549
					$result["error"]=$unmask;
15550
 
15551
					#回傳結果
15552
					return $result;
15553
 
15554
					}#if end
15555
 
15556
				#取得該段的結果
15557
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
15558
 
15559
				}#if end
15560
 
15561
			#反之
15562
			else{
15563
 
15564
				#取得該段的結果
15565
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$body;
15566
 
15567
				}#else end
15568
 
15569
			#取得剩下的內容
15570
			$text=substr($text,125);
15571
 
15572
			#取得 payload length
15573
			$length=strlen($text);
15574
 
15575
			}#while end
15576
 
15577
		#執行到這邊代表剩下的長度用一個 frame 即可表達
15578
 
15579
		#如果已經有內容了
15580
		if(count($result["content"])>0){
15581
 
15582
			#代表不用表示為 text frame 但要表示為最後一個 frame.
15583
			$header="10000000";
15584
 
15585
			}#if end
15586
 
15587
		#函式說明:
15588
		#將2進位的8位數字字串,變成bytes字串.
15589
		#回傳結果:
15590
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15591
		#$result["function"],當前執行的函式內容.
15592
		#$result["error"],錯誤訊息陣列.
15593
		#$result["content"],bytes字串,亦即其代表的一個字.
15594
		#必填參數:
15595
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15596
		$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
15597
		#可省略參數:
15598
		#無.
15599
		#參考資料:
15600
		#無.
15601
		#備註:
15602
		#無.
15603
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15604
		unset($conf["stringProcess::bit2byteStr"]);
15605
 
15606
		#如果執行失敗
15607
		if($bit2byteStr["status"]==="false"){
15608
 
15609
			#設置執行失敗
15610
			$result["status"]="false";
15611
 
15612
			#設置執行錯誤訊息
15613
			$result["error"]=$bit2byteStr;
15614
 
15615
			#回傳結果
15616
			return $result;
15617
 
15618
			}#if end
15619
 
15620
		#取得該 byte 字串
15621
		$headerInByte=$bit2byteStr["content"];
15622
 
15623
		#如果要 debug
15624
		if($conf["debug"]==="true"){
15625
 
15626
			#debug
15627
			var_dump(__LINE__,$length,base_convert($length,10,2));
15628
 
15629
			}#if end
15630
 
15631
		#如果需要mask
15632
		if($conf["mask"]==="true"){
15633
 
15634
			#增加maskbit
15635
			$length=$length+128;
15636
 
15637
			}#if end
15638
 
15639
		#函式說明:
15640
		#將2進位的8位數字字串,變成bytes字串.
15641
		#回傳結果:
15642
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15643
		#$result["function"],當前執行的函式內容.
15644
		#$result["error"],錯誤訊息陣列.
15645
		#$result["content"],bytes字串,亦即其代表的一個字.
15646
		#必填參數:
15647
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15648
		$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($length,10,2);
15649
		#可省略參數:
15650
		#無.
15651
		#參考資料:
15652
		#無.
15653
		#備註:
15654
		#無.
15655
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15656
		unset($conf["stringProcess::bit2byteStr"]);
15657
 
15658
		#如果要 debug
15659
		if($conf["debug"]==="true"){
15660
 
15661
			#debug
15662
			var_dump(__LINE__,$bit2byteStr);
15663
 
15664
			}#if end
15665
 
15666
		#如果執行失敗
15667
		if($bit2byteStr["status"]==="false"){
15668
 
15669
			#設置執行失敗
15670
			$result["status"]="false";
15671
 
15672
			#設置執行錯誤訊息
15673
			$result["error"]=$bit2byteStr;
15674
 
15675
			#回傳結果
15676
			return $result;
15677
 
15678
			}#if end
15679
 
15680
		#取得該 byte 字串
15681
		$lengthInByte=$bit2byteStr["content"];
15682
 
15683
		#初始化 4 bytes mask key.
15684
		$maskKey4bytes="";
15685
 
15686
		#如果需要mask
15687
		if($conf["mask"]==="true"){
15688
 
15689
			#函式說明:
15690
			#隨機產生任意byte(s)組成的字串.
15691
			#回傳結果:
15692
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15693
			#$result["function"],當前執行的函式內容.
15694
			#$result["error"],錯誤訊息陣列.
15695
			#$result["content"],用字串來表示的byte(s).
15696
			#必填參數:
15697
			#無.
15698
			#可省略參數:
15699
			#$conf["length"],字串,要產生多少bytes的字串,預設為1.
15700
			$conf["stringProcess::randomByte"]["length"]="4";
15701
			#參考資料:
15702
			#無.
15703
			#備註:
15704
			#無.
15705
			$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
15706
			unset($conf["stringProcess::randomByte"]);
15707
 
15708
			#如果執行失敗
15709
			if($randomByte["status"]==="false"){
15710
 
15711
				#設置執行失敗
15712
				$result["status"]="false";
15713
 
15714
				#設置執行錯誤訊息
15715
				$result["error"]=$randomByte;
15716
 
15717
				#回傳結果
15718
				return $result;
15719
 
15720
				}#if end
15721
 
15722
			#取得隨機產生的 mask key
15723
			$maskKey4bytes=$randomByte["content"];
15724
 
15725
			}#if end
15726
 
15727
		#函式說明:
15728
		#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
15729
		#回傳結果:
15730
		#$result["function"],當前函式的名稱.
15731
		#$result["argu"],使用的參數.
15732
		#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
15733
		#$result["content"],unmask後的內容.
15734
		#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
15735
		#$result["error"],錯誤訊息陣列.
15736
		#必填參數:
15737
		#$conf["payload"],字串,要解密的訊息.
15738
		$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$text; 
15739
		#可省略參數:
15740
		#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
15741
		$conf["webSock::unmask"]["allowUnmask"]="true";
15742
		#參考資料
15743
		#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
15744
		#https://tools.ietf.org/html/rfc6455
15745
		#https://tools.ietf.org/html/rfc5234
15746
		#備註:
15747
		#無.
15748
		$unmask=webSock::unmask($conf["webSock::unmask"]);
15749
		unset($conf["webSock::unmask"]);
15750
 
15751
		#如果要 debug
15752
		if($conf["debug"]==="true"){
15753
 
15754
			#debug
15755
			var_dump(__LINE__,$unmask);
15756
 
15757
			}#if end
15758
 
15759
		#如果執行失敗
15760
		if($unmask["status"]==="false"){
15761
 
15762
			#設置執行失敗
15763
			$result["status"]="false";
15764
 
15765
			#設置執行錯誤訊息
15766
			$result["error"]=$unmask;
15767
 
15768
			#回傳結果
15769
			return $result;
15770
 
15771
			}#if end
15772
 
15773
		#儲存訊息
15774
		$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
15775
 
15776
		#設置執行正常
15777
		$result["status"]="true";
15778
 
15779
		#回傳結果
15780
		return $result;
15781
 
15782
		}#function encode end
15783
 
15784
	/*
15785
	函式說明:
15786
	提供webSock::nativeSocketTcpIpServer的processFuncs參數所用的函式,可以接受要求傳遞檔案的內容給用戶.
15787
	#回傳結果:
15788
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
15789
	#$result["error"],執行不正常結束的錯訊息陣列.
15790
	#$result["argu"],陣列,使用的參數.
15791
	#必填參數:
15792
	#$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.
15793
	$conf["data"]="";
15794
	#$conf["serverSock"],resource,web socket server socket
15795
	$conf["serverSock"]=$resource;
15796
	#$conf["clientSock"],$resource,web socket client socket
15797
	$conf["clientSock"]=$resource;
15798
	#$conf["clientInfo"],陣列,web socket client info.
15799
	$conf["clientInfo"]=array();
15800
	#$conf["clientIndex"],整數.web socket client index.
15801
	$conf["clientIndex"];
15802
	#$conf["allConn"],陣列,all web socket client info.
15803
	$conf["allConn"]=array();
15804
	#可省略參數:
15805
	#無.
15806
	#參考資料:
15807
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
15808
	#備註:
15809
	#無.
15810
	*/
15811
	public static function getFileContent(&$conf){
15812
 
15813
		#初始化要回傳的結果
15814
		$result=array();
15815
 
15816
		#取得當前執行的函數名稱
15817
		$result["function"]=__FUNCTION__;
15818
 
15819
		#如果沒有參數
15820
		if(func_num_args()==0){
15821
 
15822
			#設置執行失敗
15823
			$result["status"]="false";
15824
 
15825
			#設置執行錯誤訊息
15826
			$result["error"]="函數".$result["function"]."需要參數";
15827
 
15828
			#回傳結果
15829
			return $result;
15830
 
15831
			}#if end
15832
 
15833
		#涵式說明:
15834
		#判斷當前環境為web還是cmd
15835
		#回傳結果:
15836
		#$result,"web"或"cmd"
15837
		if(csInformation::getEnv()==="web"){
15838
 
15839
			#設置執行失敗
15840
			$result["status"]="false";
15841
 
15842
			#設置執行錯誤訊息
15843
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
15844
 
15845
			#回傳結果
15846
			return $result;
15847
 
15848
			}#if end
15849
 
15850
		#取得參數
15851
		$result["argu"]=$conf;
15852
 
15853
		#如果 $conf 不為陣列
15854
		if(gettype($conf)!=="array"){
15855
 
15856
			#設置執行失敗
15857
			$result["status"]="false";
15858
 
15859
			#設置執行錯誤訊息
15860
			$result["error"][]="\$conf變數須為陣列形態";
15861
 
15862
			#如果傳入的參數為 null
15863
			if(is_null($conf)){
15864
 
15865
				#設置執行錯誤訊息
15866
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
15867
 
15868
				}#if end
15869
 
15870
			#回傳結果
15871
			return $result;
15872
 
15873
			}#if end
15874
 
15875
		#debug
15876
		#var_dump(__FUNCTION__,__LINE__,$conf);
15877
 
15878
		#檢查參數
15879
		#函式說明:
15880
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15881
		#回傳結果:
15882
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15883
		#$result["error"],執行不正常結束的錯訊息陣列.
15884
		#$result["simpleError"],簡單表示的錯誤訊息.
15885
		#$result["function"],當前執行的函式名稱.
15886
		#$result["argu"],設置給予的參數.
15887
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15888
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15889
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15890
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15891
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15892
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15893
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15894
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15895
		#必填參數:
15896
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15897
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
15898
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15899
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15900
		#可省略參數:
15901
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15902
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientSock","clientInfo","clientIndex","allConn");
15903
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
15904
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","resource","array","integer","array");
15905
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15906
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
15907
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15908
		#$conf["canNotBeEmpty"]=array();
15909
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15910
		#$conf["canBeEmpty"]=array();
15911
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15912
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("Range","partSize");
15913
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15914
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("Range","partSize");
15915
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15916
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","partSize");
15917
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15918
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,"1024000");
15919
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15920
		#$conf["disallowAllSkipableVarIsEmpty"]="";
15921
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15922
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15923
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
15924
		#$conf["disallowAllSkipableVarNotExist"]="";
15925
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15926
		#$conf["arrayCountEqualCheck"][]=array();
15927
		#參考資料:
15928
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15929
		#備註:
15930
		#無.
15931
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15932
		unset($conf["variableCheck::checkArguments"]);
15933
 
15934
		#debug
15935
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
15936
 
15937
		#如果執行失敗
15938
		if($checkArguments["status"]==="false"){
15939
 
15940
			#設置錯誤訊息
15941
			$result["error"]=$checkArguments;
15942
 
15943
			#var_dump,交給下個 processFuncs 處理
15944
			$result["status"]="false";
15945
 
15946
			#回傳結果
15947
			return $result;
15948
 
15949
			}#if end
15950
 
15951
		#如果檢查不通過
15952
		if($checkArguments["passed"]==="false"){
15953
 
15954
			#不處理,略過,交給下個 processFuncs 處理
15955
			$result["status"]="continue";
15956
 
15957
			#回傳結果
15958
			return $result;
15959
 
15960
			}#if end
15961
 
15962
		#檢查收到的訊息是否為json格式
15963
		$revJson=@json_decode($conf["data"]);
15964
 
15965
		#如果不是 json
15966
		if($revJson===null){
15967
 
15968
			#不處理,略過,交給下個 processFuncs 處理
15969
			$result["status"]="continue";
15970
 
15971
			#回傳結果
15972
			return $result;
15973
 
15974
			}#if enf
15975
 
15976
		#轉換為陣列
15977
		$revJson=(array)($revJson);
15978
 
15979
		#檢查參數
15980
		#函式說明:
15981
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15982
		#回傳結果:
15983
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15984
		#$result["error"],執行不正常結束的錯訊息陣列.
15985
		#$result["simpleError"],簡單表示的錯誤訊息.
15986
		#$result["function"],當前執行的函式名稱.
15987
		#$result["argu"],設置給予的參數.
15988
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15989
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15990
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15991
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15992
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15993
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15994
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15995
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15996
		#必填參數:
15997
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15998
		$conf["variableCheck::checkArguments"]["varInput"]=&$revJson;
15999
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
16000
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
16001
		#可省略參數:
16002
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
16003
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("Method","Host","File");
16004
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
16005
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string");
16006
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
16007
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
16008
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
16009
		#$conf["canNotBeEmpty"]=array();
16010
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
16011
		#$conf["canBeEmpty"]=array();
16012
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
16013
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("id","Range","partSize");
16014
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
16015
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","Range","partSize");
16016
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
16017
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string");
16018
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
16019
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,null,"1024000");
16020
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
16021
		#$conf["disallowAllSkipableVarIsEmpty"]="";
16022
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
16023
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
16024
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
16025
		#$conf["disallowAllSkipableVarNotExist"]="";
16026
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
16027
		#$conf["arrayCountEqualCheck"][]=array();
16028
		#參考資料:
16029
		#array_keys=>http://php.net/manual/en/function.array-keys.php
16030
		#備註:
16031
		#無.
16032
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
16033
		unset($conf["variableCheck::checkArguments"]);
16034
 
16035
		#debug
16036
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
16037
 
16038
		#如果執行失敗
16039
		if($checkArguments["status"]==="false"){
16040
 
16041
			#設置錯誤訊息
16042
			$result["error"]=$checkArguments;
16043
 
16044
			#var_dump,交給下個 processFuncs 處理
16045
			$result["status"]="false";
16046
 
16047
			#回傳結果
16048
			return $result;
16049
 
16050
			}#if end
16051
 
16052
		#如果檢查不通過
16053
		if($checkArguments["passed"]==="false"){
16054
 
16055
			#不處理,略過,交給下個 processFuncs 處理
16056
			$result["status"]="continue";
16057
 
16058
			#回傳結果
16059
			return $result;
16060
 
16061
			}#if end
16062
 
16063
		#如果是 GET Method
16064
		if($revJson["Method"]==="GET"){
16065
 
16066
			#解析 apache vhost info
16067
			#函式說明:
16068
			#使用 linux 的 httpd 指令來取得 vhost 資訊.
16069
			#回傳結果:
16070
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16071
			#$result["error"],錯誤訊息.
16072
			#$result["function"],當前執行的函式名稱.
16073
			#$result["content"],得到的結果陣列,每個元素可能會含有的key有ServerName、DocumentRoot、ServerAlias,其中DocumentRoot的數值會是用""包起來的路徑.
16074
			#必填參數:
16075
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
16076
			$conf["cmd::httpdGetVhostInfo"]["fileArgu"]=__FILE__;
16077
			#可省略參數:
16078
			#無.
16079
			#參考資料:
16080
			#無
16081
			#備註:
16082
			#無.
16083
			$httpdGetVhostInfo=cmd::httpdGetVhostInfo($conf["cmd::httpdGetVhostInfo"]);
16084
			unset($conf["cmd::httpdGetVhostInfo"]);
16085
 
16086
			#debug
16087
			#var_dump(__FUNCTION__,__LINE__,$httpdGetVhostInfo);
16088
 
16089
			#如果執行失敗
16090
			if($httpdGetVhostInfo["status"]==="false"){
16091
 
16092
				#設置錯誤訊息
16093
				$result["error"]=$httpdGetVhostInfo;
16094
 
16095
				#var_dump,交給下個 processFuncs 處理
16096
				$result["status"]="false";
16097
 
16098
				#回傳結果
16099
				return $result;
16100
 
16101
				}#if end
16102
 
16103
			#針對每個結果
16104
			foreach($httpdGetVhostInfo["content"] as $vhost){
16105
 
16106
				#如果有 ServerName
16107
				if(isset($vhost["ServerName"])){
16108
 
16109
					#如果是要找的 Host
16110
					if($vhost["ServerName"]===$revJson["Host"]){
16111
 
16112
						#如果有 DocumentRoot
16113
						if(isset($vhost["DocumentRoot"])){
16114
 
16115
							#組合要取得的檔案路徑與名稱
16116
							$file=$vhost["DocumentRoot"]."/".$revJson["File"];
16117
 
16118
							#debug
16119
							#var_dump(__LINE__,$file);
16120
 
16121
							#如果有 Range 參數
16122
							if(isset($revJson["Range"])){
16123
 
16124
								#格式參考
16125
								#bytes=0-499
16126
 
16127
								#函式說明:
16128
								#將字串特定關鍵字與其前面的內容剔除
16129
								#回傳結果:
16130
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16131
								#$result["error"],錯誤訊息陣列.
16132
								#$result["warning"],警告訊息鎮列.
16133
								#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
16134
								#$result["function"],當前執行的函數名稱.
16135
								#$result["argu"],使用的參數.
16136
								#$result["oriStr"],要處理的原始字串內容.
16137
								#$result["content"],處理好的的字串內容.	
16138
								#必填參數:
16139
								#$conf["stringIn"],字串,要處理的字串.
16140
								$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$revJson["Range"];
16141
								#$conf["keyWord"],字串,特定字串.
16142
								$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="bytes=";
16143
								#可省略參數:
16144
								#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
16145
								#$conf["recursive"]="true";
16146
								#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
16147
								#$conf["lastResult"]=$delStrBeforeKeyWord;
16148
								#參考資料:
16149
								#無.
16150
								#備註:
16151
								#無.
16152
								$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
16153
								unset($conf["stringProcess::delStrBeforeKeyWord"]);
16154
 
16155
								#如果執行失敗
16156
								if($delStrBeforeKeyWord["status"]==="false"){
16157
 
16158
									#設置錯誤訊息
16159
									$result["error"]=$delStrBeforeKeyWord;
16160
 
16161
									#var_dump,交給下個 processFuncs 處理
16162
									$result["status"]="false";
16163
 
16164
									#回傳結果
16165
									return $result;
16166
 
16167
									}#if end
16168
 
16169
								#如果沒有該有的關鍵字
16170
								if($delStrBeforeKeyWord["founded"]==="false"){
16171
 
16172
									#設置錯誤訊息
16173
									$result["error"]=$delStrBeforeKeyWord;
16174
 
16175
									#var_dump,交給下個 processFuncs 處理
16176
									$result["status"]="false";
16177
 
16178
									#回傳結果
16179
									return $result;
16180
 
16181
									}#if end
16182
 
16183
								#解析 bytes start and end
16184
								#函式說明:
16185
								#將固定格式的字串分開,並回傳分開的結果.
16186
								#回傳結果:
16187
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16188
								#$result["error"],錯誤訊息陣列
16189
								#$result["function"],當前執行的函數名稱.
16190
								#$result["argu"],使用的參數.
16191
								#$result["oriStr"],要分割的原始字串內容
16192
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
16193
								#$result["dataCounts"],爲總共分成幾段
16194
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
16195
								#必填參數:
16196
								#$conf["stringIn"],字串,要處理的字串.
16197
								$conf["stringProcess::spiltString"]["stringIn"]=$delStrBeforeKeyWord["content"];
16198
								#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
16199
								$conf["stringProcess::spiltString"]["spiltSymbol"]="-";
16200
								#可省略參數:
16201
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
16202
								#$conf["allowEmptyStr"]="false";
16203
								#參考資料:
16204
								#無.
16205
								#備註:
16206
								#無.
16207
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
16208
								unset($conf["stringProcess::spiltString"]);
16209
 
16210
								#如果執行失敗
16211
								if($spiltString["status"]==="false"){
16212
 
16213
									#設置錯誤訊息
16214
									$result["error"]=$spiltString;
16215
 
16216
									#var_dump,交給下個 processFuncs 處理
16217
									$result["status"]="false";
16218
 
16219
									#回傳結果
16220
									return $result;
16221
 
16222
									}#if end
16223
 
16224
								#如果沒有應該有的 - 符號
16225
								if($spiltString["found"]==="false"){
16226
 
16227
									#設置錯誤訊息
16228
									$result["error"]=$spiltString;
16229
 
16230
									#var_dump,交給下個 processFuncs 處理
16231
									$result["status"]="false";
16232
 
16233
									#回傳結果
16234
									return $result;
16235
 
16236
									}#if end
16237
 
16238
								#如果沒有分割成2段
16239
								if($spiltString["dataCounts"]!==2){
16240
 
16241
									#設置錯誤訊息
16242
									$result["error"]=$spiltString;
16243
 
16244
									#var_dump,交給下個 processFuncs 處理
16245
									$result["status"]="false";
16246
 
16247
									#回傳結果
16248
									return $result;
16249
 
16250
									}#if end
16251
 
16252
								#依照Range來取得檔案內容
16253
								#函式說明:
16254
								#取得檔案的部分內容
16255
								#回傳結果:
16256
								#$result["status"],"true"代表移除成功,"false"代表移除失敗.
16257
								#$result["error"],錯誤訊息陣列.
16258
								#$result["function"],當前執行的函數名稱.
16259
								#$result["cmd"],執行的指令.
16260
								#$result["content"],取得的檔案內容.
16261
								#$result["length"],取得的內容長度.
16262
								#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
16263
								#$result["mimeType"],檔案的 mime type.
16264
								#必填參數:
16265
								#$conf["file"],字串,檔案的路徑與名稱.
16266
								$conf["fileAccess::getFilePart"]["file"]=$file;
16267
								#$conf["fileArgu"],字串,__FILE__的內容.
16268
								$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
16269
								#$conf["bytes"],整數字串,要讀取多少bytes.
16270
								$conf["fileAccess::getFilePart"]["bytes"]=$spiltString["dataArray"][1]-$spiltString["dataArray"][0]+1;
16271
								#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
16272
								$conf["fileAccess::getFilePart"]["startIndex"]=$spiltString["dataArray"][0];
16273
								#可省略參數:
16274
								#無
16275
								#參考資料:
16276
								#無.
16277
								#備註:
16278
								#無
16279
								$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
16280
								unset($conf["fileAccess::getFilePart"]);
16281
 
16282
								#如果執行失敗
16283
								if($getFilePart["status"]==="false"){
16284
 
16285
									#設置錯誤訊息
16286
									$result["error"]=$getFilePart;
16287
 
16288
									#var_dump,交給下個 processFuncs 處理
16289
									$result["status"]="false";
16290
 
16291
									#回傳結果
16292
									return $result;
16293
 
16294
									}#if end
16295
 
16296
								#初始化要傳遞的訊息
16297
								$msg=array();
16298
 
16299
								#設置為最後一份了
16300
								$msg["LastPart"]="true";
16301
 
16302
								#設置資料內容類型為binary
16303
								$msg["dataType"]="binary";
16304
 
16305
								#設置內容
16306
								$msg["content"]=$getFilePart["content"];
16307
 
16308
								#設置 mimeType
16309
								$msg["mimeType"]=$getFilePart["mimeType"];
16310
 
16311
								#如果有設置 id
16312
								if(isset($revJson["id"])){
16313
 
16314
									#設置資料的 id
16315
									$msg["id"]=$revJson["id"];
16316
 
16317
									}#if end
16318
 
16319
								#函式說明:
16320
								#加密 handshake 後要傳送的訊息 
16321
								#回傳結果:
16322
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16323
								#$result["error"],執行不正常結束的錯訊息陣列.
16324
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16325
								#$result["argu"],陣列,使用的參數.
16326
								#必填參數:
16327
								#$conf["text"],字串,要加密的訊息.
16328
								$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
16329
								#可省略參數:
16330
								#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16331
								#$conf["webSock::encode"]["payloadIsBin"]="true";
16332
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16333
								#$conf["ping"]="false";
16334
								#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16335
								#$conf["pong"]="false";
16336
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16337
								#$conf["frames"]=array();
16338
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16339
								#$conf["webSock::encode"]["mask"]="false";
16340
								#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16341
								#$conf["debug"]="false";
16342
								#參考資料:
16343
								#無.
16344
								#備註:
16345
								#無.
16346
								$talkback=webSock::encode($conf["webSock::encode"]);
16347
								unset($conf["webSock::encode"]);
16348
 
16349
								#如果執行失敗
16350
								if($talkback["status"]==="false"){
16351
 
16352
									#印出結果
16353
									var_dump($talkback);
16354
 
16355
									#結束執行
16356
									exit;
16357
 
16358
									}#if end
16359
 
16360
								#針對每個訊息的分段
16361
								foreach($talkback["content"] as $msg){
16362
 
16363
									#回傳訊息
16364
									$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16365
 
16366
									#如果傳遞訊息給用戶失敗
16367
									if($socket_write===false){
16368
 
16369
										#取得錯誤代碼
16370
										$errorCode=socket_last_error($conf["clientSock"]);
16371
 
16372
										#設置執行失敗
16373
										$result["status"]="false";
16374
 
16375
										#設置錯誤代碼
16376
										$result["error"][]="error code:".$errorCode;
16377
 
16378
										#設置錯誤代碼說明
16379
										$result["erorr"][]="error description:".socket_strerror($errorCode);
16380
 
16381
										#回傳結果
16382
										return $result;
16383
 
16384
										}#if end
16385
 
16386
									}#foreach end
16387
 
16388
								#設置正常,結束後面函式的執行
16389
								$result["status"]="true";
16390
 
16391
								#回傳結果
16392
								return $result;
16393
 
16394
								}#if end
16395
 
16396
							#反之沒有 Rnage 參數
16397
							else{
16398
 
16399
								#執行到這邊代表要取得全部的檔案內容
16400
 
16401
								#debug
16402
								#var_dump(__LINE__,"get full file content");
16403
 
16404
								#第一部分的編號
16405
								$partNo=0;
16406
 
16407
								#無窮迴圈
16408
								while(true){
16409
 
16410
									#分段取得檔案
16411
									#函式說明:
16412
									#取得檔案的部分內容
16413
									#回傳結果:
16414
									#$result["status"],"true"代表移除成功,"false"代表移除失敗.
16415
									#$result["error"],錯誤訊息陣列.
16416
									#$result["function"],當前執行的函數名稱.
16417
									#$result["cmd"],執行的指令.
16418
									#$result["content"],取得的檔案內容.
16419
									#$result["length"],取得的內容長度.
16420
									#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
16421
									#$result["mimeType"],檔案的 mime type.
16422
									#必填參數:
16423
									#$conf["file"],字串,檔案的路徑與名稱.
16424
									$conf["fileAccess::getFilePart"]["file"]=$file;
16425
									#$conf["fileArgu"],字串,__FILE__的內容.
16426
									$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
16427
									#$conf["bytes"],整數字串,要讀取多少bytes.
16428
									$conf["fileAccess::getFilePart"]["bytes"]=$revJson["partSize"];
16429
									#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
16430
									$conf["fileAccess::getFilePart"]["startIndex"]=$partNo*$revJson["partSize"];
16431
									#可省略參數:
16432
									#無
16433
									#參考資料:
16434
									#無.
16435
									#備註:
16436
									#無
16437
									$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
16438
									unset($conf["fileAccess::getFilePart"]);
16439
 
16440
									#debug
16441
									#var_dump(__LINE__,$getFilePart);
16442
 
16443
									#如果執行失敗
16444
									if($getFilePart["status"]==="false"){
16445
 
16446
										#設置錯誤訊息
16447
										$result["error"]=$getFilePart;
16448
 
16449
										#var_dump,交給下個 processFuncs 處理
16450
										$result["status"]="false";
16451
 
16452
										#回傳結果
16453
										return $result;
16454
 
16455
										}#if end
16456
 
16457
									#初始化要傳遞的訊息
16458
									$msg=array();
16459
 
16460
									#設置不為最後一份
16461
									$msg["LastPart"]="false";
16462
 
16463
									#設置資料內容類型為binary
16464
									$msg["dataType"]="binary";
16465
 
16466
									#設置內容
16467
									$msg["content"]=$getFilePart["content"];
16468
 
16469
									#設置 mimeType
16470
									$msg["mimeType"]=$getFilePart["mimeType"];
16471
 
16472
									#如果有設置 id
16473
									if(isset($revJson["id"])){
16474
 
16475
										#設置資料的 id
16476
										$msg["id"]=$revJson["id"];
16477
 
16478
										}#if end
16479
 
16480
									#如果偵測到檔案結尾
16481
									if($getFilePart["EOF"]==="true"){
16482
 
16483
										#設置為最後一份了
16484
										$msg["LastPart"]="true";
16485
 
16486
										#如果沒有內容
16487
										if($getFilePart["length"]===0){
16488
 
16489
											#檔案區塊數字-1
16490
											$partNo--;
16491
 
16492
											}#if end
16493
 
16494
										#傳遞給 client - start
16495
 
16496
										#編碼後的訊息
16497
										$msgEncoded=base64_encode(urlencode(json_encode($msg)));
16498
 
16499
										#debug
16500
										#var_dump(__LINE__,$msg,$msgEncoded);
16501
 
16502
										#函式說明:
16503
										#加密 handshake 後要傳送的訊息 
16504
										#回傳結果:
16505
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16506
										#$result["error"],執行不正常結束的錯訊息陣列.
16507
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16508
										#$result["argu"],陣列,使用的參數.
16509
										#必填參數:
16510
										#$conf["text"],字串,要加密的訊息.
16511
										$conf["webSock::encode"]["text"]=$msgEncoded; 
16512
										#可省略參數:
16513
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16514
										#$conf["webSock::encode"]["payloadIsBin"]="false";
16515
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16516
										#$conf["ping"]="false";
16517
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16518
										#$conf["pong"]="false";
16519
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16520
										#$conf["frames"]=array();
16521
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16522
										#$conf["webSock::encode"]["mask"]="false";
16523
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16524
										#$conf["debug"]="false";
16525
										#參考資料:
16526
										#無.
16527
										#備註:
16528
										#無.
16529
										$talkback=webSock::encode($conf["webSock::encode"]);
16530
										unset($conf["webSock::encode"]);
16531
 
16532
										#debug
16533
										#var_dump(__LINE__,$talkback);
16534
 
16535
										#如果執行失敗
16536
										if($talkback["status"]==="false"){
16537
 
16538
											#印出結果
16539
											var_dump($talkback);
16540
 
16541
											#結束執行
16542
											exit;
16543
 
16544
											}#if end
16545
 
16546
										#針對每個訊息的分段
16547
										foreach($talkback["content"] as $msg){
16548
 
16549
											#回傳訊息
16550
											$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16551
 
16552
											#debug
16553
											#var_dump(__LINE__,$socket_write,$msg);
16554
 
16555
											#如果傳遞訊息給用戶失敗
16556
											if($socket_write===false){
16557
 
16558
												#取得錯誤代碼
16559
												$errorCode=socket_last_error($conf["clientSock"]);
16560
 
16561
												#設置執行失敗
16562
												$result["status"]="false";
16563
 
16564
												#設置錯誤代碼
16565
												$result["error"][]="error code:".$errorCode;
16566
 
16567
												#設置錯誤代碼說明
16568
												$result["erorr"][]="error description:".socket_strerror($errorCode);
16569
 
16570
												#回傳結果
16571
												return $result;
16572
 
16573
												}#if end
16574
 
16575
											}#foreach end
16576
 
16577
										#傳遞給 client - end
16578
 
16579
										#結束 while
16580
										break;
16581
 
16582
										}#if end
16583
 
16584
									#傳遞給 client - start
16585
 
16586
									#debug
16587
									#var_dump(__LINE__,"start tranfer");
16588
 
16589
									#函式說明:
16590
									#加密 handshake 後要傳送的訊息 
16591
									#回傳結果:
16592
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16593
									#$result["error"],執行不正常結束的錯訊息陣列.
16594
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
16595
									#$result["argu"],陣列,使用的參數.
16596
									#必填參數:
16597
									#$conf["text"],字串,要加密的訊息.
16598
									$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
16599
									#可省略參數:
16600
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
16601
									#$conf["webSock::encode"]["payloadIsBin"]="true";
16602
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
16603
									#$conf["ping"]="false";
16604
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
16605
									#$conf["pong"]="false";
16606
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
16607
									#$conf["frames"]=array();
16608
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
16609
									#$conf["webSock::encode"]["mask"]="false";
16610
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
16611
									#$conf["debug"]="false";
16612
									#參考資料:
16613
									#無.
16614
									#備註:
16615
									#無.
16616
									$talkback=webSock::encode($conf["webSock::encode"]);
16617
									unset($conf["webSock::encode"]);
16618
 
16619
									#如果執行失敗
16620
									if($talkback["status"]==="false"){
16621
 
16622
										#印出結果
16623
										var_dump($talkback);
16624
 
16625
										#結束執行
16626
										exit;
16627
 
16628
										}#if end
16629
 
16630
									#針對每個訊息的分段
16631
									foreach($talkback["content"] as $msg){
16632
 
16633
										#回傳訊息
16634
										$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16635
 
16636
										#如果傳遞訊息給用戶失敗
16637
										if($socket_write===false){
16638
 
16639
											#取得錯誤代碼
16640
											$errorCode=socket_last_error($conf["clientSock"]);
16641
 
16642
											#設置執行失敗
16643
											$result["status"]="false";
16644
 
16645
											#設置錯誤代碼
16646
											$result["error"][]="error code:".$errorCode;
16647
 
16648
											#設置錯誤代碼說明
16649
											$result["erorr"][]="error description:".socket_strerror($errorCode);
16650
 
16651
											#回傳結果
16652
											return $result;
16653
 
16654
											}#if end
16655
 
16656
										}#foreach end
16657
 
16658
									#傳遞給 client - end
16659
 
16660
									#檔案區塊數字+1
16661
									$partNo++;
16662
 
16663
									}#while end
16664
 
16665
								#設置執行正常
16666
								$result["status"]="true";
16667
 
16668
								#回傳結果
16669
								return $result;
16670
 
16671
								}#else end
16672
 
16673
							}#if end
16674
 
16675
						}#if end
16676
 
16677
					}#if end
16678
 
16679
				}#foreach end
16680
 
16681
			#設置執行不正常
16682
			$result["status"]="false";
16683
 
16684
			#設置執行錯誤
16685
			$result["error"]="no matched ServerName";
16686
 
16687
			#debug
66 liveuser 16688
			var_dump(__FUNCTION__,__LINE__,$result);
3 liveuser 16689
 
16690
			#回傳結果
16691
			return $result;
16692
 
16693
			}#if end
16694
 
16695
		#設置執行不正常
16696
		$result["status"]="false";
16697
 
16698
		#設置執行錯誤
16699
		$result["error"]="Method should be GET";
16700
 
16701
		#回傳結果
16702
		return $result;
16703
 
16704
		}#function getFileContent end
16705
 
66 liveuser 16706
	/*
16707
	#函式說明:
16708
	#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
16709
	#回傳結果:
16710
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16711
	#$result["error"],執行不正常結束的錯訊息陣列.
16712
	#$result["argu"],陣列,使用的參數.
16713
	#必填參數:
16714
	#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
16715
	$conf["data"]="";
16716
	#$conf["serverSock"],resource,web socket server socket
16717
	$conf["serverSock"]=$resource;
16718
	#$conf["clientSock"],$resource,web socket client socket
16719
	$conf["clientSock"]=$resource;
16720
	#$conf["clientInfo"],陣列,web socket client info.
16721
	$conf["clientInfo"]=array();
16722
	#$conf["clientIndex"],整數.web socket client index.
16723
	$conf["clientIndex"];
16724
	#$conf["allConn"],陣列,all web socket client info.
16725
	$conf["allConn"]=array();
16726
	#$conf["func"],字串,要檢查的是否具備權限的函式.
16727
	$conf["func"]="";
16728
	#可省略參數:
16729
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
16730
	#$conf["wsMode"]="true";
16731
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
16732
	#$conf["gpgId"]=gnupgId;
16733
	#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
16734
	#$conf["falseAllowFuncPlus"]=array();
16735
	#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
16736
	#$conf["publicAllowFuncPlus"]=array();
16737
	#參考資料:
16738
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
16739
	#備註:
16740
	#無.
16741
	*/
16742
	public static function checkAuth(&$conf){
16743
 
16744
		#初始化要回傳的結果
16745
		$result=array();
16746
 
16747
		#取得當前執行的函數名稱
16748
		$result["function"]=__FUNCTION__;
16749
 
16750
		#涵式說明:
16751
		#判斷當前環境為web還是cmd
16752
		#回傳結果:
16753
		#$result,"web"或"cmd"
16754
		if(csInformation::getEnv()==="web"){
16755
 
16756
			#設置執行失敗
16757
			$result["status"]="false";
16758
 
16759
			#設置執行錯誤訊息
16760
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
16761
 
16762
			#回傳結果
16763
			return $result;
16764
 
16765
			}#if end
16766
 
16767
		#取得參數
16768
		$result["argu"]=$conf;
16769
 
16770
		#如果 $conf 不為陣列
16771
		if(gettype($conf)!="array"){
16772
 
16773
			#設置執行失敗
16774
			$result["status"]="false";
16775
 
16776
			#設置執行錯誤訊息
16777
			$result["error"][]="\$conf變數須為陣列形態";
16778
 
16779
			#如果傳入的參數為 null
16780
			if($conf==null){
16781
 
16782
				#設置執行錯誤訊息
16783
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
16784
 
16785
				}#if end
16786
 
16787
			#回傳結果
16788
			return $result;
16789
 
16790
			}#if end
16791
 
16792
		#檢查參數
16793
		#函式說明:
16794
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
16795
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
16796
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
16797
		#$result["function"],當前執行的函式名稱.
16798
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
16799
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
16800
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
16801
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
16802
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
16803
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
16804
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
16805
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
16806
		#必填寫的參數:
16807
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
16808
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
16809
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
16810
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn","func");
16811
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
16812
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array","string");
16813
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
16814
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
16815
		#可以省略的參數:
16816
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
16817
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
16818
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
16819
		#$conf["canNotBeEmpty"]=array();
16820
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
16821
		#$conf["canBeEmpty"]=array();
16822
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
16823
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
16824
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
16825
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId","falseAllowFuncPlus","publicAllowFuncPlus");
16826
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
16827
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","array","array");
16828
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
16829
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId,array(),array());
16830
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
16831
		#$conf["arrayCountEqualCheck"][]=array();
16832
		#參考資料來源:
16833
		#array_keys=>http://php.net/manual/en/function.array-keys.php
16834
		#建議:
16835
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
16836
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
16837
		unset($conf["variableCheck::checkArguments"]);
16838
 
16839
		#如果檢查參數失敗
16840
		if($checkArguments["status"]==="false"){
16841
 
16842
			#設置執行失敗
16843
			$result["status"]="false";
16844
 
16845
			#設置執行錯誤訊息
16846
			$result["error"]=$checkArguments;
16847
 
16848
			#回傳結果
16849
			return $result;
16850
 
16851
			}#if end
16852
 
16853
		#如果檢查參數不通過
16854
		if($checkArguments["passed"]==="false"){
16855
 
16856
			#設置執行失敗
16857
			$result["status"]="false";
16858
 
16859
			#設置執行錯誤訊息
16860
			$result["error"]=$checkArguments;
16861
 
16862
			#回傳結果
16863
			return $result;
16864
 
16865
			}#if end
16866
 
16867
		#取得收到的訊息
16868
		$receivedData=$conf["data"];
16869
 
16870
		#取得 server 的 socket
16871
		$serverSocket=$conf["serverSock"];
16872
 
16873
		#取得 client 的 socket
16874
		$clientSocket=$conf["clientSock"];
16875
 
16876
		#取得 client 的資訊
16877
		$clientInfo=$conf["clientInfo"];
16878
 
16879
		#取得 client 的索引
16880
		$clientIndex=$conf["clientIndex"];
16881
 
16882
		#取得 all clients 的資訊
16883
		$allConn=&$conf["allConn"];
16884
 
16885
		/* 檢查權限不用看收到的訊息
16886
 
16887
		#hex2bin
16888
		#函式說明:
16889
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
16890
		#回傳結果:
16891
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
16892
		#$result["function"],當前執行的函數名稱.
16893
		#$result["content"],加密後的結果.
16894
		#$result["error"],錯誤訊息陣列.
16895
		#$result["argu"],使用的參數.
16896
		#必填參數:
16897
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
16898
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
16899
		#$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".
16900
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
16901
		#可省略參數:
16902
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
16903
		#$conf["sha1Raw"]="false";
16904
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
16905
		#$conf["p_hash"]="";
16906
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
16907
		#$conf["keyForAes256"]="";
16908
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
16909
		#$conf["aes256Encode"]="";
16910
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
16911
		#$conf["qbpwcfDecode"]="false";
16912
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
16913
		#$conf["gpgDecrypt"]="false";
16914
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
16915
		#$conf["gpgId"]="";
16916
		#參考資料:
16917
		#sha1=>http://php.net/manual/en/function.sha1.php
16918
		#md5=>http://php.net/manual/en/function.md5.php
16919
		#password_hash=>http://php.net/manual/en/function.password-hash.php
16920
		#password_verify=>http://php.net/manual/en/function.password-verify.php
16921
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
16922
		#備註:
16923
		#無.
16924
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
16925
		unset($conf["authenticate::enCodeStr"]);
16926
 
16927
		#如果執行失敗
16928
		if($enCodeStr["status"]==="false"){
16929
 
16930
			#設置執行異常
16931
			$result["status"]="false";
16932
 
16933
			#設置執行錯誤
16934
			$result["error"]=$enCodeStr;
16935
 
16936
			#回傳結果
16937
			return $result;
16938
 
16939
			}#if end
16940
 
16941
		#取得hex2bin後的字串
16942
		$receivedData=$enCodeStr["content"];
16943
 
16944
		#gpg decrypt
16945
		#函式說明:
16946
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
16947
		#回傳結果:
16948
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
16949
		#$result["function"],當前執行的函數名稱.
16950
		#$result["content"],加密後的結果.
16951
		#$result["error"],錯誤訊息陣列.
16952
		#$result["argu"],使用的參數.
16953
		#必填參數:
16954
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
16955
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
16956
		#$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".
16957
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
16958
		#可省略參數:
16959
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
16960
		#$conf["sha1Raw"]="false";
16961
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
16962
		#$conf["p_hash"]="";
16963
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
16964
		#$conf["keyForAes256"]="";
16965
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
16966
		#$conf["aes256Encode"]="";
16967
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
16968
		#$conf["qbpwcfDecode"]="false";
16969
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
16970
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
16971
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
16972
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
16973
		#參考資料:
16974
		#sha1=>http://php.net/manual/en/function.sha1.php
16975
		#md5=>http://php.net/manual/en/function.md5.php
16976
		#password_hash=>http://php.net/manual/en/function.password-hash.php
16977
		#password_verify=>http://php.net/manual/en/function.password-verify.php
16978
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
16979
		#備註:
16980
		#無.
16981
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
16982
		unset($conf["authenticate::enCodeStr"]);
16983
 
16984
		#如果執行失敗
16985
		if($enCodeStr["status"]==="false"){
16986
 
16987
			#設置執行異常
16988
			$result["status"]="false";
16989
 
16990
			#設置執行錯誤
16991
			$result["error"]=$enCodeStr;
16992
 
16993
			#回傳結果
16994
			return $result;
16995
 
16996
			}#if end
16997
 
16998
		#取得解密後的字串
16999
		$receivedData=$enCodeStr["content"];
17000
 
17001
		#json_decode
17002
		$receivedData=json_decode($receivedData);
17003
 
17004
		*/
17005
 
17006
		#取得認證狀態
17007
		$authStatus=$conf["clientInfo"][$conf["clientIndex"]]["auth"];
17008
 
17009
		#判斷 authStatus
17010
		switch($authStatus){
17011
 
17012
			#如果未經過認證
17013
			case "false":
17014
 
17015
				#預設可以使用的功能只有"auth"跟"checkAuth"
17016
				$authFunc=array("auth","checkAuth");
17017
 
17018
				#如果有 $conf["falseAllowFuncPlus"]
17019
				if(count($conf["falseAllowFuncPlus"])>0){
17020
 
17021
					#合併 array
17022
					#函式說明:
17023
					#將多個一維陣列串聯起來,key從0開始排序.
17024
					#回傳的結果:
17025
					#$result["status"],"true"表執行正常,"false"代表執行不正常.
17026
					#$result["error"],錯誤訊息陣列.
17027
					#$result["function"],當前執行的函數.
17028
					#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17029
					#$result["content"],合併好的一維陣列.
17030
					#必填參數
17031
					#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
17032
					$conf["arrays::mergeArray"]["inputArray"]=array($authFunc,$conf["falseAllowFuncPlus"]);
17033
					#可省略參數:
17034
					#$conf["allowRepeat"],字串,預設為"true",允許重複的結果;若為"false"則不會出現重複的元素內容.
17035
					$conf["arrays::mergeArray"]["allowRepeat"]="false";
17036
					#$conf["looseDiff"],字串,預設為"false",代表要嚴謹判斷為有相異,例如陣列中元素的key順序不同(整數)就代表有相異;反之為"true",例如陣列中元素的key順序不同(非整數),但value有相同,則視為無相異.
17037
					$conf["arrays::mergeArray"]["looseDiff"]="true";
17038
					#參考資料:
17039
					#無.
17040
					#備註:
17041
					#無.
17042
					$mergeArray=arrays::mergeArray($conf["arrays::mergeArray"]);
17043
					unset($conf["arrays::mergeArray"]);
17044
 
17045
					#如果執行失敗
17046
					if($mergeArray["status"]==="false"){
17047
 
17048
						#設置執行異常
17049
						$result["status"]="false";
17050
 
17051
						#設置執行錯誤
17052
						$result["error"]=$mergeArray;
17053
 
17054
						#回傳結果
17055
						return $result;
17056
 
17057
						}#if end
17058
 
17059
					#取得合併好允許使用的清單
17060
					$authFunc=$mergeArray["content"];
17061
 
17062
					}#if end
17063
 
17064
				#如果沒有權限使用 
17065
				if(!in_array($conf["func"],$authFunc)){
17066
 
17067
					#設置執行異常
17068
					$result["status"]="false";
17069
 
17070
					#設置執行錯誤
17071
					$result["error"][]="no ".$conf["func"]." permission";
17072
 
17073
					#回傳結果
17074
					return $result;
17075
 
17076
					}#if end
17077
 
17078
				#結束 switch
17079
				break;
17080
 
17081
			#如果是"root"賬戶,代表系統管理者,擁有所有權限.
17082
			case "root":
17083
 
17084
				#預設可以使用的功能只有"*",代表所有功能都能用.
17085
				$authFunc=array("*");
17086
 
17087
				/*	允許使用所有函式
17088
 
17089
				#如果沒有權限使用 
17090
				if(!in_array($conf["func"],$authFunc)){
17091
 
17092
					#設置執行異常
17093
					$result["status"]="false";
17094
 
17095
					#設置執行錯誤
17096
					$result["error"][]="no ".$conf["func"]." permission";
17097
 
17098
					#回傳結果
17099
					return $result;
17100
 
17101
					}#if end
17102
 
17103
				*/
17104
 
17105
				#結束 switch
17106
				break;
17107
 
17108
			#如果是"public"賬戶,代表具備一般使用權限的公用使用者.
17109
			case "public":
17110
 
17111
				#預設可以使用的功能只有"*",代表所有功能都能用.
17112
				$authFunc=array("auth","checkAuth","basic");
17113
 
17114
				#如果有 publicAllowFuncPlus
17115
				if(count($conf["publicAllowFuncPlus"])>0){
17116
 
17117
					#合併 array
17118
					#函式說明:
17119
					#將多個一維陣列串聯起來,key從0開始排序.
17120
					#回傳的結果:
17121
					#$result["status"],"true"表執行正常,"false"代表執行不正常.
17122
					#$result["error"],錯誤訊息陣列.
17123
					#$result["function"],當前執行的函數.
17124
					#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17125
					#$result["content"],合併好的一維陣列.
17126
					#必填參數
17127
					#$conf["inputArray"],陣列,要合併的一維陣列變數,例如:=array($array1,$array2);
17128
					$conf["arrays::mergeArray"]["inputArray"]=array($authFunc,$conf["publicAllowFuncPlus"]);
17129
					#可省略參數:
17130
					#$conf["allowRepeat"],字串,預設為"true",允許重複的結果;若為"false"則不會出現重複的元素內容.
17131
					$conf["arrays::mergeArray"]["allowRepeat"]="false";
17132
					#$conf["looseDiff"],字串,預設為"false",代表要嚴謹判斷為有相異,例如陣列中元素的key順序不同(整數)就代表有相異;反之為"true",例如陣列中元素的key順序不同(非整數),但value有相同,則視為無相異.
17133
					$conf["arrays::mergeArray"]["looseDiff"]="true";
17134
					#參考資料:
17135
					#無.
17136
					#備註:
17137
					#無.
17138
					$mergeArray=arrays::mergeArray($conf["arrays::mergeArray"]);
17139
					unset($conf["arrays::mergeArray"]);
17140
 
17141
					#如果執行失敗
17142
					if($mergeArray["status"]==="false"){
17143
 
17144
						#設置執行異常
17145
						$result["status"]="false";
17146
 
17147
						#設置執行錯誤
17148
						$result["error"]=$mergeArray;
17149
 
17150
						#回傳結果
17151
						return $result;
17152
 
17153
						}#if end
17154
 
17155
					#取得合併好允許使用的清單
17156
					$authFunc=$mergeArray["content"];
17157
 
17158
					}#if end
17159
 
17160
				#如果沒有權限使用 
17161
				if(!in_array($conf["func"],$authFunc)){
17162
 
17163
					#設置執行異常
17164
					$result["status"]="false";
17165
 
17166
					#設置執行錯誤
17167
					$result["error"][]="no ".$conf["func"]." permission";
17168
 
17169
					#回傳結果
17170
					return $result;
17171
 
17172
					}#if end
17173
 
17174
				break;
17175
 
17176
			#其他結果
17177
			default:
17178
 
17179
				#依照指定的資料來源進行權限與可用功能的檢查
17180
				#...
17181
 
17182
				#設置執行異常
17183
				$result["status"]="false";
17184
 
17185
				#設置執行錯誤
17186
				$result["error"][]="not supported authStatus(".$authStatus.")";
17187
 
17188
				#回傳結果
17189
				return $result;
17190
 
17191
			}#switch end
17192
 
17193
			#設置執行正常
17194
			$result["status"]="true";
17195
 
17196
			#回傳結果
17197
			return $result;
17198
 
17199
		}#function checkAuth end
17200
 
17201
	/*
17202
	#函式說明:
17203
	#提供webSock::nativeSocketTcpIpServer用於接受"auth:"開頭的訊息進行認證使用者的功能.
17204
	#回傳結果:
17205
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
17206
	#$result["error"],執行不正常結束的錯訊息陣列.
17207
	#$result["argu"],陣列,使用的參數.
17208
	#必填參數:
17209
	#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
17210
	$conf["data"]="";
17211
	#$conf["serverSock"],resource,web socket server socket
17212
	$conf["serverSock"]=$resource;
17213
	#$conf["clientSock"],$resource,web socket client socket
17214
	$conf["clientSock"]=$resource;
17215
	#$conf["clientInfo"],陣列,web socket client info.
17216
	$conf["clientInfo"]=array();
17217
	#$conf["clientIndex"],整數.web socket client index.
17218
	$conf["clientIndex"];
17219
	#$conf["allConn"],陣列,all web socket client info.
17220
	$conf["allConn"]=array();
17221
	#可省略參數:
17222
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
17223
	#$conf["wsMode"]="true";
17224
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
17225
	#$conf["gpgId"]=gnupgId;
17226
	#參考資料:
17227
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
17228
	#備註:
17229
	#無.
17230
	*/
17231
	public static function auth(&$conf){
17232
 
17233
		#初始化要回傳的結果
17234
		$result=array();
17235
 
17236
		#取得當前執行的函數名稱
17237
		$result["function"]=__FUNCTION__;
17238
 
17239
		#涵式說明:
17240
		#判斷當前環境為web還是cmd
17241
		#回傳結果:
17242
		#$result,"web"或"cmd"
17243
		if(csInformation::getEnv()==="web"){
17244
 
17245
			#設置執行失敗
17246
			$result["status"]="false";
17247
 
17248
			#設置執行錯誤訊息
17249
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
17250
 
17251
			#回傳結果
17252
			return $result;
17253
 
17254
			}#if end
17255
 
17256
		#取得參數
17257
		$result["argu"]=$conf;
17258
 
17259
		#如果 $conf 不為陣列
17260
		if(gettype($conf)!="array"){
17261
 
17262
			#設置執行失敗
17263
			$result["status"]="false";
17264
 
17265
			#設置執行錯誤訊息
17266
			$result["error"][]="\$conf變數須為陣列形態";
17267
 
17268
			#如果傳入的參數為 null
17269
			if($conf==null){
17270
 
17271
				#設置執行錯誤訊息
17272
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
17273
 
17274
				}#if end
17275
 
17276
			#回傳結果
17277
			return $result;
17278
 
17279
			}#if end
17280
 
17281
		#檢查參數
17282
		#函式說明:
17283
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
17284
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17285
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
17286
		#$result["function"],當前執行的函式名稱.
17287
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
17288
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
17289
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
17290
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
17291
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
17292
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17293
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
17294
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
17295
		#必填寫的參數:
17296
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
17297
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
17298
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
17299
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
17300
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
17301
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
17302
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
17303
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
17304
		#可以省略的參數:
17305
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
17306
		#$conf["canBeEmptyString"]="false";
17307
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
17308
		#$conf["canNotBeEmpty"]=array();
17309
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
17310
		#$conf["canBeEmpty"]=array();
17311
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
17312
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
17313
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
17314
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
17315
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
17316
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
17317
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
17318
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
17319
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
17320
		#$conf["arrayCountEqualCheck"][]=array();
17321
		#參考資料來源:
17322
		#array_keys=>http://php.net/manual/en/function.array-keys.php
17323
		#建議:
17324
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
17325
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
17326
		unset($conf["variableCheck::checkArguments"]);
17327
 
17328
		#如果檢查參數失敗
17329
		if($checkArguments["status"]==="false"){
17330
 
17331
			#設置執行失敗
17332
			$result["status"]="false";
17333
 
17334
			#設置執行錯誤訊息
17335
			$result["error"]=$checkArguments;
17336
 
17337
			#回傳結果
17338
			return $result;
17339
 
17340
			}#if end
17341
 
17342
		#如果檢查參數不通過
17343
		if($checkArguments["passed"]==="false"){
17344
 
17345
			#設置執行失敗
17346
			$result["status"]="false";
17347
 
17348
			#設置執行錯誤訊息
17349
			$result["error"]=$checkArguments;
17350
 
17351
			#回傳結果
17352
			return $result;
17353
 
17354
			}#if end
17355
 
17356
		#取得收到的訊息
17357
		$receivedData=$conf["data"];
17358
 
17359
		#取得 server 的 socket
17360
		$serverSocket=$conf["serverSock"];
17361
 
17362
		#取得 client 的 socket
17363
		$clientSocket=$conf["clientSock"];
17364
 
17365
		#取得 client 的資訊
17366
		$clientInfo=$conf["clientInfo"];
17367
 
17368
		#取得 client 的索引
17369
		$clientIndex=$conf["clientIndex"];
17370
 
17371
		#取得認證狀態
17372
		$authStatus=&$conf["clientInfo"][$conf["clientIndex"]]["auth"];
17373
 
17374
		#取得 all clients 的資訊
17375
		$allConn=&$conf["allConn"];
17376
 
17377
		#hex2bin
17378
		#函式說明:
17379
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
17380
		#回傳結果:
17381
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17382
		#$result["function"],當前執行的函數名稱.
17383
		#$result["content"],加密後的結果.
17384
		#$result["error"],錯誤訊息陣列.
17385
		#$result["argu"],使用的參數.
17386
		#必填參數:
17387
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
17388
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
17389
		#$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".
17390
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
17391
		#可省略參數:
17392
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
17393
		#$conf["sha1Raw"]="false";
17394
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
17395
		#$conf["p_hash"]="";
17396
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
17397
		#$conf["keyForAes256"]="";
17398
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
17399
		#$conf["aes256Encode"]="";
17400
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
17401
		#$conf["qbpwcfDecode"]="false";
17402
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
17403
		#$conf["gpgDecrypt"]="false";
17404
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
17405
		#$conf["gpgId"]="";
17406
		#參考資料:
17407
		#sha1=>http://php.net/manual/en/function.sha1.php
17408
		#md5=>http://php.net/manual/en/function.md5.php
17409
		#password_hash=>http://php.net/manual/en/function.password-hash.php
17410
		#password_verify=>http://php.net/manual/en/function.password-verify.php
17411
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
17412
		#備註:
17413
		#無.
17414
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
17415
		unset($conf["authenticate::enCodeStr"]);
17416
 
17417
		#如果執行失敗
17418
		if($enCodeStr["status"]==="false"){
17419
 
17420
			#設置執行異常
17421
			$result["status"]="false";
17422
 
17423
			#設置執行錯誤
17424
			$result["error"]=$enCodeStr;
17425
 
17426
			#回傳結果
17427
			return $result;
17428
 
17429
			}#if end
17430
 
17431
		#取得hex2bin後的字串
17432
		$receivedData=$enCodeStr["content"];
17433
 
17434
		#gpg decrypt
17435
		#函式說明:
17436
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
17437
		#回傳結果:
17438
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17439
		#$result["function"],當前執行的函數名稱.
17440
		#$result["content"],加密後的結果.
17441
		#$result["error"],錯誤訊息陣列.
17442
		#$result["argu"],使用的參數.
17443
		#必填參數:
17444
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
17445
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
17446
		#$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".
17447
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
17448
		#可省略參數:
17449
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
17450
		#$conf["sha1Raw"]="false";
17451
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
17452
		#$conf["p_hash"]="";
17453
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
17454
		#$conf["keyForAes256"]="";
17455
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
17456
		#$conf["aes256Encode"]="";
17457
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
17458
		#$conf["qbpwcfDecode"]="false";
17459
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
17460
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
17461
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
17462
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
17463
		#參考資料:
17464
		#sha1=>http://php.net/manual/en/function.sha1.php
17465
		#md5=>http://php.net/manual/en/function.md5.php
17466
		#password_hash=>http://php.net/manual/en/function.password-hash.php
17467
		#password_verify=>http://php.net/manual/en/function.password-verify.php
17468
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
17469
		#備註:
17470
		#無.
17471
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
17472
		unset($conf["authenticate::enCodeStr"]);
17473
 
17474
		#如果執行失敗
17475
		if($enCodeStr["status"]==="false"){
17476
 
17477
			#設置執行異常
17478
			$result["status"]="false";
17479
 
17480
			#設置執行錯誤
17481
			$result["error"]=$enCodeStr;
17482
 
17483
			#回傳結果
17484
			return $result;
17485
 
17486
			}#if end
17487
 
17488
		#取得解密後的字串
17489
		$receivedData=$enCodeStr["content"];
17490
 
17491
		#json_decode
17492
		$receivedData=json_decode($receivedData);
17493
 
17494
		#如果decode後的內容不為物件
17495
		if(gettype($receivedData)!=="Object"){
17496
 
17497
			#設置不適用
17498
			$result["status"]="continue";
17499
 
17500
			#回傳結果
17501
			return $result;
17502
 
17503
			}#if end
17504
 
17505
		#檢查物件是否符合格式
17506
		#函式說明:
17507
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
17508
		#回傳結果:
17509
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17510
		#$result["error"],執行不正常結束的錯訊息陣列.
17511
		#$result["simpleError"],簡單表示的錯誤訊息.
17512
		#$result["function"],當前執行的函式名稱.
17513
		#$result["argu"],設置給予的參數.
17514
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
17515
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
17516
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
17517
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
17518
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
17519
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
17520
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
17521
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
17522
		#必填參數:
17523
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
17524
		$conf["variableCheck::checkArguments"]["varInput"]=&$receivedData;
17525
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
17526
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
17527
		#可省略參數:
17528
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
17529
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("user","type","secrect");
17530
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
17531
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string");
17532
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
17533
		#$conf["canBeEmptyString"]="false";
17534
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
17535
		#$conf["canNotBeEmpty"]=array();
17536
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
17537
		#$conf["canBeEmpty"]=array();
17538
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
17539
		#$conf["skipableVariableCanNotBeEmpty"]=array();
17540
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
17541
		#$conf["skipableVariableName"]=array();
17542
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
17543
		#$conf["skipableVariableType"]=array();
17544
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
17545
		#$conf["skipableVarDefaultValue"]=array("");
17546
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
17547
		#$conf["disallowAllSkipableVarIsEmpty"]="";
17548
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
17549
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
17550
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
17551
		#$conf["disallowAllSkipableVarNotExist"]="";
17552
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
17553
		#$conf["arrayCountEqualCheck"][]=array();
17554
		#參考資料:
17555
		#array_keys=>http://php.net/manual/en/function.array-keys.php
17556
		#備註:
17557
		#無.
17558
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
17559
		unset($conf["variableCheck::checkArguments"]);
17560
 
17561
		#如果執行異常
17562
		if($checkArguments["status"]==="false"){
17563
 
17564
			#設置異常
17565
			$result["status"]="false";
17566
 
17567
			#設置錯誤訊息
17568
			$result["error"]=$checkArguments;
17569
 
17570
			#回傳結果
17571
			return $result;
17572
 
17573
			}#if end
17574
 
17575
		#如果參數不合法
17576
		if($checkArguments["passed"]==="false"){
17577
 
17578
			#設置不適用
17579
			$result["status"]="continue";
17580
 
17581
			#回傳結果
17582
			return $result;
17583
 
17584
			}#if end
17585
 
17586
		#取得使用者名稱
17587
		$user=$receivedData->user;
17588
 
17589
		#取得密碼或金鑰內容
17590
		$secrect=$receivedData->secrect;
17591
 
17592
		#依照驗證方式
17593
		switch($receivedData->type){
17594
 
17595
			#若是密碼認證
17596
			case "password":
17597
 
17598
				#測試 $user 與 password 的組合是否能夠認證.
17599
				#函式說明:
17600
				#驗證Linux使用者的密碼是否正確.
17601
				#回傳結果:
17602
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17603
				#$result["function"],當前執行的函數名稱.
17604
				#$result["error"],錯誤訊息陣列.
17605
				#$result["warninig"],警告訊息陣列.
17606
				#$result["valid"],是否為存在的使用者且密碼正確.
17607
				#必填參數:
17608
				#$conf["username"],字串,要驗證的使用者名稱.
17609
				$conf["authenticate::validUser"]["username"]=$user;
17610
				#$conf["password"],字串,用於驗證使用者的密碼.
17611
				$conf["authenticate::validUser"]["password"]=$secrect;
17612
				#$conf["fileArgu"],字串,變數__FILE__的內容.
17613
				$conf["authenticate::validUser"]["fileArgu"]=__FILE__;
17614
				#可省略參數:
17615
				#無.
17616
				#參考資料:
17617
				#無.
17618
				#備註:
17619
				#僅能在命令列環境下運行.
17620
				$validUser=authenticate::validUser($conf["authenticate::validUser"]);
17621
				unset($conf["authenticate::validUser"]);
17622
 
17623
				#如果執行異常
17624
				if($validUser["status"]==="false"){
17625
 
17626
					#設置異常
17627
					$result["status"]="false";
17628
 
17629
					#設置錯誤訊息
17630
					$result["error"]=$validUser;
17631
 
17632
					#回傳結果
17633
					return $result;
17634
 
17635
					}#if end
17636
 
17637
				#如果認證失敗
17638
				if($validUser["valid"]==="false"){
17639
 
17640
					#記錄該 client 認證失敗的事件
17641
					$allConn[$clientIndex]["authFailed"][]=array("time"=>time(),"user"=>$user);
17642
 
17643
					#針對每次認證失敗的記錄
17644
					for($i=0;$i<count($allConn[$clientIndex]["authFailed"]);$i++){
17645
 
17646
						#如果有下一個事件
17647
						if(isset($allConn[$clientIndex]["authFailed"][$i+1])){
17648
 
17649
							#如果本次跟下次事件的時間間隔小於60秒
17650
							if($allConn[$clientIndex]["authFailed"][$i+1]["time"] - $allConn[$clientIndex]["authFailed"][$i]["time"] > 60){
17651
 
17652
								#移除本次記錄
17653
								array_shift($allConn[$clientIndex]["authFailed"]);
17654
 
17655
								#新記錄的索引減少了1,因此更新$i
17656
								$i--;
17657
 
17658
								}#if end
17659
 
17660
							}#if end
17661
 
17662
						}#foreach end
17663
 
17664
					#如果總事件次數大於3
17665
					if(count($allConn[$clientIndex]["authFailed"])>3){
17666
 
17667
						#設置異常
17668
						$result["status"]="false";
17669
 
17670
						#設置錯誤訊息
17671
						$result["error"]=$allConn[$clientIndex]["authFailed"];
17672
 
17673
						#回傳結果
17674
						return $result;
17675
 
17676
						}#if end
17677
 
17678
					#設置正常
17679
					$result["status"]="true";
17680
 
17681
					#回傳結果
17682
					return $result;
17683
 
17684
					}#if end
17685
 
17686
				#執行到這邊代表使用者認證通過
17687
 
17688
				#依照 user 取得其所屬 group
17689
				#函式說明:
17690
				#id指令來取得目標賬號的群組資訊
17691
				#回傳結果:
17692
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17693
				#$reuslt["error"],執行不正常結束的錯訊息陣列.
17694
				#$result["function"],當前執行的函式名稱.
17695
				#$result["content"],呼叫完WebService所得回傳結果.
17696
				#$result["content"]["groupId"],群組的id.
17697
				#$result["content"]["belongGroupName"],陣列,隸屬的群組名稱陣列.
17698
				#$result["content"]["belongGroupId"],陣列,隸屬的群組id.
17699
				#必填參數:
17700
				#$conf["user"],字串,要取得群組資訊的目標使用者名稱.
17701
				$conf["authenticate::getUserGroup"]["user"]=$user;
17702
				#可省略參數:
17703
				#無.
17704
				#參考資料:
17705
				#無.
17706
				#備註:
17707
				#無.
17708
				$getUserGroup=authenticate::getUserGroup($conf["authenticate::getUserGroup"]);
17709
				unset($conf["authenticate::getUserGroup"]);
17710
 
17711
				#如果執行異常
17712
				if($getUserGroup["status"]==="false"){
17713
 
17714
					#設置異常
17715
					$result["status"]="false";
17716
 
17717
					#設置錯誤訊息
17718
					$result["error"]=$getUserGroup;
17719
 
17720
					#回傳結果
17721
					return $result;
17722
 
17723
					}#if end
17724
 
17725
				#設置預設的權限為 "false"
17726
				$authStatus="false";
17727
 
17728
				#針對每個取得的群組名稱
17729
				foreach($getUserGroup["content"]["belongGroupName"] as $groupName){
17730
 
17731
					#如果是 root
17732
					if($groupName==="root"){
17733
 
17734
						#設置得到的權限
17735
						$authStatus=$groupName;
17736
 
17737
						#結束 foreach
17738
						break;
17739
 
17740
						}#if end
17741
 
17742
					#反之如果是公開的使用者
17743
					else if($groupName==="public"){
17744
 
17745
						#設置得到的權限
17746
						$authStatus=$groupName;
17747
 
17748
						}#if end
17749
 
17750
					#其他群組名稱
17751
					else{
17752
 
17753
						#跳過
17754
						continue;
17755
 
17756
						}#else end
17757
 
17758
					}#foreach end
17759
 
17760
				#設置正常
17761
				$result["status"]="true";
17762
 
17763
				#回傳結果
17764
				return $result;
17765
 
17766
				#跳出 switch
17767
				break;
17768
 
17769
			#若是金鑰認證
17770
			case "key":
17771
 
17772
				#測試 $user 與 key 的組合是否能夠認證.
17773
				#函式說明:
17774
				#驗證Linux使用者的密碼或ssh private key是否正確.
17775
				#回傳結果:
17776
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
17777
				#$result["function"],當前執行的函數名稱.
17778
				#$result["error"],錯誤訊息陣列.
17779
				#$result["warninig"],警告訊息陣列.
17780
				#$result["valid"],是否為存在的使用者且密碼正確.
17781
				#必填參數:
17782
				#$conf["username"],字串,要驗證的使用者名稱.
17783
				$conf["authenticate::validUser"]["username"]=$user;
17784
				#$conf["password"],字串,用於驗證使用者的密碼.
17785
				$conf["authenticate::validUser"]["password"]=$secrect;
17786
				#$conf["fileArgu"],字串,變數__FILE__的內容.
17787
				$conf["authenticate::validUser"]["fileArgu"]=__FILE__;
17788
				#可省略參數:
17789
				#$conf["sshPrivateKey"],字串,"true"代表password為ssh private key的內容;反之預設為密碼,設置為"false".
17790
				$conf["authenticate::validUser"]["sshPrivateKey"]="true";
17791
				#參考資料:
17792
				#無.
17793
				#備註:
17794
				#僅能在命令列環境下運.
17795
				#目前僅支援驗證執行php端的使用者.
17796
				$validUser=authenticate::validUser($conf["authenticate::validUser"]);
17797
				unset($conf["authenticate::validUser"]);
17798
 
17799
				#如果執行異常
17800
				if($validUser["status"]==="false"){
17801
 
17802
					#設置異常
17803
					$result["status"]="false";
17804
 
17805
					#設置錯誤訊息
17806
					$result["error"]=$validUser;
17807
 
17808
					#回傳結果
17809
					return $result;
17810
 
17811
					}#if end
17812
 
17813
				#如果認證失敗
17814
				if($validUser["valid"]==="false"){
17815
 
17816
					#記錄該 client 認證失敗的事件
17817
					$allConn[$clientIndex]["authFailed"][]=array("time"=>time(),"user"=>$user);
17818
 
17819
					#針對每次認證失敗的記錄
17820
					for($i=0;$i<count($allConn[$clientIndex]["authFailed"]);$i++){
17821
 
17822
						#如果有下一個事件
17823
						if(isset($allConn[$clientIndex]["authFailed"][$i+1])){
17824
 
17825
							#如果本次跟下次事件的時間間隔小於60秒
17826
							if($allConn[$clientIndex]["authFailed"][$i+1]["time"] - $allConn[$clientIndex]["authFailed"][$i]["time"] > 60){
17827
 
17828
								#移除本次記錄
17829
								array_shift($allConn[$clientIndex]["authFailed"]);
17830
 
17831
								#新記錄的索引減少了1,因此更新$i
17832
								$i--;
17833
 
17834
								}#if end
17835
 
17836
							}#if end
17837
 
17838
						}#foreach end
17839
 
17840
					#如果總事件次數大於3
17841
					if(count($allConn[$clientIndex]["authFailed"])>3){
17842
 
17843
						#設置異常
17844
						$result["status"]="false";
17845
 
17846
						#設置錯誤訊息
17847
						$result["error"]=$allConn[$clientIndex]["authFailed"];
17848
 
17849
						#回傳結果
17850
						return $result;
17851
 
17852
						}#if end
17853
 
17854
					#設置正常
17855
					$result["status"]="true";
17856
 
17857
					#回傳結果
17858
					return $result;
17859
 
17860
					}#if end
17861
 
17862
				#執行到這邊代表使用者認證通過
17863
 
17864
				#依照 user 取得其所屬 group
17865
				#函式說明:
17866
				#id指令來取得目標賬號的群組資訊
17867
				#回傳結果:
17868
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
17869
				#$reuslt["error"],執行不正常結束的錯訊息陣列.
17870
				#$result["function"],當前執行的函式名稱.
17871
				#$result["content"],呼叫完WebService所得回傳結果.
17872
				#$result["content"]["groupId"],群組的id.
17873
				#$result["content"]["belongGroupName"],陣列,隸屬的群組名稱陣列.
17874
				#$result["content"]["belongGroupId"],陣列,隸屬的群組id.
17875
				#必填參數:
17876
				#$conf["user"],字串,要取得群組資訊的目標使用者名稱.
17877
				$conf["authenticate::getUserGroup"]["user"]=$user;
17878
				#可省略參數:
17879
				#無.
17880
				#參考資料:
17881
				#無.
17882
				#備註:
17883
				#無.
17884
				$getUserGroup=authenticate::getUserGroup($conf["authenticate::getUserGroup"]);
17885
				unset($conf["authenticate::getUserGroup"]);
17886
 
17887
				#如果執行異常
17888
				if($getUserGroup["status"]==="false"){
17889
 
17890
					#設置異常
17891
					$result["status"]="false";
17892
 
17893
					#設置錯誤訊息
17894
					$result["error"]=$getUserGroup;
17895
 
17896
					#回傳結果
17897
					return $result;
17898
 
17899
					}#if end
17900
 
17901
				#設置預設的權限為 "false"
17902
				$authStatus="false";
17903
 
17904
				#針對每個取得的群組名稱
17905
				foreach($getUserGroup["content"]["belongGroupName"] as $groupName){
17906
 
17907
					#如果是 root
17908
					if($groupName==="root"){
17909
 
17910
						#設置得到的權限
17911
						$authStatus=$groupName;
17912
 
17913
						#結束 foreach
17914
						break;
17915
 
17916
						}#if end
17917
 
17918
					#反之如果是公開的使用者
17919
					else if($groupName==="public"){
17920
 
17921
						#設置得到的權限
17922
						$authStatus=$groupName;
17923
 
17924
						}#if end
17925
 
17926
					#其他群組名稱
17927
					else{
17928
 
17929
						#跳過
17930
						continue;
17931
 
17932
						}#else end
17933
 
17934
					}#foreach end
17935
 
17936
				#設置正常
17937
				$result["status"]="true";
17938
 
17939
				#回傳結果
17940
				return $result;
17941
 
17942
				#跳出 switch
17943
				break;
17944
 
17945
			#其他類型
17946
			default:
17947
 
17948
				#設置不適用
17949
				$result["status"]="continue";
17950
 
17951
				#回傳結果
17952
				return $result;
17953
 
17954
			}#switch end
17955
 
17956
		#執行到這邊代表異常
17957
 
17958
		#設置異常
17959
		$result["status"]="false";
17960
 
17961
		#回傳結果
17962
		return $result;
17963
 
17964
		}#function auth end
17965
 
17966
	/*
17967
	#函式說明:
17968
	#提供webSock::nativeSocketTcpIpServer使用基本功能(basic).
17969
	#回傳結果:
17970
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
17971
	#$result["error"],執行不正常結束的錯訊息陣列.
17972
	#$result["argu"],陣列,使用的參數.
17973
	#必填參數:
17974
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料.
17975
	$conf["data"]="";
17976
	#$conf["serverSock"],resource,web socket server socket
17977
	$conf["serverSock"]=$resource;
17978
	#$conf["clientSock"],$resource,web socket client socket
17979
	$conf["clientSock"]=$resource;
17980
	#$conf["clientInfo"],陣列,web socket client info.
17981
	$conf["clientInfo"]=array();
17982
	#$conf["clientIndex"],整數.web socket client index.
17983
	$conf["clientIndex"];
17984
	#$conf["allConn"],陣列,all web socket client info.
17985
	$conf["allConn"]=array();
17986
	#可省略參數:
17987
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
17988
	#$conf["wsMode"]="true";
17989
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
17990
	#$conf["gpgId"]=gnupgId;
17991
	#參考資料:
17992
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
17993
	#備註:
17994
	#收到用戶的"id?"訊息,會回傳用戶的id.
17995
	#收到用戶的"ids?"訊息,會回傳非自己的所有用戶id.
17996
	#收到用戶的"talkTo?"訊息,會回傳目前在跟誰談話.
17997
	#收到用戶的"talkTo:client-id"訊息,會建立與id對應的用戶對話,此後傳遞的訊息均會給對方.
17998
	#結束連線的訊息"quit".
17999
	*/
18000
	public static function basic(&$conf){
18001
 
18002
		#初始化要回傳的結果
18003
		$result=array();
18004
 
18005
		#取得當前執行的函數名稱
18006
		$result["function"]=__FUNCTION__;
18007
 
18008
		#涵式說明:
18009
		#判斷當前環境為web還是cmd
18010
		#回傳結果:
18011
		#$result,"web"或"cmd"
18012
		if(csInformation::getEnv()==="web"){
18013
 
18014
			#設置執行失敗
18015
			$result["status"]="false";
18016
 
18017
			#設置執行錯誤訊息
18018
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
18019
 
18020
			#回傳結果
18021
			return $result;
18022
 
18023
			}#if end
18024
 
18025
		#取得參數
18026
		$result["argu"]=$conf;
18027
 
18028
		#如果 $conf 不為陣列
18029
		if(gettype($conf)!="array"){
18030
 
18031
			#設置執行失敗
18032
			$result["status"]="false";
18033
 
18034
			#設置執行錯誤訊息
18035
			$result["error"][]="\$conf變數須為陣列形態";
18036
 
18037
			#如果傳入的參數為 null
18038
			if($conf==null){
18039
 
18040
				#設置執行錯誤訊息
18041
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
18042
 
18043
				}#if end
18044
 
18045
			#回傳結果
18046
			return $result;
18047
 
18048
			}#if end
18049
 
18050
		#檢查參數
18051
		#函式說明:
18052
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
18053
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18054
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
18055
		#$result["function"],當前執行的函式名稱.
18056
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
18057
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
18058
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
18059
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
18060
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
18061
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
18062
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
18063
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
18064
		#必填寫的參數:
18065
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
18066
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
18067
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
18068
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
18069
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
18070
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
18071
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
18072
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
18073
		#可以省略的參數:
18074
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
18075
		#$conf["canBeEmptyString"]="false";
18076
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
18077
		#$conf["canNotBeEmpty"]=array();
18078
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
18079
		#$conf["canBeEmpty"]=array();
18080
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
18081
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
18082
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
18083
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
18084
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
18085
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
18086
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
18087
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
18088
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
18089
		#$conf["arrayCountEqualCheck"][]=array();
18090
		#參考資料來源:
18091
		#array_keys=>http://php.net/manual/en/function.array-keys.php
18092
		#建議:
18093
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
18094
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
18095
		unset($conf["variableCheck::checkArguments"]);
18096
 
18097
		#如果檢查參數失敗
18098
		if($checkArguments["status"]==="false"){
18099
 
18100
			#設置執行失敗
18101
			$result["status"]="false";
18102
 
18103
			#設置執行錯誤訊息
18104
			$result["error"]=$checkArguments;
18105
 
18106
			#回傳結果
18107
			return $result;
18108
 
18109
			}#if end
18110
 
18111
		#如果檢查參數不通過
18112
		if($checkArguments["passed"]==="false"){
18113
 
18114
			#設置執行失敗
18115
			$result["status"]="false";
18116
 
18117
			#設置執行錯誤訊息
18118
			$result["error"]=$checkArguments;
18119
 
18120
			#回傳結果
18121
			return $result;
18122
 
18123
			}#if end
18124
 
18125
		#取得收到的訊息
18126
		$receivedData=$conf["data"];
18127
 
18128
		#取得 server 的 socket
18129
		$serverSocket=$conf["serverSock"];
18130
 
18131
		#取得 client 的 socket
18132
		$clientSocket=$conf["clientSock"];
18133
 
18134
		#取得 client 的資訊
18135
		$clientInfo=$conf["clientInfo"];
18136
 
18137
		#取得 client 的索引
18138
		$clientIndex=$conf["clientIndex"];
18139
 
18140
		#取得 all clients 的資訊
18141
		$allConn=&$conf["allConn"];
18142
 
18143
		#hex2bin
18144
		#函式說明:
18145
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
18146
		#回傳結果:
18147
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
18148
		#$result["function"],當前執行的函數名稱.
18149
		#$result["content"],加密後的結果.
18150
		#$result["error"],錯誤訊息陣列.
18151
		#$result["argu"],使用的參數.
18152
		#必填參數:
18153
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
18154
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
18155
		#$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".
18156
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
18157
		#可省略參數:
18158
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
18159
		#$conf["sha1Raw"]="false";
18160
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
18161
		#$conf["p_hash"]="";
18162
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
18163
		#$conf["keyForAes256"]="";
18164
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
18165
		#$conf["aes256Encode"]="";
18166
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
18167
		#$conf["qbpwcfDecode"]="false";
18168
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
18169
		#$conf["gpgDecrypt"]="false";
18170
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
18171
		#$conf["gpgId"]="";
18172
		#參考資料:
18173
		#sha1=>http://php.net/manual/en/function.sha1.php
18174
		#md5=>http://php.net/manual/en/function.md5.php
18175
		#password_hash=>http://php.net/manual/en/function.password-hash.php
18176
		#password_verify=>http://php.net/manual/en/function.password-verify.php
18177
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
18178
		#備註:
18179
		#無.
18180
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
18181
		unset($conf["authenticate::enCodeStr"]);
18182
 
18183
		#如果執行失敗
18184
		if($enCodeStr["status"]==="false"){
18185
 
18186
			#設置執行異常
18187
			$result["status"]="false";
18188
 
18189
			#設置執行錯誤
18190
			$result["error"]=$enCodeStr;
18191
 
18192
			#回傳結果
18193
			return $result;
18194
 
18195
			}#if end
18196
 
18197
		#取得hex2bin後的字串
18198
		$receivedData=$enCodeStr["content"];
18199
 
18200
		#gpg decrypt
18201
		#函式說明:
18202
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
18203
		#回傳結果:
18204
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
18205
		#$result["function"],當前執行的函數名稱.
18206
		#$result["content"],加密後的結果.
18207
		#$result["error"],錯誤訊息陣列.
18208
		#$result["argu"],使用的參數.
18209
		#必填參數:
18210
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
18211
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
18212
		#$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".
18213
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
18214
		#可省略參數:
18215
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
18216
		#$conf["sha1Raw"]="false";
18217
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
18218
		#$conf["p_hash"]="";
18219
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
18220
		#$conf["keyForAes256"]="";
18221
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
18222
		#$conf["aes256Encode"]="";
18223
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
18224
		#$conf["qbpwcfDecode"]="false";
18225
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
18226
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
18227
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
18228
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
18229
		#參考資料:
18230
		#sha1=>http://php.net/manual/en/function.sha1.php
18231
		#md5=>http://php.net/manual/en/function.md5.php
18232
		#password_hash=>http://php.net/manual/en/function.password-hash.php
18233
		#password_verify=>http://php.net/manual/en/function.password-verify.php
18234
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
18235
		#備註:
18236
		#無.
18237
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
18238
		unset($conf["authenticate::enCodeStr"]);
18239
 
18240
		#如果執行失敗
18241
		if($enCodeStr["status"]==="false"){
18242
 
18243
			#設置執行異常
18244
			$result["status"]="false";
18245
 
18246
			#設置執行錯誤
18247
			$result["error"]=$enCodeStr;
18248
 
18249
			#回傳結果
18250
			return $result;
18251
 
18252
			}#if end
18253
 
18254
		#取得解密後的字串
18255
		$receivedData=$enCodeStr["content"];
18256
 
18257
		#json_decode
18258
		$receivedData=json_decode($receivedData);
18259
 
18260
		#如果收到的是 id?
18261
		if($receivedData==="id?"){
18262
 
18263
			#如果尚未認證
18264
			if($connections[$conIndex]["auth"]==="false"){
18265
 
18266
				#設置要回傳的訊息
18267
				$talkback="permission denied";
18268
 
18269
				}#if end
18270
 
18271
			else{
18272
 
18273
				#設置要回傳的訊息
18274
				$talkback=$connections[$conIndex]["id"];
18275
 
18276
				}#else end
18277
 
18278
			#debug
18279
			#var_dump(__LINE__,$talkback);
18280
 
18281
			#json encode 要回傳的訊息
18282
			$talkback=json_encode($talkback);
18283
 
18284
			#debug
18285
			#var_dump(__LINE__,$talkback);
18286
 
18287
			#如果是 ws 模式
18288
			if($conf["wsMode"]==="true"){
18289
 
18290
				#如果已經 handshake 過
18291
				if($connections[$conIndex]["handshaked"]==="true"){
18292
 
18293
					#如果要 unmask	
18294
					if($connections[$conIndex]["unmask"]==="true"){
18295
 
18296
						#函式說明:
18297
						#加密 handshake 後要傳送的訊息 
18298
						#回傳結果:
18299
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18300
						#$result["error"],執行不正常結束的錯訊息陣列.
18301
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18302
						#$result["argu"],陣列,使用的參數.
18303
						#必填參數:
18304
						#$conf["text"],字串,要加密的訊息.
18305
						$conf["webSock::encode"]["text"]=$talkback; 
18306
						#可省略參數:
18307
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18308
						#$conf["payloadIsBin"]="false";
18309
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18310
						#$conf["ping"]="false";
18311
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18312
						#$conf["pong"]="false";
18313
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18314
						#$conf["frames"]=array();
18315
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18316
						#$conf["mask"]="false";
18317
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18318
						#$conf["debug"]="false";
18319
						#參考資料:
18320
						#無.
18321
						#備註:
18322
						#目前$conf["text"]長度超過125會出錯.
18323
						$talkback=webSock::encode($conf["webSock::encode"]);
18324
						unset($conf["webSock::encode"]);
18325
 
18326
						#如果執行失敗
18327
						if($talkback["status"]==="false"){
18328
 
18329
							#印出結果
18330
							var_dump($talkback);
18331
 
18332
							#結束執行
18333
							exit;
18334
 
18335
							}#if end
18336
 
18337
						#debug
18338
						#var_dump(__LINE__,$talkback);
18339
 
18340
						}#if end
18341
 
18342
					}#if end
18343
 
18344
				}#if end
18345
 
18346
			#反之不為 web socket 訊息
18347
			else{
18348
 
18349
				#儲存成只有一個訊息
18350
				$talkback["content"][]=$talkback;
18351
 
18352
				}#else
18353
 
18354
			#針對每個訊息的分段
18355
			foreach($talkback["content"] as $msg){
18356
 
18357
				#debug
18358
				var_dump(__LINE__,$msg);
18359
 
18360
				#回傳訊息
18361
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18362
 
18363
				#debug
18364
				var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18365
 
18366
				}#foreach end
18367
 
18368
			#設置執行正常
18369
			$result["status"]="true";
18370
 
18371
			#回傳結果
18372
			return $result;
18373
 
18374
			}#if end
18375
 
18376
		#反之如果收到的是 "quit"
18377
		else if($receivedData==="quit"){
18378
 
18379
			#設置要回傳的訊息
18380
			$talkback="結束與 server 的連線";
18381
 
18382
			#json encode 要回傳的訊息
18383
			$talkback=json_encode($talkback).PHP_EOL;
18384
 
18385
			#如果是 ws 模式
18386
			if($conf["wsMode"]==="true"){
18387
 
18388
				#如果已經 handshake 過
18389
				if($connections[$conIndex]["handshaked"]==="true"){
18390
 
18391
					#如果要 unmask	
18392
					if($connections[$conIndex]["unmask"]==="true"){
18393
 
18394
						#函式說明:
18395
						#加密 handshake 後要傳送的訊息 
18396
						#回傳結果:
18397
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18398
						#$result["error"],執行不正常結束的錯訊息陣列.
18399
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18400
						#$result["argu"],陣列,使用的參數.
18401
						#必填參數:
18402
						#$conf["text"],字串,要加密的訊息.
18403
						$conf["webSock::encode"]["text"]=$talkback; 
18404
						#可省略參數:
18405
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18406
						#$conf["payloadIsBin"]="false";
18407
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18408
						#$conf["ping"]="false";
18409
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18410
						#$conf["pong"]="false";
18411
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18412
						#$conf["frames"]=array();
18413
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18414
						#$conf["mask"]="false";
18415
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18416
						#$conf["debug"]="false";
18417
						#參考資料:
18418
						#無.
18419
						#備註:
18420
						#目前$conf["text"]長度超過125會出錯.
18421
						$talkback=webSock::encode($conf["webSock::encode"]);
18422
						unset($conf["webSock::encode"]);
18423
 
18424
						#如果執行失敗
18425
						if($talkback["status"]==="false"){
18426
 
18427
							#印出結果
18428
							var_dump($talkback);
18429
 
18430
							#結束執行
18431
							exit;
18432
 
18433
							}#if end
18434
 
18435
						#debug
18436
						#var_dump(__LINE__,$talkback);
18437
 
18438
						}#if end
18439
 
18440
					}#if end
18441
 
18442
				}#if end
18443
 
18444
			#反之不為 web socket 訊息
18445
			else{
18446
 
18447
				#儲存成只有一個訊息
18448
				$talkback["content"][]=$talkback;
18449
 
18450
				}#else
18451
 
18452
			#針對每個訊息的分段
18453
			foreach($talkback["content"] as $msg){
18454
 
18455
				#回傳訊息
18456
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
18457
 
18458
				#debug
18459
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18460
 
18461
				}#foreach end
18462
 
18463
			#關閉被 client 的連線	
18464
			socket_close($con["connect"]);
18465
 
18466
			#清理連線的陣列
18467
			unset($connections[$conIndex]);
18468
 
18469
			#設置執行正常
18470
			$result["status"]="true";
18471
 
18472
			#回傳結果
18473
			return $result;
18474
 
18475
			}#if end
18476
 
18477
		#反之是如果收到的是 ids?
18478
		else if($receivedData === 'ids?'){
18479
 
18480
			#如果尚未認證
18481
			if($connections[$conIndex]["auth"]==="false"){
18482
 
18483
				#設置要回傳的訊息
18484
				$talkback=json_encode("permission denied");
18485
 
18486
				}#if end
18487
 
18488
			#反之
18489
			else{
18490
 
18491
				#設置要回傳的訊息
18492
				$talkback=array();
18493
 
18494
				#針對每個連線
18495
				foreach($connections as $conIndex_ids => $con_ids){
18496
 
18497
					#如果不是自己
18498
					if($con_ids["connect"]!==$connections[$conIndex]["connect"]){
18499
 
18500
						#記錄其他人的id
18501
						$talkback[]=$con_ids["id"];
18502
 
18503
						}#if end
18504
 
18505
					}#foreach end
18506
 
18507
				#json encode要回傳的id陣列
18508
				$talkback=json_encode($talkback);
18509
 
18510
				}#else end
18511
 
18512
			#如果是 ws 模式
18513
			if($conf["wsMode"]==="true"){
18514
 
18515
				#如果已經 handshake 過
18516
				if($connections[$conIndex]["handshaked"]==="true"){
18517
 
18518
					#如果要 unmask
18519
					if($connections[$conIndex]["unmask"]==="true"){
18520
 
18521
						#函式說明:
18522
						#加密 handshake 後要傳送的訊息 
18523
						#回傳結果:
18524
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18525
						#$result["error"],執行不正常結束的錯訊息陣列.
18526
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18527
						#$result["argu"],陣列,使用的參數.
18528
						#必填參數:
18529
						#$conf["text"],字串,要加密的訊息.
18530
						$conf["webSock::encode"]["text"]=$talkback; 
18531
						#可省略參數:
18532
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18533
						#$conf["payloadIsBin"]="false";
18534
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18535
						#$conf["ping"]="false";
18536
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18537
						#$conf["pong"]="false";
18538
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18539
						#$conf["frames"]=array();
18540
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18541
						#$conf["mask"]="false";
18542
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18543
						#$conf["debug"]="false";
18544
						#參考資料:
18545
						#無.
18546
						#備註:
18547
						#目前$conf["text"]長度超過125會出錯.
18548
						$talkback=webSock::encode($conf["webSock::encode"]);
18549
						unset($conf["webSock::encode"]);
18550
 
18551
						#如果執行失敗
18552
						if($talkback["status"]==="false"){
18553
 
18554
							#印出結果
18555
							var_dump($talkback);
18556
 
18557
							#結束執行
18558
							exit;
18559
 
18560
							}#if end
18561
 
18562
						#debug
18563
						#var_dump(__LINE__,$talkback);
18564
 
18565
						}#if end
18566
 
18567
					}#if end
18568
 
18569
				}#if end
18570
 
18571
			#反之不為 web socket 訊息
18572
			else{
18573
 
18574
				#儲存成只有一個訊息
18575
				$talkback["content"][]=$talkback;
18576
 
18577
				}#else
18578
 
18579
			#針對每個訊息的分段
18580
			foreach($talkback["content"] as $msg){
18581
 
18582
				#回傳訊息
18583
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18584
 
18585
				#debug
18586
				var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18587
 
18588
				}#foreach end
18589
 
18590
			#設置執行正常
18591
			$result["status"]="true";
18592
 
18593
			#回傳結果
18594
			return $result;
18595
 
18596
			}#if end
18597
 
18598
		#反之如果收到 "talkTo?"
18599
		else if($receivedData==="talkTo?"){
18600
 
18601
			#如果尚未認證
18602
			if($connections[$conIndex]["auth"]==="false"){
18603
 
18604
				#設置要回傳的訊息
18605
				$talkback=json_encode("permission denied");
18606
 
18607
				}#if end
18608
 
18609
			#反之
18610
			else{
18611
 
18612
				#初始化要講話的id陣列
18613
				$talkback=array();
18614
 
18615
				#有幾個要講話的人就執行幾次
18616
				foreach($connections[$conIndex]["talkTo"] as $to){
18617
 
18618
					#串街要講話的人
18619
					$talkback[]=$to;
18620
 
18621
					}#foreach end
18622
 
18623
				#設置要回傳的訊息
18624
				$talkback=json_encode($talkback).PHP_EOL;
18625
 
18626
				}#else end
18627
 
18628
			#如果是 ws 模式
18629
			if($conf["wsMode"]==="true"){
18630
 
18631
				#如果已經 handshake 過
18632
				if($connections[$conIndex]["handshaked"]==="true"){
18633
 
18634
					#如果要 unmask	
18635
					if($connections[$conIndex]["unmask"]==="true"){
18636
 
18637
						#函式說明:
18638
						#加密 handshake 後要傳送的訊息 
18639
						#回傳結果:
18640
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18641
						#$result["error"],執行不正常結束的錯訊息陣列.
18642
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18643
						#$result["argu"],陣列,使用的參數.
18644
						#必填參數:
18645
						#$conf["text"],字串,要加密的訊息.
18646
						$conf["webSock::encode"]["text"]=$talkback; 
18647
						#可省略參數:
18648
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18649
						#$conf["payloadIsBin"]="false";
18650
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18651
						#$conf["ping"]="false";
18652
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18653
						#$conf["pong"]="false";
18654
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18655
						#$conf["frames"]=array();
18656
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18657
						#$conf["mask"]="false";
18658
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18659
						#$conf["debug"]="false";
18660
						#參考資料:
18661
						#無.
18662
						#備註:
18663
						#目前$conf["text"]長度超過125會出錯.
18664
						$talkback=webSock::encode($conf["webSock::encode"]);
18665
						unset($conf["webSock::encode"]);
18666
 
18667
						#如果執行失敗
18668
						if($talkback["status"]==="false"){
18669
 
18670
							#印出結果
18671
							var_dump($talkback);
18672
 
18673
							#結束執行
18674
							exit;
18675
 
18676
							}#if end
18677
 
18678
						#debug
18679
						#var_dump(__LINE__,$talkback);
18680
 
18681
						}#if end
18682
 
18683
					}#if end
18684
 
18685
				}#if end
18686
 
18687
			#反之不為 web socket 訊息
18688
			else{
18689
 
18690
				#儲存成只有一個訊息
18691
				$talkback["content"][]=$talkback;
18692
 
18693
				}#else
18694
 
18695
			#針對每個訊息的分段
18696
			foreach($talkback["content"] as $msg){
18697
 
18698
				#回傳訊息
18699
				$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18700
 
18701
				#debug
18702
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18703
 
18704
				}#foreach end
18705
 
18706
			#設置執行正常
18707
			$result["status"]="true";
18708
 
18709
			#回傳結果
18710
			return $result;
18711
 
18712
			}#if end
18713
 
18714
		#如果收到的訊息長度大於 "talkTo:"
18715
		if(strlen($receivedData)>strlen("talkTo:")){
18716
 
18717
			#如果收到開頭為 "talkTo:"
18718
			#涵式說明:
18719
			#取得符合特定字首與字尾的字串
18720
			#回傳的結果:
18721
			#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
18722
			#$result["function"],當前執行的函數名稱.
18723
			#$result["error"],錯誤訊息陣列.
18724
			#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
18725
			#$result["returnString"],爲符合字首條件的字串內容。
18726
			#必填參數:
18727
			#$conf["checkString"],字串,要檢查的字串.
18728
			$conf["search::getMeetConditionsString"]["checkString"]=$receivedData;
18729
			#可省略參數:
18730
			#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
18731
			$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
18732
			#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
18733
			#$conf["tailWord"]="";
18734
			#參考資料:
18735
			#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
18736
			$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
18737
			unset($conf["search::getMeetConditionsString"]);
18738
 
18739
			#如果選找前置字串 "talkTo:" 失敗
18740
			if($getMeetConditionsString["status"]==="false"){
18741
 
18742
				#設置執行失敗
18743
				$result["status"]="false";
18744
 
18745
				#設置執行錯誤訊息
18746
				$result["error"]=$getMeetConditionsString;
18747
 
18748
				#回傳結果
18749
				return $result;
18750
 
18751
				}#if end
18752
 
18753
			#如果存在 "talkTo:" 前置字串
18754
			if($getMeetConditionsString["founded"]==="true"){
18755
 
18756
				#如果尚未認證
18757
				if($connections[$conIndex]["auth"]==="false"){
18758
 
18759
					#設置要回傳的訊息
18760
					$talkback=json_encode("permission denied");
18761
 
18762
					#如果是 ws 模式
18763
					if($conf["wsMode"]==="true"){
18764
 
18765
						#如果已經 handshake 過
18766
						if($connections[$conIndex]["handshaked"]==="true"){
18767
 
18768
							#如果要 unmask	
18769
							if($connections[$conIndex]["unmask"]==="true"){
18770
 
18771
								#函式說明:
18772
								#加密 handshake 後要傳送的訊息 
18773
								#回傳結果:
18774
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18775
								#$result["error"],執行不正常結束的錯訊息陣列.
18776
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18777
								#$result["argu"],陣列,使用的參數.
18778
								#必填參數:
18779
								#$conf["text"],字串,要加密的訊息.
18780
								$conf["webSock::encode"]["text"]=$talkback; 
18781
								#可省略參數:
18782
								#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18783
								#$conf["payloadIsBin"]="false";
18784
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18785
								#$conf["ping"]="false";
18786
								#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18787
								#$conf["pong"]="false";
18788
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18789
								#$conf["frames"]=array();
18790
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18791
								#$conf["mask"]="false";
18792
								#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18793
								#$conf["debug"]="false";
18794
								#參考資料:
18795
								#無.
18796
								#備註:
18797
								#目前$conf["text"]長度超過125會出錯.
18798
								$talkback=webSock::encode($conf["webSock::encode"]);
18799
								unset($conf["webSock::encode"]);
18800
 
18801
								#如果執行失敗
18802
								if($talkback["status"]==="false"){
18803
 
18804
									#印出結果
18805
									var_dump($talkback);
18806
 
18807
									#結束執行
18808
									exit;
18809
 
18810
									}#if end
18811
 
18812
								#debug
18813
								#var_dump(__LINE__,$talkback);
18814
 
18815
								}#if end
18816
 
18817
							}#if end
18818
 
18819
						}#if end
18820
 
18821
					#反之不為 web socket 訊息
18822
					else{
18823
 
18824
						#儲存成只有一個訊息
18825
						$talkback["content"][]=$talkback;
18826
 
18827
						}#else
18828
 
18829
					#針對每個訊息的分段
18830
					foreach($talkback["content"] as $msg){
18831
 
18832
						#回傳訊息
18833
						$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
18834
 
18835
						#debug
18836
						#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
18837
 
18838
						}#foreach end
18839
 
18840
					#設置執行正常
18841
					$result["status"]="true";
18842
 
18843
					#回傳結果
18844
					return $result;
18845
 
18846
					}#if end
18847
 
18848
				#用 "talkTo:" 分割收到的訊息
18849
				#涵式說明:
18850
				#將固定格式的字串分開,並回傳分開的結果。
18851
				#回傳結果:
18852
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18853
				#$result["error"],錯誤訊息陣列
18854
				#$result["function"],當前執行的函數名稱.
18855
				#$result["oriStr"],要分割的原始字串內容
18856
				#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
18857
				#$result["dataCounts"],爲總共分成幾段
18858
				#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
18859
				#必填的參數:
18860
				$conf["stringProcess::spiltString"]["stringIn"]=$receivedData;#要處理的字串。
18861
				$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
18862
				#可省略參數:
18863
				#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
18864
				$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
18865
				$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
18866
				unset($conf["stringProcess::spiltString"]);
18867
 
18868
				#如果分割字串失敗
18869
				if($spiltString["status"]==="false"){
18870
 
18871
					#設置執行失敗
18872
					$result["status"]="false";
18873
 
18874
					#設置執行錯誤訊息
18875
					$result["error"]=$spiltString;
18876
 
18877
					#回傳結果
18878
					return $result;
18879
 
18880
					}#if end
18881
 
18882
				#如果剛好分割出一筆資料
18883
				if($spiltString["dataCounts"]===1){
18884
 
18885
					#取得自己的id
18886
					$myId=$connections[$conIndex]["id"];
18887
 
18888
					#取得講話對象的id
18889
					$toId=$spiltString["dataArray"][0];
18890
 
18891
					#設置對象不存在的識別
18892
					$targetExist=false;
18893
 
18894
					#設置通話對象的key
18895
					$targetKey="";
18896
 
18897
					#取得除了自己的id以外的所有連線
18898
					foreach($connections as $index=>$talkInfo){
18899
 
18900
						#除了自己的id
18901
						if($talkInfo["id"]!==$myId){
18902
 
18903
							#如果存在要對話的對象
18904
							if($talkInfo["id"]===$toId){
18905
 
18906
								#設置對象存在的識別
18907
								$targetExist=true;
18908
 
18909
								#通話對象的key
18910
								$targetKey=$index;
18911
 
18912
								}#if end
18913
 
18914
							}#if end
18915
 
18916
						}#for each end
18917
 
18918
					#如果通話對象存在
18919
					if($targetExist){
18920
 
18921
						#保存自己的通話對象
18922
						$connections[$conIndex]["talkTo"][]=$toId;
18923
 
18924
						#設置要給自己看的訊息
18925
						$talkback="您與 ".$toId." 展開對話";
18926
 
18927
						#json encode 要給自己看的訊息
18928
						$talkback=json_encode($talkback).PHP_EOL;
18929
 
18930
						#如果是 ws 模式
18931
						if($conf["wsMode"]==="true"){
18932
 
18933
							#如果已經 handshake 過
18934
							if($connections[$conIndex]["handshaked"]==="true"){
18935
 
18936
								#如果要 unmask	
18937
								if($connections[$conIndex]["unmask"]==="true"){
18938
 
18939
									#函式說明:
18940
									#加密 handshake 後要傳送的訊息 
18941
									#回傳結果:
18942
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
18943
									#$result["error"],執行不正常結束的錯訊息陣列.
18944
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
18945
									#$result["argu"],陣列,使用的參數.
18946
									#必填參數:
18947
									#$conf["text"],字串,要加密的訊息.
18948
									$conf["webSock::encode"]["text"]=$talkback; 
18949
									#可省略參數:
18950
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
18951
									#$conf["payloadIsBin"]="false";
18952
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
18953
									#$conf["ping"]="false";
18954
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
18955
									#$conf["pong"]="false";
18956
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
18957
									#$conf["frames"]=array();
18958
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
18959
									#$conf["mask"]="false";
18960
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
18961
									#$conf["debug"]="false";
18962
									#參考資料:
18963
									#無.
18964
									#備註:
18965
									#目前$conf["text"]長度超過125會出錯.
18966
									$talkback=webSock::encode($conf["webSock::encode"]);
18967
									unset($conf["webSock::encode"]);
18968
 
18969
									#如果執行失敗
18970
									if($talkback["status"]==="false"){
18971
 
18972
										#印出結果
18973
										var_dump($talkback);
18974
 
18975
										#結束執行
18976
										exit;
18977
 
18978
										}#if end
18979
 
18980
									#debug
18981
									#var_dump(__LINE__,$talkback);
18982
 
18983
									}#if end
18984
 
18985
								}#if end
18986
 
18987
							}#if end
18988
 
18989
						#反之不為 web socket 訊息
18990
						else{
18991
 
18992
							#儲存成只有一個訊息
18993
							$talkback["content"][]=$talkback;
18994
 
18995
							}#else
18996
 
18997
						#針對每個訊息的分段
18998
						foreach($talkback["content"] as $msg){
18999
 
19000
							#回傳訊息
19001
							$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
19002
 
19003
							#debug
19004
							#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19005
 
19006
							}#foreach end
19007
 
19008
						#讓對方可以跟自己對話
19009
						$connections[$targetKey]["talkTo"][]=$myId;
19010
 
19011
						#設置要給對方看的訊息
19012
						$talkback=$connections[$conIndex]["id"]." 與您展開對話";
19013
 
19014
						#json encode 設置要給對方看的訊息
19015
						$talkback=json_encode($talkback);
19016
 
19017
						#如果是 ws 模式
19018
						if($conf["wsMode"]==="true"){
19019
 
19020
							#如果已經 handshake 過
19021
							if($connections[$conIndex]["handshaked"]==="true"){
19022
 
19023
								#如果要 unmask	
19024
								if($connections[$conIndex]["unmask"]==="true"){
19025
 
19026
									#函式說明:
19027
									#加密 handshake 後要傳送的訊息 
19028
									#回傳結果:
19029
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19030
									#$result["error"],執行不正常結束的錯訊息陣列.
19031
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19032
									#$result["argu"],陣列,使用的參數.
19033
									#必填參數:
19034
									#$conf["text"],字串,要加密的訊息.
19035
									$conf["webSock::encode"]["text"]=$talkback; 
19036
									#可省略參數:
19037
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19038
									#$conf["payloadIsBin"]="false";
19039
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19040
									#$conf["ping"]="false";
19041
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19042
									#$conf["pong"]="false";
19043
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19044
									#$conf["frames"]=array();
19045
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19046
									#$conf["mask"]="false";
19047
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19048
									#$conf["debug"]="false";
19049
									#參考資料:
19050
									#無.
19051
									#備註:
19052
									#目前$conf["text"]長度超過125會出錯.
19053
									$talkback=webSock::encode($conf["webSock::encode"]);
19054
									unset($conf["webSock::encode"]);
19055
 
19056
									#如果執行失敗
19057
									if($talkback["status"]==="false"){
19058
 
19059
										#印出結果
19060
										var_dump($talkback);
19061
 
19062
										#結束執行
19063
										exit;
19064
 
19065
										}#if end
19066
 
19067
									#debug
19068
									#var_dump(__LINE__,$talkback);
19069
 
19070
									}#if end
19071
 
19072
								}#if end
19073
 
19074
							}#if end
19075
 
19076
						#反之不為 web socket 訊息
19077
						else{
19078
 
19079
							#儲存成只有一個訊息
19080
							$talkback["content"][]=$talkback;
19081
 
19082
							}#else
19083
 
19084
						#針對每個訊息的分段
19085
						foreach($talkback["content"] as $msg){
19086
 
19087
							#給對方看的訊息
19088
							$socket_write=socket_write($connections[$targetKey]["connect"], $msg, strlen($msg));
19089
 
19090
							#debug
19091
							#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19092
 
19093
							}#foreach end
19094
 
19095
						#設置執行正常
19096
						$result["status"]="true";
19097
 
19098
						#回傳結果
19099
						return $result;
19100
 
19101
						}#if end
19102
 
19103
					}#if end
19104
 
19105
				}#if end
19106
 
19107
			}#if end
19108
 
19109
		#不是支援的訊息
19110
		$result["status"]="continue";
19111
 
19112
		#回傳結果
19113
		return $result;
19114
 
19115
		}#function basic end
19116
 
19117
	/*
19118
	#函式說明:
19119
	#提供webSock::nativeSocketTcpIpServer使用系統功能(system).
19120
	#回傳結果:
19121
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
19122
	#$result["error"],執行不正常結束的錯訊息陣列.
19123
	#$result["argu"],陣列,使用的參數.
19124
	#必填參數:
19125
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
19126
	$conf["data"]="";
19127
	#$conf["serverSock"],resource,web socket server socket
19128
	$conf["serverSock"]=$resource;
19129
	#$conf["clientSock"],$resource,web socket client socket
19130
	$conf["clientSock"]=$resource;
19131
	#$conf["clientInfo"],陣列,web socket client info.
19132
	$conf["clientInfo"]=array();
19133
	#$conf["clientIndex"],整數.web socket client index.
19134
	$conf["clientIndex"];
19135
	#$conf["allConn"],陣列,all web socket client info.
19136
	$conf["allConn"]=array();
19137
	#可省略參數:
19138
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
19139
	#$conf["wsMode"]="true";
19140
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
19141
	#$conf["gpgId"]=gnupgId;
19142
	#參考資料:
19143
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
19144
	#備註:
19145
	#收到用戶的"shutdown"訊息,會重新啟動webSocket server.
19146
	#無.
19147
	*/
19148
	public static function system(&$conf){
19149
 
19150
		#初始化要回傳的結果
19151
		$result=array();
19152
 
19153
		#取得當前執行的函數名稱
19154
		$result["function"]=__FUNCTION__;
19155
 
19156
		#涵式說明:
19157
		#判斷當前環境為web還是cmd
19158
		#回傳結果:
19159
		#$result,"web"或"cmd"
19160
		if(csInformation::getEnv()==="web"){
19161
 
19162
			#設置執行失敗
19163
			$result["status"]="false";
19164
 
19165
			#設置執行錯誤訊息
19166
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19167
 
19168
			#回傳結果
19169
			return $result;
19170
 
19171
			}#if end
19172
 
19173
		#取得參數
19174
		$result["argu"]=$conf;
19175
 
19176
		#如果 $conf 不為陣列
19177
		if(gettype($conf)!="array"){
19178
 
19179
			#設置執行失敗
19180
			$result["status"]="false";
19181
 
19182
			#設置執行錯誤訊息
19183
			$result["error"][]="\$conf變數須為陣列形態";
19184
 
19185
			#如果傳入的參數為 null
19186
			if($conf==null){
19187
 
19188
				#設置執行錯誤訊息
19189
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19190
 
19191
				}#if end
19192
 
19193
			#回傳結果
19194
			return $result;
19195
 
19196
			}#if end
19197
 
19198
		#檢查參數
19199
		#函式說明:
19200
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19201
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19202
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19203
		#$result["function"],當前執行的函式名稱.
19204
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19205
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19206
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19207
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19208
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19209
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
19210
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
19211
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
19212
		#必填寫的參數:
19213
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
19214
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
19215
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
19216
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
19217
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
19218
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
19219
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
19220
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
19221
		#可以省略的參數:
19222
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
19223
		#$conf["canBeEmptyString"]="false";
19224
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
19225
		#$conf["canNotBeEmpty"]=array();
19226
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
19227
		#$conf["canBeEmpty"]=array();
19228
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
19229
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
19230
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
19231
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
19232
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
19233
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
19234
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
19235
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
19236
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
19237
		#$conf["arrayCountEqualCheck"][]=array();
19238
		#參考資料來源:
19239
		#array_keys=>http://php.net/manual/en/function.array-keys.php
19240
		#建議:
19241
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
19242
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
19243
		unset($conf["variableCheck::checkArguments"]);
19244
 
19245
		#如果檢查參數失敗
19246
		if($checkArguments["status"]==="false"){
19247
 
19248
			#設置執行失敗
19249
			$result["status"]="false";
19250
 
19251
			#設置執行錯誤訊息
19252
			$result["error"]=$checkArguments;
19253
 
19254
			#回傳結果
19255
			return $result;
19256
 
19257
			}#if end
19258
 
19259
		#如果檢查參數不通過
19260
		if($checkArguments["passed"]==="false"){
19261
 
19262
			#設置執行失敗
19263
			$result["status"]="false";
19264
 
19265
			#設置執行錯誤訊息
19266
			$result["error"]=$checkArguments;
19267
 
19268
			#回傳結果
19269
			return $result;
19270
 
19271
			}#if end
19272
 
19273
		#取得收到的訊息
19274
		$receivedData=$conf["data"];
19275
 
19276
		#取得 server 的 socket
19277
		$serverSocket=$conf["serverSock"];
19278
 
19279
		#取得 client 的 socket
19280
		$clientSocket=$conf["clientSock"];
19281
 
19282
		#取得 client 的資訊
19283
		$clientInfo=$conf["clientInfo"];
19284
 
19285
		#取得 client 的索引
19286
		$clientIndex=$conf["clientIndex"];
19287
 
19288
		#取得 all clients 的資訊
19289
		$allConn=&$conf["allConn"];
19290
 
19291
		#hex2bin
19292
		#函式說明:
19293
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19294
		#回傳結果:
19295
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19296
		#$result["function"],當前執行的函數名稱.
19297
		#$result["content"],加密後的結果.
19298
		#$result["error"],錯誤訊息陣列.
19299
		#$result["argu"],使用的參數.
19300
		#必填參數:
19301
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19302
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19303
		#$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".
19304
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
19305
		#可省略參數:
19306
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19307
		#$conf["sha1Raw"]="false";
19308
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19309
		#$conf["p_hash"]="";
19310
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19311
		#$conf["keyForAes256"]="";
19312
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19313
		#$conf["aes256Encode"]="";
19314
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19315
		#$conf["qbpwcfDecode"]="false";
19316
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19317
		#$conf["gpgDecrypt"]="false";
19318
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19319
		#$conf["gpgId"]="";
19320
		#參考資料:
19321
		#sha1=>http://php.net/manual/en/function.sha1.php
19322
		#md5=>http://php.net/manual/en/function.md5.php
19323
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19324
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19325
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19326
		#備註:
19327
		#無.
19328
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19329
		unset($conf["authenticate::enCodeStr"]);
19330
 
19331
		#如果執行失敗
19332
		if($enCodeStr["status"]==="false"){
19333
 
19334
			#設置執行異常
19335
			$result["status"]="false";
19336
 
19337
			#設置執行錯誤
19338
			$result["error"]=$enCodeStr;
19339
 
19340
			#回傳結果
19341
			return $result;
19342
 
19343
			}#if end
19344
 
19345
		#取得hex2bin後的字串
19346
		$receivedData=$enCodeStr["content"];
19347
 
19348
		#gpg decrypt
19349
		#函式說明:
19350
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19351
		#回傳結果:
19352
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19353
		#$result["function"],當前執行的函數名稱.
19354
		#$result["content"],加密後的結果.
19355
		#$result["error"],錯誤訊息陣列.
19356
		#$result["argu"],使用的參數.
19357
		#必填參數:
19358
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19359
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19360
		#$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".
19361
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
19362
		#可省略參數:
19363
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19364
		#$conf["sha1Raw"]="false";
19365
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19366
		#$conf["p_hash"]="";
19367
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19368
		#$conf["keyForAes256"]="";
19369
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19370
		#$conf["aes256Encode"]="";
19371
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19372
		#$conf["qbpwcfDecode"]="false";
19373
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19374
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
19375
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19376
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
19377
		#參考資料:
19378
		#sha1=>http://php.net/manual/en/function.sha1.php
19379
		#md5=>http://php.net/manual/en/function.md5.php
19380
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19381
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19382
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19383
		#備註:
19384
		#無.
19385
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19386
		unset($conf["authenticate::enCodeStr"]);
19387
 
19388
		#如果執行失敗
19389
		if($enCodeStr["status"]==="false"){
19390
 
19391
			#設置執行異常
19392
			$result["status"]="false";
19393
 
19394
			#設置執行錯誤
19395
			$result["error"]=$enCodeStr;
19396
 
19397
			#回傳結果
19398
			return $result;
19399
 
19400
			}#if end
19401
 
19402
		#取得解密後的字串
19403
		$receivedData=$enCodeStr["content"];
19404
 
19405
		#json_decode
19406
		$receivedData=json_decode($receivedData);
19407
 
19408
		#如果收到 "shutdown"
19409
		if($receivedData==="shutdown"){
19410
 
19411
			#設置要回傳的訊息
19412
			$talkback="Server 即將關閉";
19413
 
19414
			#json encode 要回傳的訊息
19415
			$talkback=json_encode($talkback);
19416
 
19417
			#如果是 ws 模式
19418
			if($conf["wsMode"]==="true"){
19419
 
19420
				#如果已經 handshake 過
19421
				if($connections[$conIndex]["handshaked"]==="true"){
19422
 
19423
					#如果要 unmask	
19424
					if($connections[$conIndex]["unmask"]==="true"){
19425
 
19426
						#函式說明:
19427
						#加密 handshake 後要傳送的訊息 
19428
						#回傳結果:
19429
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19430
						#$result["error"],執行不正常結束的錯訊息陣列.
19431
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19432
						#$result["argu"],陣列,使用的參數.
19433
						#必填參數:
19434
						#$conf["text"],字串,要加密的訊息.
19435
						$conf["webSock::encode"]["text"]=$talkback; 
19436
						#可省略參數:
19437
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19438
						#$conf["payloadIsBin"]="false";
19439
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19440
						#$conf["ping"]="false";
19441
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19442
						#$conf["pong"]="false";
19443
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19444
						#$conf["frames"]=array();
19445
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19446
						#$conf["mask"]="false";
19447
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19448
						#$conf["debug"]="false";
19449
						#參考資料:
19450
						#無.
19451
						#備註:
19452
						#無.
19453
						$talkback=webSock::encode($conf["webSock::encode"]);
19454
						unset($conf["webSock::encode"]);
19455
 
19456
						#如果執行失敗
19457
						if($talkback["status"]==="false"){
19458
 
19459
							#印出結果
19460
							var_dump($talkback);
19461
 
19462
							#結束執行
19463
							exit;
19464
 
19465
							}#if end
19466
 
19467
						#debug
19468
						#var_dump(__LINE__,$talkback);
19469
 
19470
						}#if end
19471
 
19472
					}#if end
19473
 
19474
				}#if end
19475
 
19476
			#反之不為 web socket 訊息
19477
			else{
19478
 
19479
				#儲存成只有一個訊息
19480
				$talkback["content"][]=$talkback;
19481
 
19482
				}#else
19483
 
19484
			#針對每個訊息的分段
19485
			foreach($talkback["content"] as $msg){
19486
 
19487
				#回傳訊息
19488
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
19489
 
19490
				#debug
19491
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19492
 
19493
				}#foreach end
19494
 
19495
			#關閉用戶的連線
19496
			socket_close($con["connect"]);
19497
 
19498
			}#if end
19499
 
19500
		#關閉 server socket
19501
		socket_close($serverSocket);
19502
 
19503
		#設置執行正常
19504
		$result["status"]="true";
19505
 
19506
		#回傳結果
19507
		return $result;
19508
 
19509
		}#function system end
19510
 
19511
	/*
19512
	#函式說明:
19513
	#提供webSock::nativeSocketTcpIpServer使用系統功能(system).
19514
	#回傳結果:
19515
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
19516
	#$result["error"],執行不正常結束的錯訊息陣列.
19517
	#$result["argu"],陣列,使用的參數.
19518
	#必填參數:
19519
	#$conf["data"],字串,收到的bin2hex編碼後再gpg加密過後的json格式資料.
19520
	$conf["data"]="";
19521
	#$conf["serverSock"],resource,web socket server socket
19522
	$conf["serverSock"]=$resource;
19523
	#$conf["clientSock"],$resource,web socket client socket
19524
	$conf["clientSock"]=$resource;
19525
	#$conf["clientInfo"],陣列,web socket client info.
19526
	$conf["clientInfo"]=array();
19527
	#$conf["clientIndex"],整數.web socket client index.
19528
	$conf["clientIndex"];
19529
	#$conf["allConn"],陣列,all web socket client info.
19530
	$conf["allConn"]=array();
19531
	#可省略參數:
19532
	#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
19533
	#$conf["wsMode"]="true";
19534
	#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
19535
	#$conf["gpgId"]=gnupgId;
19536
	#參考資料:
19537
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
19538
	#備註:
19539
	#收到用戶的"quit"訊息,會結束與用戶的連線.
19540
	*/
19541
	public static function noAuth(&$conf){
19542
 
19543
		#初始化要回傳的結果
19544
		$result=array();
19545
 
19546
		#取得當前執行的函數名稱
19547
		$result["function"]=__FUNCTION__;
19548
 
19549
		#涵式說明:
19550
		#判斷當前環境為web還是cmd
19551
		#回傳結果:
19552
		#$result,"web"或"cmd"
19553
		if(csInformation::getEnv()==="web"){
19554
 
19555
			#設置執行失敗
19556
			$result["status"]="false";
19557
 
19558
			#設置執行錯誤訊息
19559
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19560
 
19561
			#回傳結果
19562
			return $result;
19563
 
19564
			}#if end
19565
 
19566
		#取得參數
19567
		$result["argu"]=$conf;
19568
 
19569
		#如果 $conf 不為陣列
19570
		if(gettype($conf)!="array"){
19571
 
19572
			#設置執行失敗
19573
			$result["status"]="false";
19574
 
19575
			#設置執行錯誤訊息
19576
			$result["error"][]="\$conf變數須為陣列形態";
19577
 
19578
			#如果傳入的參數為 null
19579
			if($conf==null){
19580
 
19581
				#設置執行錯誤訊息
19582
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19583
 
19584
				}#if end
19585
 
19586
			#回傳結果
19587
			return $result;
19588
 
19589
			}#if end
19590
 
19591
		#檢查參數
19592
		#函式說明:
19593
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19594
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19595
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19596
		#$result["function"],當前執行的函式名稱.
19597
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19598
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19599
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19600
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19601
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19602
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
19603
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
19604
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
19605
		#必填寫的參數:
19606
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
19607
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
19608
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
19609
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
19610
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
19611
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
19612
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
19613
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
19614
		#可以省略的參數:
19615
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
19616
		#$conf["canBeEmptyString"]="false";
19617
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
19618
		#$conf["canNotBeEmpty"]=array();
19619
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
19620
		#$conf["canBeEmpty"]=array();
19621
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
19622
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("wsMode");
19623
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
19624
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("wsMode","gpgId");
19625
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
19626
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
19627
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
19628
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true",gnupgId);
19629
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
19630
		#$conf["arrayCountEqualCheck"][]=array();
19631
		#參考資料來源:
19632
		#array_keys=>http://php.net/manual/en/function.array-keys.php
19633
		#建議:
19634
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
19635
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
19636
		unset($conf["variableCheck::checkArguments"]);
19637
 
19638
		#如果檢查參數失敗
19639
		if($checkArguments["status"]==="false"){
19640
 
19641
			#設置執行失敗
19642
			$result["status"]="false";
19643
 
19644
			#設置執行錯誤訊息
19645
			$result["error"]=$checkArguments;
19646
 
19647
			#回傳結果
19648
			return $result;
19649
 
19650
			}#if end
19651
 
19652
		#如果檢查參數不通過
19653
		if($checkArguments["passed"]==="false"){
19654
 
19655
			#設置執行失敗
19656
			$result["status"]="false";
19657
 
19658
			#設置執行錯誤訊息
19659
			$result["error"]=$checkArguments;
19660
 
19661
			#回傳結果
19662
			return $result;
19663
 
19664
			}#if end
19665
 
19666
		#取得收到的訊息
19667
		$receivedData=$conf["data"];
19668
 
19669
		#取得 server 的 socket
19670
		$serverSocket=$conf["serverSock"];
19671
 
19672
		#取得 client 的 socket
19673
		$clientSocket=$conf["clientSock"];
19674
 
19675
		#取得 client 的資訊
19676
		$clientInfo=$conf["clientInfo"];
19677
 
19678
		#取得 client 的索引
19679
		$clientIndex=$conf["clientIndex"];
19680
 
19681
		#取得 all clients 的資訊
19682
		$allConn=&$conf["allConn"];
19683
 
19684
		#hex2bin
19685
		#函式說明:
19686
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19687
		#回傳結果:
19688
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19689
		#$result["function"],當前執行的函數名稱.
19690
		#$result["content"],加密後的結果.
19691
		#$result["error"],錯誤訊息陣列.
19692
		#$result["argu"],使用的參數.
19693
		#必填參數:
19694
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19695
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19696
		#$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".
19697
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
19698
		#可省略參數:
19699
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19700
		#$conf["sha1Raw"]="false";
19701
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19702
		#$conf["p_hash"]="";
19703
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19704
		#$conf["keyForAes256"]="";
19705
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19706
		#$conf["aes256Encode"]="";
19707
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19708
		#$conf["qbpwcfDecode"]="false";
19709
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19710
		#$conf["gpgDecrypt"]="false";
19711
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19712
		#$conf["gpgId"]="";
19713
		#參考資料:
19714
		#sha1=>http://php.net/manual/en/function.sha1.php
19715
		#md5=>http://php.net/manual/en/function.md5.php
19716
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19717
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19718
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19719
		#備註:
19720
		#無.
19721
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19722
		unset($conf["authenticate::enCodeStr"]);
19723
 
19724
		#如果執行失敗
19725
		if($enCodeStr["status"]==="false"){
19726
 
19727
			#設置執行異常
19728
			$result["status"]="false";
19729
 
19730
			#設置執行錯誤
19731
			$result["error"]=$enCodeStr;
19732
 
19733
			#回傳結果
19734
			return $result;
19735
 
19736
			}#if end
19737
 
19738
		#取得hex2bin後的字串
19739
		$receivedData=$enCodeStr["content"];
19740
 
19741
		#gpg decrypt
19742
		#函式說明:
19743
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
19744
		#回傳結果:
19745
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19746
		#$result["function"],當前執行的函數名稱.
19747
		#$result["content"],加密後的結果.
19748
		#$result["error"],錯誤訊息陣列.
19749
		#$result["argu"],使用的參數.
19750
		#必填參數:
19751
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
19752
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
19753
		#$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".
19754
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
19755
		#可省略參數:
19756
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
19757
		#$conf["sha1Raw"]="false";
19758
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
19759
		#$conf["p_hash"]="";
19760
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
19761
		#$conf["keyForAes256"]="";
19762
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
19763
		#$conf["aes256Encode"]="";
19764
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
19765
		#$conf["qbpwcfDecode"]="false";
19766
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
19767
		$conf["authenticate::enCodeStr"]["gpgDecrypt"]="true";
19768
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
19769
		$conf["authenticate::enCodeStr"]["gpgId"]=$conf["gpgId"];
19770
		#參考資料:
19771
		#sha1=>http://php.net/manual/en/function.sha1.php
19772
		#md5=>http://php.net/manual/en/function.md5.php
19773
		#password_hash=>http://php.net/manual/en/function.password-hash.php
19774
		#password_verify=>http://php.net/manual/en/function.password-verify.php
19775
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
19776
		#備註:
19777
		#無.
19778
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
19779
		unset($conf["authenticate::enCodeStr"]);
19780
 
19781
		#如果執行失敗
19782
		if($enCodeStr["status"]==="false"){
19783
 
19784
			#設置執行異常
19785
			$result["status"]="false";
19786
 
19787
			#設置執行錯誤
19788
			$result["error"]=$enCodeStr;
19789
 
19790
			#回傳結果
19791
			return $result;
19792
 
19793
			}#if end
19794
 
19795
		#取得解密後的字串
19796
		$receivedData=$enCodeStr["content"];
19797
 
19798
		#json_decode
19799
		$receivedData=json_decode($receivedData);
19800
 
19801
		#如果訊息內容為 "quit"
19802
		if($receivedData==="quit"){
19803
 
19804
			#設置要回傳的訊息
19805
			$talkback="結束與 server 的連線";
19806
 
19807
			#json encode 要回傳的訊息
19808
			$talkback=json_encode($talkback).PHP_EOL;
19809
 
19810
			#如果是 ws 模式
19811
			if($conf["wsMode"]==="true"){
19812
 
19813
				#如果已經 handshake 過
19814
				if($connections[$conIndex]["handshaked"]==="true"){
19815
 
19816
					#如果要 unmask	
19817
					if($connections[$conIndex]["unmask"]==="true"){
19818
 
19819
						#函式說明:
19820
						#加密 handshake 後要傳送的訊息 
19821
						#回傳結果:
19822
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19823
						#$result["error"],執行不正常結束的錯訊息陣列.
19824
						#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
19825
						#$result["argu"],陣列,使用的參數.
19826
						#必填參數:
19827
						#$conf["text"],字串,要加密的訊息.
19828
						$conf["webSock::encode"]["text"]=$talkback; 
19829
						#可省略參數:
19830
						#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
19831
						#$conf["payloadIsBin"]="false";
19832
						#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
19833
						#$conf["ping"]="false";
19834
						#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
19835
						#$conf["pong"]="false";
19836
						#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
19837
						#$conf["frames"]=array();
19838
						#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
19839
						#$conf["mask"]="false";
19840
						#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
19841
						#$conf["debug"]="false";
19842
						#參考資料:
19843
						#無.
19844
						#備註:
19845
						#目前$conf["text"]長度超過125會出錯.
19846
						$talkback=webSock::encode($conf["webSock::encode"]);
19847
						unset($conf["webSock::encode"]);
19848
 
19849
						#如果執行失敗
19850
						if($talkback["status"]==="false"){
19851
 
19852
							#印出結果
19853
							var_dump($talkback);
19854
 
19855
							#結束執行
19856
							exit;
19857
 
19858
							}#if end
19859
 
19860
						#debug
19861
						#var_dump(__LINE__,$talkback);
19862
 
19863
						}#if end
19864
 
19865
					}#if end
19866
 
19867
				}#if end
19868
 
19869
			#反之不為 web socket 訊息
19870
			else{
19871
 
19872
				#儲存成只有一個訊息
19873
				$talkback["content"][]=$talkback;
19874
 
19875
				}#else
19876
 
19877
			#針對每個訊息的分段
19878
			foreach($talkback["content"] as $msg){
19879
 
19880
				#回傳訊息
19881
				$socket_write=socket_write($con["connect"], $msg, strlen($msg));
19882
 
19883
				#debug
19884
				#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
19885
 
19886
				}#foreach end
19887
 
19888
			#關閉被 client 的連線
19889
			socket_close($con["connect"]);
19890
 
19891
			#清理連線的陣列
19892
			unset($connections[$conIndex]);
19893
 
19894
			#設置執行正常
19895
			$result["status"]="true";
19896
 
19897
			#回傳結果
19898
			return $result;
19899
 
19900
			}#if end
19901
 
19902
		}#function noAuth end
19903
 
19904
	/*
19905
	#函式說明:
19906
	#依照參數來執行對應的函式.
19907
	#回傳結果:
19908
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
19909
	#$result["function"],當前執行的函數名稱.
19910
	#$result["content"],加密後的結果.
19911
	#$result["error"],錯誤訊息陣列.
19912
	#$result["argu"],使用的參數.
19913
	#必填參數:
19914
	#$conf["data"],字串,收到bin2hex編碼後再gpg加密後的資料.
19915
	$conf["data"]="";
19916
	#$conf["serverSock"],socket,代表web socket server的socket.
19917
	$conf["serverSock"]=;
19918
	#$conf["clientSock"],socket,代表web socket client的socket.
19919
	#$conf["clientInfo"],陣列,用戶端的資訊.
19920
	$conf["clientInfo"]=array();
19921
	#$conf["clientIndex"],字串,代表client於allConn中的索引.
19922
	$conf["clientIndex"]="";
19923
	#$conf["allConn"],陣列,所有連線的用戶端的連線資訊.
19924
	$conf["allConn"]=array();
19925
	#可省略參數:
19926
	#無.
19927
	#參考資料:
19928
	#無.
19929
	#備註:
19930
	#無.
19931
	*/
19932
	public static function callFunc(&$conf){
19933
 
19934
		#初始化要回傳的結果
19935
		$result=array();
19936
 
19937
		#取得當前執行的函數名稱
19938
		$result["function"]=__FUNCTION__;
19939
 
19940
		#涵式說明:
19941
		#判斷當前環境為web還是cmd
19942
		#回傳結果:
19943
		#$result,"web"或"cmd"
19944
		if(csInformation::getEnv()==="web"){
19945
 
19946
			#設置執行失敗
19947
			$result["status"]="false";
19948
 
19949
			#設置執行錯誤訊息
19950
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
19951
 
19952
			#回傳結果
19953
			return $result;
19954
 
19955
			}#if end
19956
 
19957
		#取得參數
19958
		$result["argu"]=$conf;
19959
 
19960
		#如果 $conf 不為陣列
19961
		if(gettype($conf)!="array"){
19962
 
19963
			#設置執行失敗
19964
			$result["status"]="false";
19965
 
19966
			#設置執行錯誤訊息
19967
			$result["error"][]="\$conf變數須為陣列形態";
19968
 
19969
			#如果傳入的參數為 null
19970
			if($conf==null){
19971
 
19972
				#設置執行錯誤訊息
19973
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
19974
 
19975
				}#if end
19976
 
19977
			#回傳結果
19978
			return $result;
19979
 
19980
			}#if end
19981
 
19982
		#檢查參數
19983
		#函式說明:
19984
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
19985
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
19986
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
19987
		#$result["function"],當前執行的函式名稱.
19988
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
19989
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
19990
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
19991
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
19992
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
19993
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
19994
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
19995
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
19996
		#必填寫的參數:
19997
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
19998
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
19999
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
20000
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientInfo","clientIndex","allConn");
20001
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
20002
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","array","string","array");
20003
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
20004
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
20005
		#可以省略的參數:
20006
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
20007
		#$conf["canBeEmptyString"]="false";
20008
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
20009
		#$conf["canNotBeEmpty"]=array();
20010
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
20011
		#$conf["canBeEmpty"]=array();
20012
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
20013
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
20014
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
20015
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("listenIp","listenPort","wsMode","processFuncs");
20016
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
20017
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array");
20018
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
20019
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",null,"false",null);
20020
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
20021
		#$conf["arrayCountEqualCheck"][]=array();
20022
		#參考資料來源:
20023
		#array_keys=>http://php.net/manual/en/function.array-keys.php
20024
		#建議:
20025
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
20026
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
20027
		unset($conf["variableCheck::checkArguments"]);
20028
 
20029
		#如果檢查參數失敗
20030
		if($checkArguments["status"]==="false"){
20031
 
20032
			#設置執行失敗
20033
			$result["status"]="false";
20034
 
20035
			#設置執行錯誤訊息
20036
			$result["error"]=$checkArguments;
20037
 
20038
			#回傳結果
20039
			return $result;
20040
 
20041
			}#if end
20042
 
20043
		#如果檢查參數不通過
20044
		if($checkArguments["passed"]==="false"){
20045
 
20046
			#設置執行失敗
20047
			$result["status"]="false";
20048
 
20049
			#設置執行錯誤訊息
20050
			$result["error"]=$checkArguments;
20051
 
20052
			#回傳結果
20053
			return $result;
20054
 
20055
			}#if end
20056
 
20057
		#取得收到的訊息
20058
		$receivedData=$conf["data"];
20059
 
20060
		#取得 server 的 socket
20061
		$serverSocket=$conf["serverSock"];
20062
 
20063
		#取得 client 的 socket
20064
		$clientSocket=$conf["clientSock"];
20065
 
20066
		#取得 client 的資訊
20067
		$clientInfo=$conf["clientInfo"];
20068
 
20069
		#取得 client 的索引
20070
		$clientIndex=$conf["clientIndex"];
20071
 
20072
		#取得 all clients 的資訊
20073
		$allConn=$conf["allConn"];
20074
 
20075
		#hex2bin
20076
		#函式說明:
20077
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,gpg,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
20078
		#回傳結果:
20079
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
20080
		#$result["function"],當前執行的函數名稱.
20081
		#$result["content"],加密後的結果.
20082
		#$result["error"],錯誤訊息陣列.
20083
		#$result["argu"],使用的參數.
20084
		#必填參數:
20085
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
20086
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$receivedData;
20087
		#$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加解密.
20088
		$conf["authenticate::enCodeStr"]["enCodeType"]="hex2bin";
20089
		#可省略參數:
20090
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
20091
		#$conf["sha1Raw"]="false";
20092
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
20093
		#$conf["p_hash"]="";
20094
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
20095
		#$conf["keyForAes256"]="";
20096
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
20097
		#$conf["aes256Encode"]="";
20098
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
20099
		#$conf["qbpwcfDecode"]="false";
20100
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
20101
		#$conf["gpgDecrypt"]="false";
20102
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
20103
		$conf["authenticate::enCodeStr"]["gpgId"]=gnupgId;
20104
		#參考資料:
20105
		#sha1=>http://php.net/manual/en/function.sha1.php
20106
		#md5=>http://php.net/manual/en/function.md5.php
20107
		#password_hash=>http://php.net/manual/en/function.password-hash.php
20108
		#password_verify=>http://php.net/manual/en/function.password-verify.php
20109
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
20110
		#備註:
20111
		#無.
20112
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
20113
		unset($conf["authenticate::enCodeStr"]);
20114
 
20115
		#如果執行失敗
20116
		if($enCodeStr["status"]==="false"){
20117
 
20118
			#印出結果
20119
			return $enCodeStr;
20120
 
20121
			}#if end
20122
 
20123
		#用GnuPG解密
20124
		#函式說明:
20125
		#加密或編碼字串,可以用的方法有sha1,md5,password_sha,qbpwcf,bin2hex,hex2bin,gpg,sha1可以回傳20或40的數值字串,md5可以回傳32個數值字串,password_hash可以回傳60~255個字元.
20126
		#回傳結果:
20127
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常. 
20128
		#$result["function"],當前執行的函數名稱.
20129
		#$result["content"],加密後的結果.
20130
		#$result["error"],錯誤訊息陣列.
20131
		#$result["argu"],使用的參數.
20132
		#必填參數:
20133
		#$conf["enCodeStr"],any,要加密的字串,陣列,物件.
20134
		$conf["authenticate::enCodeStr"]["enCodeStr"]=$$enCodeStr["content"];
20135
		#$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加解密.
20136
		$conf["authenticate::enCodeStr"]["enCodeType"]="gpg";
20137
		#可省略參數:
20138
		#$conf["sha1Raw"],字串,sha1加密的結果要用20個0與1組合還是要用40位數的16進位數值,"true"代表前者,"false"代表後者,預設為"false".
20139
		#$conf["sha1Raw"]="false";
20140
		#$conf["p_hash"],字串,p_hash加密過後的字串,該參數若存在且$conf["enCodeType"]為"p_hash",則代表是要檢查$conf["enCodeStr"]是否為符合$conf["p_hash"]的密碼.
20141
		#$conf["p_hash"]="";
20142
		#$conf["keyForAes256"],字串,用來 AES256 加解密的金鑰.
20143
		#$conf["keyForAes256"]="";
20144
		#$conf["aes256Encode"],字串,"true"代表是要加密,"false"代表是要解密.
20145
		#$conf["aes256Encode"]="";
20146
		#$conf["qbpwcfDecode"],字串,若"enCodeType"為"qbpwcf",則預設為"false",代表加密;反之為"true",代表解密.
20147
		#$conf["qbpwcfDecode"]="false";
20148
		#$conf["gpgDecrypt"],字串,若"enCodeType"為"gpg",則預設為"false",代表加密;反之為"true",代表解密.
20149
		#$conf["gpgDecrypt"]="false";
20150
		#$conf["gpgId"],字串,若"enCodeType"為"gpg"時,該參數必填.
20151
		$conf["authenticate::enCodeStr"]["gpgId"]=gnupgId;
20152
		#參考資料:
20153
		#sha1=>http://php.net/manual/en/function.sha1.php
20154
		#md5=>http://php.net/manual/en/function.md5.php
20155
		#password_hash=>http://php.net/manual/en/function.password-hash.php
20156
		#password_verify=>http://php.net/manual/en/function.password-verify.php
20157
		#json_decode=>https://www.php.net/manual/en/function.json-decode.php
20158
		#備註:
20159
		#無.
20160
		$enCodeStr=authenticate::enCodeStr($conf["authenticate::enCodeStr"]);
20161
		unset($conf["authenticate::enCodeStr"]);
20162
 
20163
		#如果執行失敗
20164
		if($enCodeStr["status"]==="false"){
20165
 
20166
			#印出結果
20167
			return $enCodeStr;
20168
 
20169
			}#if end
20170
 
20171
		#解碼取得的內容
20172
		$receivedData=json_decode($enCodeStr["content"]);
20173
 
20174
		#如果有設置 callFunc
20175
		if(isset($receivedData->callFunc)){
20176
 
20177
			#取得要呼叫的函式
20178
			$func=$receivedData->callFunc;
20179
 
20180
			#檢查是否有權限執行該函式
20181
			#函式說明:
20182
			#提供webSock::nativeSocketTcpIpServer用於接受檢查權限的功能.
20183
			#回傳結果:
20184
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
20185
			#$result["error"],執行不正常結束的錯訊息陣列.
20186
			#$result["argu"],陣列,使用的參數.
20187
			#必填參數:
20188
			#$conf["data"],字串,收到的bin2hex編碼後果gpg加密過後的json格式資料,必填的key有"randomStr","username","password".
20189
			$conf["self::checkAuth"]["data"]=$conf["data"];
20190
			#$conf["serverSock"],resource,web socket server socket
20191
			$conf["self::checkAuth"]["serverSock"]=$conf["serverSock"];
20192
			#$conf["clientSock"],$resource,web socket client socket
20193
			$conf["self::checkAuth"]["clientSock"]=$conf["clientSock"];
20194
			#$conf["clientInfo"],陣列,web socket client info.
20195
			$conf["self::checkAuth"]["clientInfo"]=$conf["clientInfo"];
20196
			#$conf["clientIndex"],整數.web socket client index.
20197
			$conf["self::checkAuth"]["clientIndex"]=$conf["clientIndex"];
20198
			#$conf["allConn"],陣列,all web socket client info.
20199
			$conf["self::checkAuth"]["allConn"]=$conf["allConn"];
20200
			#$conf["func"],字串,要檢查的是否具備權限的函式.
20201
			$conf["self::checkAuth"]["func"]=$func;
20202
			#可省略參數:
20203
			#$conf["wsMode"],字串,是否要按照rfc6555,預設為"true"為是;"false"為否.
20204
			#$conf["wsMode"]="true";
20205
			#$conf["gpgId"],字串,用於加解密的gpg id,預設為gnupgId.
20206
			#$conf["gpgId"]=gnupgId;
20207
			#$conf["falseAllowFuncPlus"],陣列,額外的未認證時可以執行的函式清單.
20208
			#$conf["falseAllowFuncPlus"]=array();
20209
			#$conf["publicAllowFuncPlus"],陣列,額外的認證為public時可以執行的函式清單.
20210
			#$conf["publicAllowFuncPlus"]=array();
20211
			#參考資料:
20212
			#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
20213
			#備註:
20214
			#無.
20215
			$checkAuth=self::checkAuth($conf["self::checkAuth"]);
20216
			unset($conf["self::checkAuth"]);
20217
 
20218
			#如果異常
20219
			if($checkAuth["status"]==="false"){
20220
 
20221
				#回傳結果
20222
				return $checkAuth;
20223
 
20224
				}#if end
20225
 
20226
			#移除使用好的元素
20227
			unset($receivedData["callFunc"]);
20228
 
20229
			#置換data為未加密的內容
20230
			$conf["data"]=json_encode($receivedData);
20231
 
20232
			#呼叫對應的函式
20233
			return eval($func."(&\$conf);");
20234
 
20235
			}#if end
20236
 
20237
		#設置執行失敗
20238
		$result["ststus"]="false";
20239
 
20240
		#回傳結果
20241
		return $result;
20242
 
20243
		}#function callFunc end
20244
 
3 liveuser 20245
	}#class webSock end
20246
 
66 liveuser 20247
?>