Subversion Repositories php-qbpwcf

Rev

Rev 66 | Go to most recent revision | Details | 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__的內容.
10038
			$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];		
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";
10111
	#$conf["processFuncs"],陣列,針對收到的訊息要呼叫的函式,會帶入一個參數陣列,array("data"=>收到的資料,"serverSock"=>serverSock,"clientSock"=>clientSock,"clientInfo"=>用戶端的資訊,"clientIndex"=>用戶端的索引,"allConn"=>所有連線的用戶端的連線資訊),回傳的結果若為陣列$result,其$result["status"]為"true"時,會結束執行(等待下個訊息);為"false"時,會var_dump結果,然後交給下一個函式執行;為"continue"時,代表交給下一個函式執行.
10112
	#$conf["processFuncs"]=array();
10113
	#參考資料:
10114
	#http://php.net/manual/en/sockets.examples.php
10115
	#http://us3.php.net/manual/en/function.socket-select.php
10116
	#response should at least end with "\r"=>http://stackoverflow.com/questions/25739768/websocket-communication-between-chromeclient-and-hotspotserver-status-line
10117
	#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
10118
	#webSocket實做=>http://srchea.com/build-a-real-time-application-using-html5-websockets
10119
	#webSocketServer實做=>http://www.cuelogic.com/blog/php-and-html5-websocket-server-and-client-communication/
10120
	#備註:
10121
	#僅能在命令列執行.
10122
	#收到用戶的"id?"訊息,會回傳用戶的id.
10123
	#收到用戶的"ids?"訊息,會回傳非自己的所有用戶id
10124
	#收到用戶的"talkTo?"訊息,會回傳目前在跟誰談話.
10125
	#收到用戶的"talkTo:client-id"訊息,會建立與id對應的用戶對話,此後傳遞的訊息均會給對方.
10126
	#收到用戶的"quit"訊息,會結束與用戶的連線.
10127
	#收到用戶的"shutdown"訊息,會重新啟動webSocket server.
10128
	*/
10129
	public static function nativeSocketTcpIpServer(&$conf){
10130
 
10131
		#初始化要回傳的結果
10132
		$result=array();
10133
 
10134
		#取得當前執行的函數名稱
10135
		$result["function"]=__FUNCTION__;
10136
 
10137
		#涵式說明:
10138
		#判斷當前環境為web還是cmd
10139
		#回傳結果:
10140
		#$result,"web"或"cmd"
10141
		if(csInformation::getEnv()==="web"){
10142
 
10143
			#設置執行失敗
10144
			$result["status"]="false";
10145
 
10146
			#設置執行錯誤訊息
10147
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
10148
 
10149
			#回傳結果
10150
			return $result;
10151
 
10152
			}#if end
10153
 
10154
		#取得參數
10155
		$result["argu"]=$conf;
10156
 
10157
		#如果 $conf 不為陣列
10158
		if(gettype($conf)!="array"){
10159
 
10160
			#設置執行失敗
10161
			$result["status"]="false";
10162
 
10163
			#設置執行錯誤訊息
10164
			$result["error"][]="\$conf變數須為陣列形態";
10165
 
10166
			#如果傳入的參數為 null
10167
			if($conf==null){
10168
 
10169
				#設置執行錯誤訊息
10170
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
10171
 
10172
				}#if end
10173
 
10174
			#回傳結果
10175
			return $result;
10176
 
10177
			}#if end
10178
 
10179
		#檢查參數
10180
		#函式說明:
10181
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
10182
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10183
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
10184
		#$result["function"],當前執行的函式名稱.
10185
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
10186
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
10187
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
10188
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
10189
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
10190
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
10191
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
10192
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
10193
		#必填寫的參數:
10194
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
10195
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
10196
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
10197
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu");
10198
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
10199
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
10200
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
10201
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
10202
		#可以省略的參數:
10203
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
10204
		#$conf["canBeEmptyString"]="false";
10205
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
10206
		#$conf["canNotBeEmpty"]=array();
10207
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
10208
		#$conf["canBeEmpty"]=array();
10209
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
10210
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
10211
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
10212
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("listenIp","listenPort","wsMode","processFuncs");
10213
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
10214
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array");
10215
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
10216
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",null,"false",null);
10217
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
10218
		#$conf["arrayCountEqualCheck"][]=array();
10219
		#參考資料來源:
10220
		#array_keys=>http://php.net/manual/en/function.array-keys.php
10221
		#建議:
10222
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
10223
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
10224
		unset($conf["variableCheck::checkArguments"]);
10225
 
10226
		#如果檢查參數失敗
10227
		if($checkArguments["status"]==="false"){
10228
 
10229
			#設置執行失敗
10230
			$result["status"]="false";
10231
 
10232
			#設置執行錯誤訊息
10233
			$result["error"]=$checkArguments;
10234
 
10235
			#回傳結果
10236
			return $result;
10237
 
10238
			}#if end
10239
 
10240
		#如果檢查參數不通過
10241
		if($checkArguments["passed"]==="false"){
10242
 
10243
			#設置執行失敗
10244
			$result["status"]="false";
10245
 
10246
			#設置執行錯誤訊息
10247
			$result["error"]=$checkArguments;
10248
 
10249
			#回傳結果
10250
			return $result;
10251
 
10252
			}#if end		
10253
 
10254
		#如果 $conf["listenPort"] 不存在
10255
		if(!isset($conf["listenPort"])){
10256
 
10257
			#用nmap掃port
10258
			#函式說明:
10259
			#掃port的程式
10260
			#回傳結果:
10261
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10262
			#$result["error"],錯誤訊息.
10263
			#$result["function"],當前執行的函數名稱.
10264
			#$result["argu"],使用的參數.
10265
			#$result["content"],掃好可能可以使用的port資訊.
10266
			#必填參數
10267
			#無:
10268
			#可省略參數:
10269
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10270
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10271
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10272
			#$conf["-Pn"]="false";
10273
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10274
			unset($conf["cmd::nmap"]);
10275
 
10276
			#如果掃port失敗
10277
			if($nmap["status"]==="false"){
10278
 
10279
				#設置執行失敗
10280
				$result["status"]="false";
10281
 
10282
				#設置執行錯誤訊息
10283
				$result["error"]=$nmap;
10284
 
10285
				#回傳結果
10286
				return $result;
10287
 
10288
				}#if end
10289
 
10290
			#如果有掃到port
10291
			if(count($nmap["content"])>0){
10292
 
10293
				#找最大的port
10294
				#涵式說明:
10295
				#找最大值,結果會回傳最大值.
10296
				#回傳的結果:
10297
				#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10298
				#$result["error"],錯誤訊息陣列.
10299
				#$result["function"],當前執行的函數名稱.
10300
				#$result["key"],最大值原先的key.
10301
				#$result["value"],最大值的數字.
10302
				#必填的參數:
10303
				$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10304
				$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10305
				unset($conf["math::getMaxValue"]);
10306
 
10307
				#如果找最大port失敗
10308
				if($getMaxValue["status"]==="false"){
10309
 
10310
					#設置執行失敗
10311
					$result["status"]="false";
10312
 
10313
					#設置執行錯誤訊息
10314
					$result["error"]=$getMaxValue;
10315
 
10316
					#回傳結果
10317
					return $result;
10318
 
10319
					}#if end
10320
 
10321
				#設置 $conf["listenPort"] 為最大 port+1
10322
				$conf["listenPort"]=$getMaxValue["value"]+1;
10323
 
10324
				#如果port小於4000,會無法讓nmap偵測到有使用
10325
				if($conf["listenPort"]<4000){
10326
 
10327
					#設為4000
10328
					$conf["listenPort"]="4000";
10329
 
10330
					}#if end
10331
 
10332
				}#if end	
10333
 
10334
			}#if end
10335
 
10336
		#反之
10337
		else{
10338
 
10339
			#用nmap掃port
10340
			#函式說明:
10341
			#掃port的程式
10342
			#回傳結果:
10343
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10344
			#$result["error"],錯誤訊息.
10345
			#$result["function"],當前執行的函數名稱.
10346
			#$result["argu"],使用的參數.
10347
			#$result["content"],掃好可能可以使用的port資訊.
10348
			#必填參數
10349
			#無:
10350
			#可省略參數:
10351
			#$conf["target"],字串,要掃描的主機,預設為"127.0.0.1",
10352
			$conf["cmd::nmap"]["target"]=$conf["listenIp"];
10353
			#$conf["-Pn"],字串,是否要啟用避免ping不到就會掃port失敗的功能,預設為"false".
10354
			#$conf["-Pn"]="false";
10355
			#$conf["fileArgu"],字串,變數__FILE__的內容.
10356
			$conf["cmd::nmap"]["fileArgu"]=$conf["fileArgu"];
10357
			$nmap=cmd::nmap($conf["cmd::nmap"]);
10358
			unset($conf["cmd::nmap"]);
10359
 
10360
			#如果掃port失敗
10361
			if($nmap["status"]==="false"){
10362
 
10363
				#設置執行失敗
10364
				$result["status"]="false";
10365
 
10366
				#設置執行錯誤訊息
10367
				$result["error"]=$nmap;
10368
 
10369
				#回傳結果
10370
				return $result;
10371
 
10372
				}#if end
10373
 
10374
			#如果有掃到port
10375
			if(count($nmap["content"])>0){
10376
 
10377
				#如果要用來建立socket的port已被使用
10378
				if(in_array($conf["listenPort"],$nmap["content"])){
10379
 
10380
					#找最大的port
10381
					#涵式說明:
10382
					#找最大值,結果會回傳最大值.
10383
					#回傳的結果:
10384
					#$result["status"],執行是否正常,"true"為正常,"false"為不正常.
10385
					#$result["error"],錯誤訊息陣列.
10386
					#$result["function"],當前執行的函數名稱.
10387
					#$result["key"],最大值原先的key.
10388
					#$result["value"],最大值的數字.
10389
					#必填的參數:
10390
					$conf["math::getMaxValue"]["rawDataArray"]=$nmap["content"];#爲原始數據
10391
					$getMaxValue=math::getMaxValue($conf["math::getMaxValue"]);
10392
					unset($conf["math::getMaxValue"]);
10393
 
10394
					#如果找最大port失敗
10395
					if($getMaxValue["status"]==="false"){
10396
 
10397
						#設置執行失敗
10398
						$result["status"]="false";
10399
 
10400
						#設置執行錯誤訊息
10401
						$result["error"]=$getMaxValue;
10402
 
10403
						#回傳結果
10404
						return $result;
10405
 
10406
						}#if end
10407
 
10408
					#設置 $conf["listenPort"] 為最大 port+1
10409
					$conf["listenPort"]=$getMaxValue["value"]+1;
10410
 
10411
					#如果port小於4000,會無法讓nmap偵測到有使用
10412
					if($conf["listenPort"]<4000){
10413
 
10414
						#設為4000
10415
						$conf["listenPort"]="4000";
10416
 
10417
						}#if end
10418
 
10419
					}#if end
10420
 
10421
				}#if end
10422
 
10423
			}#else end
10424
 
10425
		#回報任何錯誤
10426
		#error_reporting(E_ALL);
10427
 
10428
		/* Allow the script to hang around waiting for connections. */
10429
		set_time_limit(0);
10430
 
10431
		/* Turn on implicit output flushing so we see what we're getting as it comes in. */
10432
		#ob_implicit_flush();
10433
 
10434
		#設定要listen的主機ip
10435
		$address = $conf["listenIp"];
10436
 
10437
		#設定要listen的port
10438
		$port = $conf["listenPort"];
10439
 
10440
		#重複做,讓socket服務不會結束.
10441
		do{
10442
 
10443
			#如果建立 socket 失敗
10444
			if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false){
10445
 
10446
				#印出錯誤訊息
10447
				echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
10448
 
10449
				}#if end
10450
 
10451
			#設置不等待連線與訊息的到來,變成不會卡位
10452
			socket_set_nonblock($sock);
10453
 
10454
			#SOL_SOCKET => socket level
10455
			#SO_REUSEADDR => Reports whether local addresses can be reused. 
10456
			socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
10457
 
10458
			#如果 Binds a name to a socket 失敗
10459
			if (@socket_bind($sock, $address, $port) === false){
10460
 
10461
				#儲存錯誤訊息
10462
				$error=socket_strerror(socket_last_error($sock));
10463
 
10464
				#印出錯誤訊息
10465
				echo "socket_bind() failed: reason: " .$error. PHP_EOL;
10466
 
10467
				#判斷錯誤訊息的是否有 "Address already in use"
10468
				#函式說明:
10469
				#檢查字串裡面有無指定的關鍵字
10470
				#回傳的結果:
10471
				#$result["status"],"true"代表執行成功,"false"代表執行失敗。
10472
				#$result["error"],錯誤訊息
10473
				#$result["function"],當前執行的函數名稱.
10474
				#$result["founded"],是否找到關鍵字,"true"代表有找到關鍵字;"false"代表沒有找到關鍵字。
10475
				#$result["keyWordCount"],找到的關鍵字數量.
10476
				#必填的參數:
10477
				$conf["search::findKeyWord"]["keyWord"]="Address already in use";#想要搜尋的關鍵字
10478
				$conf["search::findKeyWord"]["string"]=$error;#要被搜尋的字串內容
10479
				#可省略的參數:
10480
				#$conf["completeEqual"]="true";#是否內容要完全符合,不能多出任何不符合的內容,預設為不需要完全符合。
10481
				$findKeyWord=search::findKeyWord($conf["search::findKeyWord"]);
10482
				unset($conf["search::findKeyWord"]);
10483
 
10484
				#如果解析錯誤訊息失敗
10485
				if($findKeyWord["status"]==="false"){
10486
 
10487
					#設置執行失敗
10488
					$result["status"]="false";
10489
 
10490
					#設置執行錯誤訊息
10491
					$result["error"]=$getMeetConditionsString;
10492
 
10493
					#回傳結果
10494
					return $result;
10495
 
10496
					}#if end
10497
 
10498
				#如果錯誤原因為socket的port已經被使用了.
10499
				if($findKeyWord["founded"]==="true"){
10500
 
10501
					#port加1
10502
					$port++;
10503
 
10504
					#再次建立socket服務
10505
					continue;
10506
 
10507
					}#if end
10508
 
10509
				#反之
10510
				else{
10511
 
10512
					#結束程式
10513
					exit;
10514
 
10515
					}#else 
10516
 
10517
				}#if end
10518
 
10519
			#如果 listen socket 經過嘗試5次後仍然失敗
10520
			if (socket_listen($sock, 5) === false) {
10521
 
10522
				#印出錯誤訊息
10523
				echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;
10524
 
10525
				}#if end
10526
 
10527
			#初始化儲存已經連線到 socket service 的服務
10528
			$connections=array();
10529
 
10530
			#提示 listen 的 ip 與 port
10531
			echo "Listen to:".$address.":".$port.PHP_EOL;
10532
 
10533
			#重複做,等待別人連線.
10534
			do{
10535
 
10536
				#初始化儲存有需要處理的socket連線
10537
				$read = array();
10538
 
10539
				#初始化一開始建立的socket為要處理的項目
10540
				$read[] = $sock;
10541
 
10542
				#有幾個連線就執行幾次
10543
				foreach($connections as $conForSockSelect){
10544
 
10545
					#產生要合併的陣列
10546
					$arrayToMerage=array($conForSockSelect["connect"]);
10547
 
10548
					#合併陣列
10549
					$read = array_merge($read,$arrayToMerage);
10550
 
10551
					}#foreach end
10552
 
10553
				#從socket物件陣列($read)裡面取出有需要處理連線的socket物件.
10554
				#Set up a blocking call to socket_select
10555
				$write=array();
10556
				$except=array();
10557
				$tv_sec = 1;
10558
				if(socket_select($read, $write, $except, $tv_sec) < 1){
10559
 
10560
					#沒有事情發生
10561
					echo ".";
10562
 
10563
					#函式說明:
10564
					#加密 handshake 後要傳送的訊息 
10565
					#回傳結果:
10566
					#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
10567
					#$result["error"],執行不正常結束的錯訊息陣列.
10568
					#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
10569
					#$result["argu"],陣列,使用的參數.
10570
					#必填參數:
10571
					#$conf["text"],字串,要加密的訊息.
10572
					$conf["webSock::encode"]["text"]=""; 
10573
					#可省略參數:
10574
					#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
10575
					$conf["webSock::encode"]["ping"]="true";
10576
					#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
10577
					#$conf["frames"]=array();
10578
					#參考資料:
10579
					#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
10580
					#備註:
10581
					#無.
10582
					$encode=webSock::encode($conf["webSock::encode"]);
10583
					unset($conf["webSock::encode"]);
10584
 
10585
					#debug
10586
					#var_dump(__LINE__,$encode);
10587
 
10588
					#如果執行失敗
10589
					if($encode["status"]==="false"){
10590
 
10591
						#設置執行失敗
10592
						$result["status"]="false";
10593
 
10594
						#設置執行錯誤訊息
10595
						$result["error"]=$encode;
10596
 
10597
						#回傳結果
10598
						return $result;
10599
 
10600
						}#if end
10601
 
10602
					#針對每個連線的 client
10603
					foreach($connections as $client){
10604
 
10605
						#如果有 last ping time
10606
						if(isset($client["lastPongTime"])){
10607
 
10608
							#如果小於5秒沒有收到pong
10609
							if(time()-$client["lastPongTime"]<5){
10610
 
10611
								#看下一個連線
10612
								continue;
10613
 
10614
								}#if end
10615
 
10616
							}#if end
10617
 
10618
						#取得用戶socket
10619
						$clientSock=$client["connect"];
10620
 
10621
						#傳送ping給client
10622
						$socket_write=socket_write($clientSock, $encode["content"][0], strlen($encode["content"][0]));
10623
 
10624
						#debug
10625
						#var_dump(__LINE__,"send ping",$socket_write,socket_strerror(socket_last_error($clientSock)));
10626
 
10627
						}#foreach end
10628
 
10629
					#下一輪
10630
					continue;
10631
 
10632
					}#if end
10633
 
10634
				#有事情發生
10635
				echo "something happen".PHP_EOL;
10636
 
10637
				#如果有socket要處理
10638
				if(in_array($sock,$read)){
10639
 
10640
					#如果有接收到 socket 連線
10641
					if (($msgsock = socket_accept($sock)) !== false) {
10642
 
10643
						#初始化不是既有的 sock
10644
						$existSock=false;
10645
 
10646
						#尋找是哪個 socket
10647
						for($i=0;$i<count($connections);$i++){
10648
 
10649
							#如果是既有的 sock
10650
							if($connections[$i]["connect"]===$msgsock){
10651
 
10652
								#設置是既有的 sock
10653
								$existSock=true;
10654
 
10655
								}#if end
10656
 
10657
							}#for end
10658
 
10659
						#如果該 socket 是新的
10660
						if(!$existSock){
10661
 
10662
							#重複做
10663
							do{
10664
 
10665
								#亂數產生連線id
10666
								#涵式說明:
10667
								#建立以圖片(PNG格式)呈現的驗證碼.
10668
								#回傳的解果:
10669
								#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
10670
								#$result["error"],錯誤訊息.
10671
								#$result["function"],檔前執行的函數名稱.
10672
								#$result["randNumberWord"],傳驗證碼的內容.
10673
								#$result["imgAddress"],圖片的位置與名稱.
10674
								#必填的參數:
10675
								#$conf["imgAddressAndName"],字串,爲驗證碼圖片儲存的位置與名稱,副檔名程式會自動產生
10676
								$conf["authenticate::validationCode"]["imgAddressAndName"]="no used!";
10677
								#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
10678
								$conf["authenticate::validationCode"]["fileArgu"]=$conf["fileArgu"];
10679
								#可省略的參數:
10680
								#$conf["num"],字串,爲驗證碼的位數,請輸入阿拉伯數字,預設為"8"位數.
10681
								#$conf["num"]="8";
10682
								#$conf["disableImg"],字串,是否要取消驗證碼圖片的輸出,"true"為要取消,預設為"false"為不取消
10683
								$conf["authenticate::validationCode"]["disableImg"]="true";
10684
								#$conf["imgToData"],字串,預設為"true"代表將圖片轉存成base64圖片,並將原始圖片移除;反之為"false"
10685
								#$conf["authenticate::validationCode"]["imgToData"]="true";
10686
								$validationCode=authenticate::validationCode($conf["authenticate::validationCode"]);
10687
								unset($conf["authenticate::validationCode"]);
10688
 
10689
								#如果產生亂數失敗
10690
								if($validationCode["status"]==="false"){
10691
 
10692
									#設置執行失敗
10693
									$result["status"]="false";
10694
 
10695
									#設置執行錯誤訊息
10696
									$result["error"]=$validationCode;
10697
 
10698
									#回傳結果
10699
									return $result;
10700
 
10701
									}#if end
10702
 
10703
								#如果不存在既有的連線資訊
10704
								if(count($connections)<1){
10705
 
10706
									#跳出迴圈
10707
									break;
10708
 
10709
									}#if end
10710
 
10711
								#初始化連線id的陣列
10712
								$idArray=array();
10713
 
10714
								#針對既有的連線
10715
								foreach($connections as $exist_conn){
10716
 
10717
									#儲存連線id
10718
									$idArray[]=$exist_conn["id"];
10719
 
10720
									}#foreach end
10721
 
10722
								}#do end
10723
 
10724
							#檢查id有無重複
10725
							while(in_array($validationCode["randNumberWord"],$idArray));
10726
 
10727
							#如果不是 ws 模式			
10728
							if($conf["wsMode"]==="false"){
10729
 
10730
								#儲存連線到陣列裡面
10731
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array());
10732
 
10733
								}#if end
10734
 
10735
							#如果是 ws 模式
10736
							if($conf["wsMode"]==="true"){
10737
 
10738
								#儲存連線到陣列裡面
10739
								$connections[]=array("connect"=>$msgsock,"buf"=>"","id"=>$validationCode["randNumberWord"],"talkTo"=>array(),"handshaked"=>"false","unmask"=>"false","userAgent"=>"false","3rn"=>0,"receivedMsgFromServer"=>array());
10740
 
10741
								}#if end
10742
 
10743
							#debug,提示 Server 給予的新 Id
10744
							echo "new connection:".PHP_EOL;
10745
 
10746
							#初始化連線後要回傳的訊息
10747
							$msg="";
10748
 
10749
							#如果不是 ws 模式
10750
							if($conf["wsMode"]!=="true"){
10751
 
10752
								#提示client連上線後得到的訊息
10753
								$msg = $msg.PHP_EOL."Welcome to the PHP Test Server.".PHP_EOL;
10754
								$msg = $msg."To quit, type 'quit'. To shut down the server type 'shutdown'.".PHP_EOL;
10755
								socket_write($msgsock, $msg, strlen($msg));
10756
 
10757
								}#if end
10758
 
10759
							}#if end
10760
 
10761
						}#if end
10762
 
10763
					}#if end
10764
 
10765
				#重新排序 $connections
10766
				#函式說明:
10767
				#將陣列的key重新排序,然後回傳,以便後續存取,也可以指定key的內容,但一定要跟元素數量相同。
10768
				#回傳的解果:
10769
				#$result["status"],執行是否成功,"true"代表成功,"false"代表失敗.
10770
				#$result["error"],執行錯誤的訊息.
10771
				#$result["function"],當前執行的函數名稱.
10772
				#$result["dataContent"],儲存陣列元素的內容.
10773
				#若指定了key的名稱,則 $result["dataContent"] 會變成 $result["dataContent"]["指定的key名稱"]
10774
				#$result["dataCount"],儲存陣列元素的數量。
10775
				#必填的參數:
10776
				$conf["arrays::createV2"]["arrayContent"]=$connections;#陣列變數
10777
				#可省略的參數:
10778
				#$conf["specifiesKeyArray"]=array();#指定key的名稱,須與$conf["arrayContent"]的元素數量相同
10779
				$createV2=arrays::createV2($conf["arrays::createV2"]);
10780
				unset($conf["arrays::createV2"]);
10781
 
10782
				#如果重新排序失敗
10783
				if($createV2["status"]==="false"){
10784
 
10785
					#設置執行失敗
10786
					$result["status"]="false";
10787
 
10788
					#設置執行錯誤訊息
10789
					$result["error"]=$createV2;
10790
 
10791
					#回傳結果
10792
					return $result;
10793
 
10794
					}#if end
10795
 
10796
				#取得重新排序好的陣列
10797
				$connections=$createV2["dataContent"];
10798
 
10799
				#依據每個 client 的連線
10800
				foreach($connections as $conIndex => $con){
10801
 
10802
					#如果有要處理的socket連線項目
10803
					if(in_array($con["connect"], $read)){
10804
 
10805
						#如果不存在 handshaked
10806
						if(!isset($con["handshaked"])){
10807
 
10808
							#預設為 "false"
10809
							$con["handshaked"]="false";
10810
 
10811
							}#if end
10812
 
10813
						#如果有 handshaked
10814
						if($con["handshaked"]==="true"){
10815
 
10816
							#讀取內容					
10817
							$buf = @socket_read($con["connect"], 2048, PHP_BINARY_READ);
10818
 
10819
							#設置要 unmask
10820
							$connections[$conIndex]["unmask"]="true";
10821
 
10822
							}#if end
10823
 
10824
						#反之
10825
						else{
10826
 
10827
							#讀取內容
10828
							$buf = @socket_read($con["connect"], 2048, PHP_NORMAL_READ);
10829
 
10830
							}#else end
10831
 
10832
						#如果讀取出錯
10833
						if($buf===false){
10834
 
10835
							#印出錯誤訊息
10836
							echo "socket_recv() failed: reason: " . socket_strerror(socket_last_error($con["connect"])) . PHP_EOL;
10837
 
10838
							#移除該連線的資料
10839
							unset($connections[$conIndex]);	
10840
 
10841
							#跳到下一輪
10842
							continue;
10843
 
10844
							}#if end
10845
 
10846
						#如果收到的資料長度為 0 bytes
10847
						if($buf===""){
10848
 
10849
							#關閉 socket msg
10850
							socket_close($con["connect"]);	
10851
 
10852
							#移除該連線的資料
10853
							unset($connections[$conIndex]);
10854
 
10855
							#跳到下一輪
10856
							continue;
10857
 
10858
							}#if end
10859
 
10860
						#印出接受的非換行符號內容
10861
						if($buf!==PHP_EOL){
10862
 
10863
							#debug
10864
							echo "received:".$buf.PHP_EOL;
10865
 
10866
							}#if end
10867
 
10868
						#如果無 handshaked
10869
						if($con["handshaked"]!=="true"){
10870
 
10871
							#清除換行字元
10872
							$buf=trim($buf);
10873
 
10874
							}#if end
10875
 
10876
						#web socket mode
10877
						if($conf["wsMode"]==="true"){
10878
 
10879
							#如果不需要 unmask
10880
							if($connections[$conIndex]["unmask"]==="false"){
10881
 
10882
								#提示還不用 unmask
10883
								echo "don't need unmask now".PHP_EOL;
10884
 
10885
								#重新計數 \r\n
10886
								$connections[$conIndex]["3rn"]=0;
10887
 
10888
								}#if end
10889
 
10890
							}#if end
10891
 
10892
						#如果有內容(不是換行符號)
10893
						$st=trim($buf);
10894
 
10895
						#如果是 ws 模式
10896
						if($conf["wsMode"]==="true"){
10897
 
10898
							#如果尚未 handshake
10899
							if($connections[$conIndex]["handshaked"]==="false"){
10900
 
10901
								#提示 server 在檢查 handshake 用的 key 是否存在.
10902
								echo "check Sec-WebSocket-Key ..".PHP_EOL;
10903
 
10904
								#handshake
10905
								#如果收到的內容$buf含有 Sec-WebSocket-Key: 字串開頭,擷取後面的內容存到$matchs裡面.
10906
								if(preg_match("/Sec-WebSocket-Key: (.*)/",$buf,$matchs)){
10907
 
10908
									#提示serve在handshake
10909
									echo "do handshake...".PHP_EOL.PHP_EOL;
10910
 
10911
									#handshake
10912
									$key = $matchs[1].'258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
10913
									$key =  base64_encode(sha1($key, true)); 
10914
 
10915
									#設置 handshake 的 header
10916
									$headers = 
10917
									"HTTP/1.1 101 Switching Protocols".PHP_EOL.
10918
									"Upgrade: websocket".PHP_EOL.
10919
									"Connection: Upgrade".PHP_EOL.
10920
									"Sec-WebSocket-Accept: ".$key.PHP_EOL.
10921
									"X-Powered-By: qbpwcf".PHP_EOL.
10922
									PHP_EOL;
10923
 
10924
									#傳送header給client
10925
									socket_write($con["connect"], $headers);
10926
 
10927
									#儲存server傳送給client的訊息
10928
									#$connections[$conIndex]["receivedMsgFromServer"][]=$headers;
10929
 
10930
									#提示serve handshake 完畢
10931
									echo "handshak done...".PHP_EOL;
10932
 
10933
									#設置已經 handshake
10934
									$connections[$conIndex]["handshaked"]="true";
10935
 
10936
									}#if end
10937
 
10938
								}#if end
10939
 
10940
							}#if end
10941
 
10942
						#如果是 ws 模式
10943
						if($conf["wsMode"]==="true"){
10944
 
10945
							#如果尚未 handshake 過
10946
							if($connections[$conIndex]["handshaked"]==="false"){
10947
 
10948
								#跳過
10949
								continue;
10950
 
10951
								}#if end
10952
 
10953
							#如果還不用要 unmask	
10954
							if($connections[$conIndex]["unmask"]==="false"){
10955
 
10956
								#跳過
10957
								continue;
10958
 
10959
								}#if end
10960
 
10961
							}#if end
10962
 
10963
						#如果是 ws 模式
10964
						if($conf["wsMode"]==="true"){
10965
 
10966
							#debug
10967
							#var_dump(__LINE__,$connections[$conIndex]);
10968
 
10969
							#如果已經 handshake 過
10970
							if($connections[$conIndex]["handshaked"]==="true"){
10971
 
10972
								#如果要 unmask	
10973
								if($connections[$conIndex]["unmask"]==="true"){
10974
 
10975
									#如果收到的訊息不為空
10976
									if(!empty($buf)){
10977
 
10978
										echo "start unmask...".PHP_EOL;
10979
 
10980
										#debug
10981
										#var_dump(__LINE__,$buf);
10982
 
10983
										#解密 $buf
10984
										#回傳結果:
10985
										#$result["function"],當前函式的名稱.
10986
										#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
10987
										#$result["content"],unmask後的內容.
10988
										#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong.
10989
										#$result["error"],錯誤訊息陣列.
10990
										$conf["self::unmask"]["payload"]=$buf;
10991
										#$conf["self::unmask"]["debug"]="true";
10992
										$buf=webSock::unmask($conf["self::unmask"]);
10993
										unset($conf["self::unmask"]);
10994
 
10995
										#如果執行失敗
10996
										if($buf["status"]==="false"){
10997
 
10998
											#印出結果
10999
											var_dump($buf);
11000
 
11001
											#結束執行
11002
											exit;
11003
 
11004
											}#if end
11005
 
11006
										#如果是 ping 的回應 pong
11007
										if($buf["type"]==="pong"){
11008
 
11009
											#提示收到 pong
11010
											echo "got pong".PHP_EOL;
11011
 
11012
											#更新的連線的 last pong time
11013
											$connections[$conIndex]["lastPongTime"]=time();
11014
 
11015
											#換處理下一則訊息
11016
											continue;
11017
 
11018
											}#if end
11019
 
11020
										#如果不是 web socket frame
11021
										if($buf["type"]==="invalid"){
11022
 
11023
											#提示收到非 web socket frame
11024
											echo "not web socket frame".PHP_EOL;
11025
 
11026
											#debug
11027
											#var_dump(__LINE__,$buf);
11028
 
11029
											#換處理下一則訊息
11030
											continue;
11031
 
11032
											}#if end
11033
 
11034
										#取得umask後的內容
11035
										$buf=$buf["content"];
11036
 
11037
										#提示 unmask 結束
11038
										echo "end unmask()".PHP_EOL;
11039
 
11040
										#提示 web socket server 收到訊息的長度(bytes)
11041
										echo "Server receviced plain content(".strlen($buf)."):".PHP_EOL;
11042
 
11043
										#提示 web socket server 收到的訊息內容
11044
										echo $buf.PHP_EOL;
11045
 
11046
										}#if end
11047
 
11048
									}#if end
11049
 
11050
								}#if end
11051
 
11052
							}#if end
11053
 
11054
						#如果收到的是 id?
11055
						if($buf === 'id?'){
11056
 
11057
							#設置要回傳的訊息
11058
							$talkback=$connections[$conIndex]["id"];
11059
 
11060
							#debug
11061
							#var_dump(__LINE__,$talkback);
11062
 
11063
							#json encode 要回傳的訊息
11064
							$talkback=json_encode($talkback);
11065
 
11066
							#debug
11067
							#var_dump(__LINE__,$talkback);
11068
 
11069
							#如果是 ws 模式
11070
							if($conf["wsMode"]==="true"){
11071
 
11072
								#如果已經 handshake 過
11073
								if($connections[$conIndex]["handshaked"]==="true"){
11074
 
11075
									#如果要 unmask	
11076
									if($connections[$conIndex]["unmask"]==="true"){
11077
 
11078
										#函式說明:
11079
										#加密 handshake 後要傳送的訊息 
11080
										#回傳結果:
11081
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11082
										#$result["error"],執行不正常結束的錯訊息陣列.
11083
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11084
										#$result["argu"],陣列,使用的參數.
11085
										#必填參數:
11086
										#$conf["text"],字串,要加密的訊息.
11087
										$conf["webSock::encode"]["text"]=$talkback; 
11088
										#可省略參數:
11089
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11090
										#$conf["payloadIsBin"]="false";
11091
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11092
										#$conf["ping"]="false";
11093
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11094
										#$conf["pong"]="false";
11095
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11096
										#$conf["frames"]=array();
11097
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11098
										#$conf["mask"]="false";
11099
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11100
										#$conf["debug"]="false";
11101
										#參考資料:
11102
										#無.
11103
										#備註:
11104
										#目前$conf["text"]長度超過125會出錯.
11105
										$talkback=webSock::encode($conf["webSock::encode"]);
11106
										unset($conf["webSock::encode"]);
11107
 
11108
										#如果執行失敗
11109
										if($talkback["status"]==="false"){
11110
 
11111
											#印出結果
11112
											var_dump($talkback);
11113
 
11114
											#結束執行
11115
											exit;
11116
 
11117
											}#if end
11118
 
11119
										#debug
11120
										#var_dump(__LINE__,$talkback);
11121
 
11122
										}#if end
11123
 
11124
									}#if end
11125
 
11126
								}#if end
11127
 
11128
							#反之不為 web socket 訊息
11129
							else{
11130
 
11131
								#儲存成只有一個訊息
11132
								$talkback["content"][]=$talkback;
11133
 
11134
								}#else
11135
 
11136
							#針對每個訊息的分段
11137
							foreach($talkback["content"] as $msg){
11138
 
11139
								#debug
11140
								var_dump(__LINE__,$msg);
11141
 
11142
								#回傳訊息
11143
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11144
 
11145
								#debug
11146
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11147
 
11148
								}#foreach end
11149
 
11150
							#跳到下一輪
11151
							continue;
11152
 
11153
							}#if end
11154
 
11155
						#如果收到的是 ids?
11156
						if($buf === 'ids?'){
11157
 
11158
							#設置要回傳的訊息
11159
							$talkback=array();
11160
 
11161
							#針對每個連線
11162
							foreach($connections as $conIndex_ids => $con_ids){
11163
 
11164
								#如果不是自己							
11165
								if($con_ids["connect"]!==$connections[$conIndex]["connect"]){
11166
 
11167
									#記錄其他人的id
11168
									$talkback[]=$con_ids["id"];
11169
 
11170
									}#if end
11171
 
11172
								}#foreach end
11173
 
11174
							#json encode要回傳的id陣列	
11175
							$talkback=json_encode($talkback);	
11176
 
11177
							#如果是 ws 模式
11178
							if($conf["wsMode"]==="true"){
11179
 
11180
								#如果已經 handshake 過
11181
								if($connections[$conIndex]["handshaked"]==="true"){
11182
 
11183
									#如果要 unmask	
11184
									if($connections[$conIndex]["unmask"]==="true"){
11185
 
11186
										#函式說明:
11187
										#加密 handshake 後要傳送的訊息 
11188
										#回傳結果:
11189
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11190
										#$result["error"],執行不正常結束的錯訊息陣列.
11191
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11192
										#$result["argu"],陣列,使用的參數.
11193
										#必填參數:
11194
										#$conf["text"],字串,要加密的訊息.
11195
										$conf["webSock::encode"]["text"]=$talkback; 
11196
										#可省略參數:
11197
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11198
										#$conf["payloadIsBin"]="false";
11199
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11200
										#$conf["ping"]="false";
11201
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11202
										#$conf["pong"]="false";
11203
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11204
										#$conf["frames"]=array();
11205
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11206
										#$conf["mask"]="false";
11207
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11208
										#$conf["debug"]="false";
11209
										#參考資料:
11210
										#無.
11211
										#備註:
11212
										#目前$conf["text"]長度超過125會出錯.
11213
										$talkback=webSock::encode($conf["webSock::encode"]);
11214
										unset($conf["webSock::encode"]);
11215
 
11216
										#如果執行失敗
11217
										if($talkback["status"]==="false"){
11218
 
11219
											#印出結果
11220
											var_dump($talkback);
11221
 
11222
											#結束執行
11223
											exit;
11224
 
11225
											}#if end
11226
 
11227
										#debug
11228
										#var_dump(__LINE__,$talkback);
11229
 
11230
										}#if end
11231
 
11232
									}#if end
11233
 
11234
								}#if end
11235
 
11236
							#反之不為 web socket 訊息
11237
							else{
11238
 
11239
								#儲存成只有一個訊息
11240
								$talkback["content"][]=$talkback;
11241
 
11242
								}#else
11243
 
11244
							#針對每個訊息的分段
11245
							foreach($talkback["content"] as $msg){
11246
 
11247
								#回傳訊息
11248
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11249
 
11250
								#debug
11251
								var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11252
 
11253
								}#foreach end
11254
 
11255
							#跳到下一輪
11256
							continue;
11257
 
11258
							}#if end
11259
 
11260
						#如果收到 "talkTo?"
11261
						if($buf==="talkTo?"){
11262
 
11263
							#初始化要講話的id陣列
11264
							$talkback=array();
11265
 
11266
							#有幾個要講話的人就執行幾次
11267
							foreach($connections[$conIndex]["talkTo"] as $to){
11268
 
11269
								#串街要講話的人
11270
								$talkback[]=$to;
11271
 
11272
								}#foreach end
11273
 
11274
							#設置要回傳的訊息
11275
							$talkback=json_encode($talkback).PHP_EOL;
11276
 
11277
							#如果是 ws 模式
11278
							if($conf["wsMode"]==="true"){
11279
 
11280
								#如果已經 handshake 過
11281
								if($connections[$conIndex]["handshaked"]==="true"){
11282
 
11283
									#如果要 unmask	
11284
									if($connections[$conIndex]["unmask"]==="true"){
11285
 
11286
										#函式說明:
11287
										#加密 handshake 後要傳送的訊息 
11288
										#回傳結果:
11289
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11290
										#$result["error"],執行不正常結束的錯訊息陣列.
11291
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11292
										#$result["argu"],陣列,使用的參數.
11293
										#必填參數:
11294
										#$conf["text"],字串,要加密的訊息.
11295
										$conf["webSock::encode"]["text"]=$talkback; 
11296
										#可省略參數:
11297
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11298
										#$conf["payloadIsBin"]="false";
11299
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11300
										#$conf["ping"]="false";
11301
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11302
										#$conf["pong"]="false";
11303
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11304
										#$conf["frames"]=array();
11305
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11306
										#$conf["mask"]="false";
11307
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11308
										#$conf["debug"]="false";
11309
										#參考資料:
11310
										#無.
11311
										#備註:
11312
										#目前$conf["text"]長度超過125會出錯.
11313
										$talkback=webSock::encode($conf["webSock::encode"]);
11314
										unset($conf["webSock::encode"]);
11315
 
11316
										#如果執行失敗
11317
										if($talkback["status"]==="false"){
11318
 
11319
											#印出結果
11320
											var_dump($talkback);
11321
 
11322
											#結束執行
11323
											exit;
11324
 
11325
											}#if end
11326
 
11327
										#debug
11328
										#var_dump(__LINE__,$talkback);
11329
 
11330
										}#if end
11331
 
11332
									}#if end
11333
 
11334
								}#if end
11335
 
11336
							#反之不為 web socket 訊息
11337
							else{
11338
 
11339
								#儲存成只有一個訊息
11340
								$talkback["content"][]=$talkback;
11341
 
11342
								}#else
11343
 
11344
							#針對每個訊息的分段
11345
							foreach($talkback["content"] as $msg){
11346
 
11347
								#回傳訊息
11348
								$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11349
 
11350
								#debug
11351
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11352
 
11353
								}#foreach end
11354
 
11355
							#跳到下一輪
11356
							continue;
11357
 
11358
							}#if end
11359
 
11360
						#如果收到的$buf長度大於 "talkTo:"
11361
						if(strlen($buf)>strlen("talkTo:")){
11362
 
11363
							#如果收到開頭為 "talkTo:"
11364
							#涵式說明:
11365
							#取得符合特定字首與字尾的字串
11366
							#回傳的結果:
11367
							#$result["status"],若爲"true"則代表執行正常;若爲"false"則代表執行失敗。
11368
							#$result["function"],當前執行的函數名稱.
11369
							#$result["error"],錯誤訊息陣列.
11370
							#$result["founded"],若為"true"則代表有找到符合字首條件的結果;若爲"false"則代表沒有找到。
11371
							#$result["returnString"],爲符合字首條件的字串內容。
11372
							#必填參數:
11373
							#$conf["checkString"],字串,要檢查的字串.
11374
							$conf["search::getMeetConditionsString"]["checkString"]=$buf;
11375
							#可省略參數:
11376
							#$conf["frontWord"],字串,用來檢查字首應該要有什麼字串,預設不指定.
11377
							$conf["search::getMeetConditionsString"]["frontWord"]="talkTo:";
11378
							#$conf["tailWord"],字串,用來檢查字尾應該要有什麼字串,預設不指定.
11379
							#$conf["tailWord"]="";
11380
							#參考資料:
11381
							#str_spilt(),可以將字串依照字母分割成一個個陣列字串。
11382
							$getMeetConditionsString=search::getMeetConditionsString($conf["search::getMeetConditionsString"]);
11383
							unset($conf["search::getMeetConditionsString"]);
11384
 
11385
							#如果選找前置字串 "talkTo:" 失敗
11386
							if($getMeetConditionsString["status"]==="false"){
11387
 
11388
								#設置執行失敗
11389
								$result["status"]="false";
11390
 
11391
								#設置執行錯誤訊息
11392
								$result["error"]=$getMeetConditionsString;
11393
 
11394
								#回傳結果
11395
								return $result;
11396
 
11397
								}#if end
11398
 
11399
							#如果存在 "talkTo:" 前置字串
11400
							if($getMeetConditionsString["founded"]==="true"){
11401
 
11402
								#用 "talkTo:" 分割 $buf
11403
								#涵式說明:
11404
								#將固定格式的字串分開,並回傳分開的結果。
11405
								#回傳結果:
11406
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11407
								#$result["error"],錯誤訊息陣列
11408
								#$result["function"],當前執行的函數名稱.
11409
								#$result["oriStr"],要分割的原始字串內容
11410
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
11411
								#$result["dataCounts"],爲總共分成幾段
11412
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
11413
								#必填的參數:
11414
								$conf["stringProcess::spiltString"]["stringIn"]=$buf;#要處理的字串。
11415
								$conf["stringProcess::spiltString"]["spiltSymbol"]="talkTo:";#爲以哪個符號作爲分割
11416
								#可省略參數:
11417
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
11418
								$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
11419
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
11420
								unset($conf["stringProcess::spiltString"]);
11421
 
11422
								#如果分割字串失敗
11423
								if($spiltString["status"]==="false"){
11424
 
11425
									#設置執行失敗
11426
									$result["status"]="false";
11427
 
11428
									#設置執行錯誤訊息
11429
									$result["error"]=$spiltString;
11430
 
11431
									#回傳結果
11432
									return $result;
11433
 
11434
									}#if end
11435
 
11436
								#如果剛好分割出一筆資料
11437
								if($spiltString["dataCounts"]===1){
11438
 
11439
									#取得自己的id
11440
									$myId=$connections[$conIndex]["id"];
11441
 
11442
									#取得講話對象的id
11443
									$toId=$spiltString["dataArray"][0];
11444
 
11445
									#設置對象不存在的識別
11446
									$targetExist=false;
11447
 
11448
									#設置通話對象的key
11449
									$targetKey="";
11450
 
11451
									#取得除了自己的id以外的所有連線
11452
									foreach($connections as $index=>$talkInfo){
11453
 
11454
										#除了自己的id
11455
										if($talkInfo["id"]!==$myId){
11456
 
11457
											#如果存在要對話的對象
11458
											if($talkInfo["id"]===$toId){
11459
 
11460
												#設置對象存在的識別
11461
												$targetExist=true;
11462
 
11463
												#通話對象的key
11464
												$targetKey=$index;
11465
 
11466
												}#if end
11467
 
11468
											}#if end
11469
 
11470
										}#for each end
11471
 
11472
									#如果通話對象存在
11473
									if($targetExist){
11474
 
11475
										#保存自己的通話對象
11476
										$connections[$conIndex]["talkTo"][]=$toId;
11477
 
11478
										#設置要給自己看的訊息
11479
										$talkback="您與 ".$toId." 展開對話";
11480
 
11481
										#json encode 要給自己看的訊息
11482
										$talkback=json_encode($talkback).PHP_EOL;
11483
 
11484
										#如果是 ws 模式
11485
										if($conf["wsMode"]==="true"){
11486
 
11487
											#如果已經 handshake 過
11488
											if($connections[$conIndex]["handshaked"]==="true"){
11489
 
11490
												#如果要 unmask	
11491
												if($connections[$conIndex]["unmask"]==="true"){
11492
 
11493
													#函式說明:
11494
													#加密 handshake 後要傳送的訊息 
11495
													#回傳結果:
11496
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11497
													#$result["error"],執行不正常結束的錯訊息陣列.
11498
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11499
													#$result["argu"],陣列,使用的參數.
11500
													#必填參數:
11501
													#$conf["text"],字串,要加密的訊息.
11502
													$conf["webSock::encode"]["text"]=$talkback; 
11503
													#可省略參數:
11504
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11505
													#$conf["payloadIsBin"]="false";
11506
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11507
													#$conf["ping"]="false";
11508
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11509
													#$conf["pong"]="false";
11510
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11511
													#$conf["frames"]=array();
11512
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11513
													#$conf["mask"]="false";
11514
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11515
													#$conf["debug"]="false";
11516
													#參考資料:
11517
													#無.
11518
													#備註:
11519
													#目前$conf["text"]長度超過125會出錯.
11520
													$talkback=webSock::encode($conf["webSock::encode"]);
11521
													unset($conf["webSock::encode"]);
11522
 
11523
													#如果執行失敗
11524
													if($talkback["status"]==="false"){
11525
 
11526
														#印出結果
11527
														var_dump($talkback);
11528
 
11529
														#結束執行
11530
														exit;
11531
 
11532
														}#if end
11533
 
11534
													#debug
11535
													#var_dump(__LINE__,$talkback);
11536
 
11537
													}#if end
11538
 
11539
												}#if end
11540
 
11541
											}#if end
11542
 
11543
										#反之不為 web socket 訊息
11544
										else{
11545
 
11546
											#儲存成只有一個訊息
11547
											$talkback["content"][]=$talkback;
11548
 
11549
											}#else
11550
 
11551
										#針對每個訊息的分段
11552
										foreach($talkback["content"] as $msg){
11553
 
11554
											#回傳訊息
11555
											$socket_write=socket_write($connections[$conIndex]["connect"], $msg, strlen($msg));
11556
 
11557
											#debug
11558
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11559
 
11560
											}#foreach end
11561
 
11562
										#讓對方可以跟自己對話
11563
										$connections[$targetKey]["talkTo"][]=$myId;
11564
 
11565
										#設置要給對方看的訊息
11566
										$talkback=$connections[$conIndex]["id"]." 與您展開對話";
11567
 
11568
										#json encode 設置要給對方看的訊息
11569
										$talkback=json_encode($talkback);
11570
 
11571
										#如果是 ws 模式
11572
										if($conf["wsMode"]==="true"){
11573
 
11574
											#如果已經 handshake 過
11575
											if($connections[$conIndex]["handshaked"]==="true"){
11576
 
11577
												#如果要 unmask	
11578
												if($connections[$conIndex]["unmask"]==="true"){
11579
 
11580
													#函式說明:
11581
													#加密 handshake 後要傳送的訊息 
11582
													#回傳結果:
11583
													#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11584
													#$result["error"],執行不正常結束的錯訊息陣列.
11585
													#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11586
													#$result["argu"],陣列,使用的參數.
11587
													#必填參數:
11588
													#$conf["text"],字串,要加密的訊息.
11589
													$conf["webSock::encode"]["text"]=$talkback; 
11590
													#可省略參數:
11591
													#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11592
													#$conf["payloadIsBin"]="false";
11593
													#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11594
													#$conf["ping"]="false";
11595
													#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11596
													#$conf["pong"]="false";
11597
													#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11598
													#$conf["frames"]=array();
11599
													#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11600
													#$conf["mask"]="false";
11601
													#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11602
													#$conf["debug"]="false";
11603
													#參考資料:
11604
													#無.
11605
													#備註:
11606
													#目前$conf["text"]長度超過125會出錯.
11607
													$talkback=webSock::encode($conf["webSock::encode"]);
11608
													unset($conf["webSock::encode"]);
11609
 
11610
													#如果執行失敗
11611
													if($talkback["status"]==="false"){
11612
 
11613
														#印出結果
11614
														var_dump($talkback);
11615
 
11616
														#結束執行
11617
														exit;
11618
 
11619
														}#if end
11620
 
11621
													#debug
11622
													#var_dump(__LINE__,$talkback);
11623
 
11624
													}#if end
11625
 
11626
												}#if end
11627
 
11628
											}#if end
11629
 
11630
										#反之不為 web socket 訊息
11631
										else{
11632
 
11633
											#儲存成只有一個訊息
11634
											$talkback["content"][]=$talkback;
11635
 
11636
											}#else
11637
 
11638
										#針對每個訊息的分段
11639
										foreach($talkback["content"] as $msg){
11640
 
11641
											#給對方看的訊息
11642
											$socket_write=socket_write($connections[$targetKey]["connect"], $msg, strlen($msg));
11643
 
11644
											#debug
11645
											#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11646
 
11647
											}#foreach end
11648
 
11649
										#換一個連線
11650
										continue;
11651
 
11652
										}#if end
11653
 
11654
									}#if end
11655
 
11656
								}#if end
11657
 
11658
							}#if end
11659
 
11660
						#如果收到的是 quit
11661
						if ($buf === 'quit' ) {
11662
 
11663
							#設置要回傳的訊息
11664
							$talkback="結束與 server 的連線";
11665
 
11666
							#json encode 要回傳的訊息
11667
							$talkback=json_encode($talkback).PHP_EOL;
11668
 
11669
							#如果是 ws 模式
11670
							if($conf["wsMode"]==="true"){
11671
 
11672
								#如果已經 handshake 過
11673
								if($connections[$conIndex]["handshaked"]==="true"){
11674
 
11675
									#如果要 unmask	
11676
									if($connections[$conIndex]["unmask"]==="true"){
11677
 
11678
										#函式說明:
11679
										#加密 handshake 後要傳送的訊息 
11680
										#回傳結果:
11681
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11682
										#$result["error"],執行不正常結束的錯訊息陣列.
11683
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11684
										#$result["argu"],陣列,使用的參數.
11685
										#必填參數:
11686
										#$conf["text"],字串,要加密的訊息.
11687
										$conf["webSock::encode"]["text"]=$talkback; 
11688
										#可省略參數:
11689
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11690
										#$conf["payloadIsBin"]="false";
11691
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11692
										#$conf["ping"]="false";
11693
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11694
										#$conf["pong"]="false";
11695
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11696
										#$conf["frames"]=array();
11697
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11698
										#$conf["mask"]="false";
11699
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11700
										#$conf["debug"]="false";
11701
										#參考資料:
11702
										#無.
11703
										#備註:
11704
										#目前$conf["text"]長度超過125會出錯.
11705
										$talkback=webSock::encode($conf["webSock::encode"]);
11706
										unset($conf["webSock::encode"]);
11707
 
11708
										#如果執行失敗
11709
										if($talkback["status"]==="false"){
11710
 
11711
											#印出結果
11712
											var_dump($talkback);
11713
 
11714
											#結束執行
11715
											exit;
11716
 
11717
											}#if end
11718
 
11719
										#debug
11720
										#var_dump(__LINE__,$talkback);
11721
 
11722
										}#if end
11723
 
11724
									}#if end
11725
 
11726
								}#if end
11727
 
11728
							#反之不為 web socket 訊息
11729
							else{
11730
 
11731
								#儲存成只有一個訊息
11732
								$talkback["content"][]=$talkback;
11733
 
11734
								}#else
11735
 
11736
							#針對每個訊息的分段
11737
							foreach($talkback["content"] as $msg){
11738
 
11739
								#回傳訊息
11740
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
11741
 
11742
								#debug
11743
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11744
 
11745
								}#foreach end
11746
 
11747
							#關閉被 client 的連線	
11748
							socket_close($con["connect"]);
11749
 
11750
							#清理連線的陣列
11751
							unset($connections[$conIndex]);
11752
 
11753
							#跳到下一輪
11754
							continue;
11755
 
11756
							}#if end
11757
 
11758
						#如果收到的是 shutdown	
11759
						if ($buf === 'shutdown') {
11760
 
11761
							#設置要回傳的訊息
11762
							$talkback="Server 即將關閉";
11763
 
11764
							#json encode 要回傳的訊息
11765
							$talkback=json_encode($talkback);
11766
 
11767
							#如果是 ws 模式
11768
							if($conf["wsMode"]==="true"){
11769
 
11770
								#如果已經 handshake 過
11771
								if($connections[$conIndex]["handshaked"]==="true"){
11772
 
11773
									#如果要 unmask	
11774
									if($connections[$conIndex]["unmask"]==="true"){
11775
 
11776
										#函式說明:
11777
										#加密 handshake 後要傳送的訊息 
11778
										#回傳結果:
11779
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11780
										#$result["error"],執行不正常結束的錯訊息陣列.
11781
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
11782
										#$result["argu"],陣列,使用的參數.
11783
										#必填參數:
11784
										#$conf["text"],字串,要加密的訊息.
11785
										$conf["webSock::encode"]["text"]=$talkback; 
11786
										#可省略參數:
11787
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
11788
										#$conf["payloadIsBin"]="false";
11789
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
11790
										#$conf["ping"]="false";
11791
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
11792
										#$conf["pong"]="false";
11793
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
11794
										#$conf["frames"]=array();
11795
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
11796
										#$conf["mask"]="false";
11797
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
11798
										#$conf["debug"]="false";
11799
										#參考資料:
11800
										#無.
11801
										#備註:
11802
										#無.
11803
										$talkback=webSock::encode($conf["webSock::encode"]);
11804
										unset($conf["webSock::encode"]);
11805
 
11806
										#如果執行失敗
11807
										if($talkback["status"]==="false"){
11808
 
11809
											#印出結果
11810
											var_dump($talkback);
11811
 
11812
											#結束執行
11813
											exit;
11814
 
11815
											}#if end
11816
 
11817
										#debug
11818
										#var_dump(__LINE__,$talkback);
11819
 
11820
										}#if end
11821
 
11822
									}#if end
11823
 
11824
								}#if end
11825
 
11826
							#反之不為 web socket 訊息
11827
							else{
11828
 
11829
								#儲存成只有一個訊息
11830
								$talkback["content"][]=$talkback;
11831
 
11832
								}#else
11833
 
11834
							#針對每個訊息的分段
11835
							foreach($talkback["content"] as $msg){
11836
 
11837
								#回傳訊息
11838
								$socket_write=socket_write($con["connect"], $msg, strlen($msg));
11839
 
11840
								#debug
11841
								#var_dump(__LINE__,$socket_write,socket_strerror(socket_last_error($con["connect"])));
11842
 
11843
								}#foreach end
11844
 
11845
							#關閉用戶的連線
11846
							socket_close($con["connect"]);
11847
 
11848
							#跳到最外層,結束webSocket server
11849
							break 2;
11850
 
11851
							}#if end
11852
 
11853
						#如果有指定的外掛函式
11854
						if(isset($conf["processFuncs"])){
11855
 
11856
							#針對每個用來處理輸入字串的函式
11857
							foreach($conf["processFuncs"] as $proFunc){
11858
 
11859
								#debug
11860
								#var_dump(__LINE__,$proFunc);
11861
 
11862
								#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket
11863
								#https://www.php.net/manual/en/function.call-user-func.php
11864
								$param=array("data"=>&$buf,"serverSock"=>&$sock,"clientSock"=>&$con["connect"],"clientInfo"=>&$connections[$conIndex],"clientIndex"=>&$conIndex,"allConn"=>&$connections);
11865
								$params=array();
11866
								$params[]=&$param;										
11867
								$result=call_user_func_array($proFunc,$params);						
11868
 
11869
								#debug
11870
								#var_dump(__LINE__,$result);
11871
 
11872
								#如果有回傳結果
11873
								if($result!==NULL){
11874
 
11875
									#如果回傳的形態為陣列
11876
									if(gettype($result)==="array"){
11877
 
11878
										#如果執行出錯
11879
										if($result["status"]==="false"){
11880
 
11881
											#提示錯誤
11882
											echo "run function ".$proFunc." with params:".print_r($params,true)." failed!".PHP_EOL;
11883
 
11884
											#提示會往後面執行
11885
											echo "go next function.".PHP_EOL;
11886
 
11887
											#跳到下一輪
11888
											#continue;
11889
 
11890
											}#if end
11891
 
11892
										#如果結果為跳下一輪
11893
										else if($result["status"]==="continue"){
11894
 
11895
											#提示成功
11896
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
11897
 
11898
											#提示會往後面執行
11899
											echo "go next function.".PHP_EOL;
11900
 
11901
											#跳下一輪
11902
											#continue;
11903
 
11904
											}#if end
11905
 
11906
										#如果已經被處理好了且不准移交給後面的處理
11907
										else if($result["status"]==="true"){
11908
 
11909
											#提示成功
11910
											echo "run function ".$proFunc." with params:".print_r($params,true)." success.".PHP_EOL;
11911
 
11912
											#提示在此打住.
11913
											echo "end process,".PHP_EOL;
11914
 
11915
											#後面就不做了
11916
											break;
11917
 
11918
											}#if end
11919
 
11920
										}#if end
11921
 
11922
									#反之回傳形態錯誤
11923
									else{
11924
 
11925
										#提示錯誤
11926
										echo "run function ".$proFunc." with params:".print_r($params,true)." success, but format of return is incorrect!".PHP_EOL;
11927
 
11928
										#提示會往後面執行
11929
										echo "go next function.".PHP_EOL;
11930
 
11931
										}#else end
11932
 
11933
									}#if end
11934
 
11935
								#如果沒有回傳結果
11936
								else{
11937
 
11938
									#提示錯誤
11939
									echo "run function ".$proFunc." with params:".print_r($params,true)." success, but there is no return!".PHP_EOL;
11940
 
11941
									#跳下一輪
11942
									#continue;
11943
 
11944
									}#else end
11945
 
11946
								}#foreach end
11947
 
11948
							}#if end
11949
 
11950
						#如果有要接收訊息的id
11951
						if(count($connections[$conIndex]["talkTo"])>0){
11952
 
11953
							#初始化要傳送給哪些id
11954
							$broadcastId=array();
11955
 
11956
							#依據每個連線資訊
11957
							foreach($connections as $index=>$broadcast){
11958
 
11959
								#儲存每個
11960
								$broadcastId[$index]=$broadcast["id"];
11961
 
11962
								}#foreach end
11963
 
11964
							#檢查哪些人是要接收到訊息的	
11965
							#涵式說明:
11966
							#檢查多個數值,是否與陣列裏面的某些元素相同。
11967
							#回傳的結果:
11968
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
11969
							#$result["function"],當前執行的函數
11970
							#$result["error"],涵式錯誤訊息,若爲""則表示沒有錯誤 
11971
							#$result["founded"][$i],若爲"false"代表沒有相同的元素;反之"true"代表有相同的元素,$i爲第i+1個$conf["inputElement"]參數判斷後的結果.
11972
							#$result["key"][$i],為找到$conf["inputElement"]第$i+1個元素的值是在$conf["blackBoxElement"]中的哪個元素.
11973
							#必填的參數:
11974
							$conf["search::checkEquality"]["inputElement"]=$connections[$conIndex]["talkTo"];#想要找到的變數/數值.
11975
							$conf["search::checkEquality"]["blackBoxElement"]=$broadcastId;#要從哪些變數/數值去尋找.
11976
							$checkEquality=search::checkEquality($conf["search::checkEquality"]);
11977
							unset($conf["search::checkEquality"]);
11978
 
11979
							#如果檢查失敗
11980
							if($checkEquality["status"]==="false"){
11981
 
11982
								#設置執行失敗
11983
								$result["status"]="false";
11984
 
11985
								#設置執行錯誤訊息
11986
								$result["error"]=$checkEquality;
11987
 
11988
								#回傳結果
11989
								return $result;
11990
 
11991
								}#if end
11992
 
11993
							#針對每個搜尋的結果
11994
							foreach($checkEquality["founded"] as $key=>$found){
11995
 
11996
								#如果有找到
11997
								if($found==="true"){
11998
 
11999
									#取得要接收訊息的msgSock
12000
									$receiveMsgSock=$connections[$checkEquality["key"][$key]]["connect"];
12001
 
12002
									#設置要傳送的訊息
12003
									$talkback = $connections[$conIndex]["id"]." said ".$buf;
12004
 
12005
									#json encode 要傳送的訊息
12006
									$talkback=json_encode($talkback).PHP_EOL;
12007
 
12008
									#如果是 ws 模式
12009
									if($conf["wsMode"]==="true"){
12010
 
12011
										#如果已經 handshake 過
12012
										if($connections[$conIndex]["handshaked"]==="true"){
12013
 
12014
											#如果要 unmask	
12015
											if($connections[$conIndex]["unmask"]==="true"){
12016
 
12017
												#加密
12018
												$conf["webSock::encode"]["text"]=$talkback;
12019
												$talkback=webSock::encode($conf["webSock::encode"]);
12020
												unset($conf["webSock::encode"]);
12021
 
12022
												}#if end
12023
 
12024
											}#if end
12025
 
12026
										}#if end
12027
 
12028
									#反之不為 web socket 訊息
12029
									else{
12030
 
12031
										#儲存成只有一個訊息
12032
										$talkback["content"][]=$talkback;
12033
 
12034
										}#else
12035
 
12036
 
12037
									#針對每個訊息的分段
12038
									foreach($talkback["content"] as $msg){
12039
 
12040
										#回傳訊息
12041
										$socket_write=socket_write($receiveMsgSock, $msg, strlen($msg));
12042
 
12043
										#debug
12044
										#var_dump(__LINE__,$receiveMsgSock,socket_strerror(socket_last_error($receiveMsgSock)));
12045
 
12046
										}#foreach end
12047
 
12048
									}#if end
12049
 
12050
								}#foreach end
12051
 
12052
							}#if end
12053
 
12054
						}#if end
12055
 
12056
					}#foreach end
12057
 
12058
				#do end 
12059
				}while(true);
12060
 
12061
			#提示關閉 server socket
12062
			echo "關閉 server socket".PHP_EOL;
12063
 
12064
			#關閉 socket
12065
			socket_close($sock);
12066
 
12067
			#do end
12068
			}while(true);
12069
 
12070
		#設置執行正常
12071
		$result["status"]="true";
12072
 
12073
		#回傳結果
12074
		return $result;
12075
 
12076
		}#function nativeSocketTcpIpServer end
12077
 
12078
	/*	
12079
	#函式說明:
12080
	#連線到webSocket,會印出建立好的unixDomainSocket位置與名稱.
12081
	#回傳結果:
12082
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
12083
	#$result["error"],錯誤訊息陣列.
12084
	#$resutl["function"],當前執行的涵式名稱.
12085
	#$result["content"],取得的回應.
12086
	#$result["argu"],所使用的參數.
12087
	#$result["Sec-WebSocket-Accept"],所得到的Sec-WebSocket-Accept.
12088
	#必填參數:
12089
	#無.
12090
	#可省略參數:
12091
	#$conf["targetServr"],字串,要連線的目標,預設為"localhost".
12092
	#$conf["targetServr"]="";
12093
	#$conf["targetPort"],字串,要連線的目標port.
12094
	#$conf["targetPort"]="";
12095
	#$conf["ssl"],字串,是否要走wss,預設為"false",不走wss;反之為"true".
12096
	#$conf["ssl"]="false";
12097
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
12098
	#$conf["debug"]="false";
12099
	#參考資料:
12100
	#https://www.php.net/manual/en/function.stream-socket-client.php
12101
	#https://www.php.net/manual/en/function.stream-context-create.php
12102
	#https://www.php.net/manual/en/context.ssl.php
12103
	#備註:
12104
	#建構中...
12105
	*/
12106
	public static function clientDaemon(&$conf){
12107
 
12108
		#初始化要回傳的結果
12109
		$result=array();
12110
 
12111
		#取得當前執行的函數名稱
12112
		$result["function"]=__FUNCTION__;
12113
 
12114
		#涵式說明:
12115
		#判斷當前環境為web還是cmd
12116
		#回傳結果:
12117
		#$result,"web"或"cmd"
12118
		if(csInformation::getEnv()==="web"){
12119
 
12120
			#設置執行失敗
12121
			$result["status"]="false";
12122
 
12123
			#設置執行錯誤訊息
12124
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
12125
 
12126
			#回傳結果
12127
			return $result;
12128
 
12129
			}#if end
12130
 
12131
		#取得參數
12132
		$result["argu"]=$conf;
12133
 
12134
		#如果 $conf 不為陣列
12135
		if(gettype($conf)!="array"){
12136
 
12137
			#設置執行失敗
12138
			$result["status"]="false";
12139
 
12140
			#設置執行錯誤訊息
12141
			$result["error"][]="\$conf變數須為陣列形態";
12142
 
12143
			#如果傳入的參數為 null
12144
			if($conf==null){
12145
 
12146
				#設置執行錯誤訊息
12147
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
12148
 
12149
				}#if end
12150
 
12151
			#回傳結果
12152
			return $result;
12153
 
12154
			}#if end
12155
 
12156
		#檢查參數
12157
		#函式說明:
12158
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
12159
		#回傳結果:
12160
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12161
		#$result["error"],執行不正常結束的錯訊息陣列.
12162
		#$result["simpleError"],簡單表示的錯誤訊息.
12163
		#$result["function"],當前執行的函式名稱.
12164
		#$result["argu"],設置給予的參數.
12165
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
12166
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
12167
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
12168
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
12169
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
12170
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
12171
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
12172
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
12173
		#必填參數:
12174
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
12175
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
12176
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
12177
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
12178
		#可省略參數:
12179
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
12180
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array();
12181
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
12182
		#$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array();
12183
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
12184
		#$conf["canBeEmptyString"]="false";
12185
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
12186
		#$conf["canNotBeEmpty"]=array();
12187
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
12188
		#$conf["canBeEmpty"]=array();
12189
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
12190
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("targetServr","targetPort","ssl","debug");
12191
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
12192
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("targetServr","targetPort","ssl","debug");
12193
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
12194
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","string");
12195
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
12196
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("localhost",null,"false","false");
12197
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
12198
		#$conf["disallowAllSkipableVarIsEmpty"]="";
12199
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
12200
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
12201
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
12202
		#$conf["disallowAllSkipableVarNotExist"]="";
12203
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
12204
		#$conf["arrayCountEqualCheck"][]=array();
12205
		#參考資料:
12206
		#array_keys=>http://php.net/manual/en/function.array-keys.php
12207
		#備註:
12208
		#無.
12209
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
12210
		unset($conf["variableCheck::checkArguments"]);
12211
 
12212
		#如果檢查參數失敗
12213
		if($checkArguments["status"]==="false"){
12214
 
12215
			#設置執行失敗
12216
			$result["status"]="false";
12217
 
12218
			#設置執行錯誤訊息
12219
			$result["error"]=$checkArguments;
12220
 
12221
			#回傳結果
12222
			return $result;
12223
 
12224
			}#if end
12225
 
12226
		#如果檢查參數不通過
12227
		if($checkArguments["passed"]==="false"){
12228
 
12229
			#設置執行失敗
12230
			$result["status"]="false";
12231
 
12232
			#設置執行錯誤訊息
12233
			$result["error"]=$checkArguments;
12234
 
12235
			#回傳結果
12236
			return $result;
12237
 
12238
			}#if end
12239
 
12240
		#如果targetPort沒有設置
12241
		if(!isset($conf["targetPort"])){
12242
 
12243
			#port預設為80
12244
			$conf["targetPort"]="80";
12245
 
12246
			#如果有啟用 ssl
12247
			if($conf["ssl"]==="true"){
12248
 
12249
				#port預設為443
12250
				$conf["targetPort"]="443";
12251
 
12252
				}#if end
12253
 
12254
			}#if end
12255
 
12256
		#回報任何錯誤
12257
		#error_reporting(E_ALL);
12258
 
12259
		#如果要使用 ssl
12260
		if($conf["ssl"]==="true"){
12261
 
12262
			#預設的path
12263
			$path="/";
12264
 
12265
			#分割出server位置與對應GET的path
12266
			#函式說明:
12267
			#將固定格式的字串分開,並回傳分開的結果.
12268
			#回傳結果:
12269
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12270
			#$result["error"],錯誤訊息陣列
12271
			#$result["function"],當前執行的函數名稱.
12272
			#$result["argu"],使用的參數.
12273
			#$result["oriStr"],要分割的原始字串內容
12274
			#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
12275
			#$result["dataCounts"],爲總共分成幾段
12276
			#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
12277
			#必填參數:
12278
			#$conf["stringIn"],字串,要處理的字串.
12279
			$conf["stringProcess::spiltString"]["stringIn"]=$conf["targetServr"];
12280
			#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
12281
			$conf["stringProcess::spiltString"]["spiltSymbol"]="/";
12282
			#可省略參數:
12283
			#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
12284
			$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
12285
			#參考資料:
12286
			#無.
12287
			#備註:
12288
			#無.
12289
			$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
12290
			unset($conf["stringProcess::spiltString"]);
12291
 
12292
			#如果檢查執行失敗
12293
			if($spiltString["status"]==="false"){
12294
 
12295
				#設置執行失敗
12296
				$result["status"]="false";
12297
 
12298
				#設置執行錯誤訊息
12299
				$result["error"]=$spiltString;
12300
 
12301
				#回傳結果
12302
				return $result;
12303
 
12304
				}#if end
12305
 
12306
			#如果含有 /
12307
			if($spiltString["found"]==="true"){
12308
 
12309
				#函式說明:
12310
				#將字串特定關鍵字與其前面的內容剔除
12311
				#回傳結果:
12312
				#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12313
				#$result["error"],錯誤訊息陣列.
12314
				#$result["warning"],警告訊息鎮列.
12315
				#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
12316
				#$result["function"],當前執行的函數名稱.
12317
				#$result["argu"],使用的參數.
12318
				#$result["oriStr"],要處理的原始字串內容.
12319
				#$result["content"],處理好的的字串內容.	
12320
				#必填參數:
12321
				#$conf["stringIn"],字串,要處理的字串.
12322
				$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$conf["targetServr"];
12323
				#$conf["keyWord"],字串,特定字串.
12324
				$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="/";
12325
				#可省略參數:
12326
				#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
12327
				#$conf["recursive"]="true";
12328
				#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
12329
				#$conf["lastResult"]=$delStrBeforeKeyWord;
12330
				#參考資料:
12331
				#無.
12332
				#備註:
12333
				#無.
12334
				$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
12335
				unset($conf["stringProcess::delStrBeforeKeyWord"]);
12336
 
12337
				#如果檢查執行失敗
12338
				if($delStrBeforeKeyWord["status"]==="false"){
12339
 
12340
					#設置執行失敗
12341
					$result["status"]="false";
12342
 
12343
					#設置執行錯誤訊息
12344
					$result["error"]=$delStrBeforeKeyWord;
12345
 
12346
					#回傳結果
12347
					return $result;
12348
 
12349
					}#if end
12350
 
12351
				#如果該存在的 / 不存在
12352
				if($delStrBeforeKeyWord["founded"]==="false"){
12353
 
12354
					#設置執行失敗
12355
					$result["status"]="false";
12356
 
12357
					#設置執行錯誤訊息
12358
					$result["error"]=$delStrBeforeKeyWord;
12359
 
12360
					#回傳結果
12361
					return $result;
12362
 
12363
					}#if end
12364
 
12365
				#設置 path
12366
				$path="/".$delStrBeforeKeyWord["content"];
12367
 
12368
				#如果有切出 path
12369
				if($spiltString["dataCounts"]>=2){
12370
 
12371
					#另存peer host name
12372
					$peerHostName=$spiltString["dataArray"][0];
12373
 
12374
					#更新 targetServr
12375
					$conf["targetServr"]=$peerHostName;
12376
 
12377
					}#if end
12378
 
12379
				}#if end
12380
 
12381
			#初始化給 stream_context_create 用的參數
12382
			$paramsForStream_context_create=array();
12383
 
12384
			#設置為http相關的參數
12385
			#$paramsForStream_context_create["http"]=array();
12386
 
12387
			#method為HEAD
12388
			#$paramsForStream_context_create["http"]["method"]="HEAD ".$path;
12389
 
12390
			#HTTP/1.1
12391
			#$paramsForStream_context_create["http"]["protocol_version"]="1.1";
12392
 
12393
			#初始化header
12394
			#$paramsForStream_context_create["http"]["header"]=array();
12395
 
12396
			#設置header Host
12397
			#$paramsForStream_context_create["http"]["header"][]="Host: ".$conf["targetServr"];
12398
 
12399
			#設置header Upgrade
12400
			#$paramsForStream_context_create["http"]["header"][]="Upgrade: websocket";
12401
 
12402
			#設置header Connection
12403
			#$paramsForStream_context_create["http"]["header"][]="Connection: Upgrade";
12404
 
12405
			#設置header Sec-WebSocket-Version
12406
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Version: 13";
12407
 
12408
			#設置header Sec-WebSocket-Key
12409
			#$paramsForStream_context_create["http"]["header"][]="Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==";
12410
 
12411
			#body content
12412
			#$paramsForStream_context_create["http"]["content"]="";
12413
 
12414
			#設置為ssl相關的參數
12415
			$paramsForStream_context_create["ssl"]=array();
12416
 
12417
			#被連線端的網域名稱
12418
			#$paramsForStream_context_create["ssl"]["peer_name"]=$conf["targetServr"];
12419
 
12420
			#verify_peer
12421
			#$paramsForStream_context_create["ssl"]["verify_peer"]=true;
12422
			#$paramsForStream_context_create["ssl"]["verify_peer"]=false;
12423
 
12424
			#verify_peer_name
12425
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=true;
12426
			#$paramsForStream_context_create["ssl"]["verify_peer_name"]=false;
12427
 
12428
			#allow_self_signed,允許沒有受到認可的憑證
12429
			#$paramsForStream_context_create["ssl"]["allow_self_signed"]=false; 
12430
 
12431
			#cafile
12432
			$paramsForStream_context_create["ssl"]["cafile"]="/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem";
12433
 
12434
			#capath
12435
			#$paramsForStream_context_create["ssl"]["capath"]="/etc/pki/ca-trust/extracted/pem/directory-hash/";
12436
 
12437
			#local_cert
12438
			#$paramsForStream_context_create["ssl"]["local_cert"]="/etc/pki/tls/certs/php-selfsigned-and-key.crt";
12439
 
12440
			#local_pk
12441
			#$paramsForStream_context_create["ssl"]["local_pk"]="/etc/pki/tls/private/php-selfsigned.key";
12442
 
12443
			#capture_peer_cert
12444
			$paramsForStream_context_create["ssl"]["capture_peer_cert"]=true;
12445
 
12446
			#capture_peer_cert_chain
12447
			$paramsForStream_context_create["ssl"]["capture_peer_cert_chain"]=true;
12448
 
12449
			#security_level
12450
			#$paramsForStream_context_create["ssl"]["security_level"]=5;
12451
 
12452
			#如果要 debug
12453
			if($conf["debug"]==="true"){
12454
 
12455
				#debug
12456
				var_dump(__LINE__,$paramsForStream_context_create);
12457
 
12458
				}#if end
12459
 
12460
			#建立ssl設定
12461
			$stream_context_create=stream_context_create($paramsForStream_context_create);
12462
 
12463
			#如果要 debug
12464
			if($conf["debug"]==="true"){
12465
 
12466
				#debug
12467
				var_dump(__LINE__,$stream_context_create);
12468
 
12469
				}#if end
12470
 
12471
			#連線到 $conf["targetServr"].":".$conf["targetPort"] ,若有 error 可從 $error_code,$error_message 取得資訊, timeout 為 30 秒, connection flags 為 STREAM_CLIENT_CONNECT, 連線的屬性記載在 $stream_context_create.
12472
			$stream_socket_client=stream_socket_client("ssl://".$conf["targetServr"].":".$conf["targetPort"],$error_code,$error_message,0,STREAM_CLIENT_CONNECT,$stream_context_create);
12473
 
12474
			#如果連線到 peer 失敗
12475
			if($stream_socket_client===false){
12476
 
12477
				#設置執行失敗
12478
				$result["status"]="false";
12479
 
12480
				#設置執行錯誤訊息
12481
				$result["error"][]="stream_socket_client() failed.".PHP_EOL."Reason: ".$error_message."(".$error_code.")".PHP_EOL;
12482
 
12483
				#回傳結果
12484
				return $result;
12485
 
12486
				}#if end
12487
 
12488
			#取得連線的資訊
12489
			$result["info"]=stream_get_meta_data($stream_socket_client);
12490
 
12491
			#write header - start
12492
 
12493
			#initial header
12494
			$header="";
12495
 
12496
			#method、path、protocol
12497
			$header=$header."HEAD ".$path." HTTP/1.1"."\r\n";
12498
 
12499
			#Host
12500
			$header=$header."Host: ".$conf["targetServr"]."\r\n";
12501
 
12502
			#Upgrade
12503
			$header=$header."Upgrade: websocket"."\r\n";
12504
 
12505
			#Connection
12506
			$header=$header."Connection: Upgrade"."\r\n";
12507
 
12508
			#Sec-WebSocket-Version
12509
			$header=$header."Sec-WebSocket-Version: 13"."\r\n";
12510
 
12511
			#Sec-WebSocket-Key
12512
			$header=$header."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
12513
 
12514
			#send header					
12515
			fwrite($stream_socket_client,$header."\r\n");
12516
 
12517
			#write header - close
12518
 
12519
			#GET server reponse
12520
			while(!feof($stream_socket_client)){
12521
 
12522
				#讀取內容
12523
				$fgets=fgets($stream_socket_client, 1024);
12524
 
12525
				#如果要 debug
12526
				if($conf["debug"]==="true"){
12527
 
12528
					#debug
12529
					var_dump(__LINE__,$fgets);
12530
 
12531
					}#if end
12532
 
12533
				#如果 server 已經回應要用 websocket 協定了
12534
				if(trim($fgets)==="Upgrade: websocket"){
12535
 
12536
					#跳出while
12537
					break;
12538
 
12539
					}#if end
12540
 
12541
				}#if end
12542
 
12543
			#將建立的 sock 放到 $master 陣列
12544
			$master[] = $stream_socket_client;
12545
 
12546
			#函式說明:
12547
			#取得目前瀏覽的頁面的路徑或執行的php程式路徑.
12548
			#回傳結果:
12549
			#$result["status"],執行是否正常,"true"代表執行成功,"false"代表執行失敗.
12550
			#$result["error"],錯誤訊息.
12551
			#$result["function"],檔前執行的函數名稱.
12552
			#$result["content"],目前瀏覽的頁面的路徑或執行的php程式路徑.
12553
			#$result["serverIp"],取得伺服器ip.
12554
			#$result["scheme"],取得與伺服器連線所使用的通訊協定.
12555
			#必填參數:
12556
			$conf["csInformation::getPathOfThisPhpFile"]["type"]="pathOnly";#想要取得的路徑類型,"full"代表完整路徑,"pathOnly"代表只要路徑,"lastLayer"代表上一層目錄的名稱
12557
			#必填參數:
12558
			#無.
12559
			#可省略參數:
12560
			#無.
12561
			#參考資料:
12562
			#http://blog.longwin.com.tw/2009/01/php-get-directory-file-path-dirname-2008/
12563
			#備註:
12564
			#無.
12565
			$getPathOfThisPhpFile=csInformation::getPathOfThisPhpFile($conf["csInformation::getPathOfThisPhpFile"]);
12566
			unset($conf["csInformation::getPathOfThisPhpFile"]);
12567
 
12568
			#如果執行失敗
12569
			if($getPathOfThisPhpFile["status"]=="false"){
12570
 
12571
				#設置錯誤識別
12572
				$result["status"]="false";
12573
 
12574
				#設置錯誤訊息
12575
				$result["error"]=$getPathOfThisPhpFile;
12576
 
12577
				#回傳結果
12578
				return $result;
12579
 
12580
				}#if end
12581
 
12582
			#函式說明:
12583
			#使用 linux 的 uuid 指令來產生 uuid 字串
12584
			#回傳結果:
12585
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12586
			#$result["error"],錯誤訊息.
12587
			#$result["function"],當前執行的函式名稱.
12588
			#$result["content"],uuid.
12589
			#必填參數:
12590
			#無.
12591
			#可省略參數:
12592
			#無.
12593
			#參考資料:
12594
			#無.
12595
			#備註:
12596
			#無.
12597
			$uuid=cmd::uuid();
12598
 
12599
			#如果執行失敗
12600
			if($uuid["status"]=="false"){
12601
 
12602
				#設置錯誤識別
12603
				$result["status"]="false";
12604
 
12605
				#設置錯誤訊息
12606
				$result["error"]=$uuid;
12607
 
12608
				#回傳結果
12609
				return $result;
12610
 
12611
				}#if end
12612
 
12613
			#設置存放socket的path
12614
			$socketPath=$getPathOfThisPhpFile["content"]."var/webSock::clientDaemon";
12615
 
12616
			#讓存放unix domain socket的路徑存在
12617
			#函式說明:
12618
			#確保路徑存在.
12619
			#回傳結果:
12620
			#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
12621
			#$result["error"],錯誤訊息陣列.
12622
			#$resutl["function"],當前執行的涵式名稱.
12623
			#$result["path"],建立好的路徑字串.
12624
			#$result["fileName"],檔案名稱,若 $conf["haveFileName"] 為 "true" 則會回傳.
12625
			#$result["argu"],使用的參數.
12626
			#必填參數:
12627
			#$conf["path"],要檢查的路徑
12628
			$conf["fileAccess::validatePath"]["path"]=$socketPath;
12629
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
12630
			$conf["fileAccess::validatePath"]["fileArgu"]=__FILE__;
12631
			#可省略參數:
12632
			#$conf["haveFileName"],字串,"true"代表有$conf["path"]檔案名稱,"false"代表$conf["path"]為純路徑,預設為"false".
12633
			$conf["fileAccess::validatePath"]["haveFileName"]="false";
12634
			#$conf["dirPermission"],字串,新建資料夾的權限設定,預設爲0770,亦即擁有者,同群組者可以讀,寫,存取,其他人無法使用.
12635
			#$conf["dirPermission"]="";
12636
			#$conf["web"],是否為檔案系統,"true"為網頁路徑,"false"為網頁系統,預設為"false".
12637
			$conf["fileAccess::validatePath"]["web"]="false";
12638
			#參考資料:
12639
			#無.
12640
			#備註:
12641
			#無.
12642
			$validatePath=fileAccess::validatePath($conf["fileAccess::validatePath"]);
12643
			unset($conf["fileAccess::validatePath"]);
12644
 
12645
			#如果執行失敗
12646
			if($validatePath["status"]==="false"){
12647
 
12648
				#設置錯誤識別
12649
				$result["status"]="false";
12650
 
12651
				#設置錯誤訊息
12652
				$result["error"]=$validatePath;
12653
 
12654
				#回傳結果
12655
				return $result;
12656
 
12657
				}#if end
12658
 
12659
			#變更 working dir
12660
			$chdir=chdir($socketPath);
12661
 
12662
			#設置sock檔案名稱
12663
			$socketName=$uuid["content"].".sock";
12664
 
12665
			#設置sock檔案位置與名稱
12666
			$socketAddr=$socketPath."/".$socketName;
12667
 
12668
			#如果要 debug
12669
			if($conf["debug"]==="true"){
12670
 
12671
				#debug
12672
				var_dump(__LINE__,$socketAddr);
12673
 
12674
				}#if end
12675
 
12676
			#建立 unix domain socket
12677
			$usock=stream_socket_server("unix://".$socketName, $errno, $errstr);
12678
 
12679
			#如果建立 unix domain socket 失敗
12680
			if(!$usock){
12681
 
12682
				#設置執行失敗
12683
				$result["status"]="false";
12684
 
12685
				#設置錯誤訊息
12686
				$result["error"][]=$errstr." (".$errno.")";
12687
 
12688
				#設置錯誤訊息
12689
				$result["error"][]="建立 unix domain socket(".$socketAddr.") 失敗";
12690
 
12691
				#回傳結果
12692
				return $result;
12693
 
12694
				}#if end
12695
 
12696
			#印出socket addr
12697
			echo "unixDomainSocket:".$socketAddr;
12698
 
12699
			#將建立的 unix domain socket 放到 $master 陣列
12700
			$master[] = $usock;
12701
 
12702
			#永久監聽, 不 timeout
12703
			while(true){
12704
 
12705
				#設置給 stream_select 監控的 sock 變數
12706
				$read = $write = $except = $master;
12707
 
12708
				#等待1秒,看有沒有連線進來讀寫資料
12709
				$mod_fd = stream_select($read, $write, $except, 1);
12710
 
12711
				#如果沒有偵測到讀寫動作失敗
12712
				if($mod_fd===FALSE){
12713
 
12714
					#關閉 web socket 連線
12715
					@fclose($stream_socket_client);
12716
 
12717
					#關閉unix domain socket
12718
					@fclose($usock);
12719
 
12720
					#移除unix domain socket
12721
					@unlink($socketAddr);
12722
 
12723
					#設置執行失敗
12724
					$result["status"]="false";
12725
 
12726
					#設置錯誤訊息
12727
					$result["error"][]="監聽資源異動失敗";
12728
 
12729
					#回傳結果
12730
					return $result;
12731
 
12732
					}#if end
12733
 
12734
				#如果沒有訊息,代表閒置時可以做的事情
12735
				else if($mod_fd===0){
12736
 
12737
					#代表沒收到訊息
12738
					echo ".";
12739
 
12740
					}#if end
12741
 
12742
				#反之有收到來自 web socket server 或 unix socket 的訊息
12743
				else{
12744
 
12745
					#針對每個 sock 陣列
12746
					foreach($read as $readStream){
12747
 
12748
						#如果是來自 web socket server 的訊息
12749
						if($readStream===$stream_socket_client){
12750
 
12751
							#當等待別人連線時,若有人連線進來.
12752
							#$webConn = stream_socket_accept($stream_socket_client);
12753
 
12754
							#如果要 debug
12755
							if($conf["debug"]==="true"){
12756
 
12757
								#debug
12758
								var_dump(__LINE__,"有收到來自 web socket server 的訊息");
12759
 
12760
								}#if end
12761
 
12762
							#讀取內容
12763
							$fread=fread($stream_socket_client,1024);
12764
 
12765
							#如果要 debug
12766
							if($conf["debug"]==="true"){
12767
 
12768
								#debug
12769
								var_dump(__LINE__,strlen($fread),$fread);
12770
 
12771
								}#if end
12772
 
12773
							#函式說明:
12774
							#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
12775
							#回傳結果:
12776
							#$result["function"],當前函式的名稱.
12777
							#$result["argu"],使用的參數.
12778
							#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
12779
							#$result["content"],unmask後的內容.
12780
							#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
12781
							#$result["error"],錯誤訊息陣列.
12782
							#必填參數:
12783
							#$conf["payload"],字串,要解密的訊息.
12784
							$conf["webSock::unmask"]["payload"]=$fread; 
12785
							#可省略參數:
12786
							#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
12787
							$conf["webSock::unmask"]["allowUnmask"]="true";
12788
							#$conf["webSock::unmask"]["debug"]="true";
12789
							#參考資料
12790
							#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
12791
							#https://tools.ietf.org/html/rfc6455
12792
							#https://tools.ietf.org/html/rfc5234
12793
							#備註:
12794
							#無.
12795
							$unmask=webSock::unmask($conf["webSock::unmask"]);
12796
							unset($conf["webSock::unmask"]);
12797
 
12798
							#debug
12799
							#var_dump(__LINE__,$unmask);
12800
 
12801
							#如果出錯
12802
							if($unmask["status"]==="false"){
12803
 
12804
								#關閉 web socket 連線
12805
								@fclose($stream_socket_client);
12806
 
12807
								#關閉unix domain socket
12808
								@fclose($usock);
12809
 
12810
								#移除unix domain socket
12811
								@unlink($socketAddr);
12812
 
12813
								#設置執行失敗
12814
								$result["status"]="false";
12815
 
12816
								#設置執行錯誤訊息
12817
								$result["error"]=$unmask;
12818
 
12819
								#回傳結果
12820
								return $result;
12821
 
12822
								}#if end
12823
 
12824
							#如果收到文字訊息
12825
							if($unmask["type"]==="text"){
12826
 
12827
								#如果有解析出內容
12828
								if(isset($unmask["content"])){
12829
 
12830
									#提示收到的訊息
12831
									echo $unmask["content"];
12832
 
12833
									#傳遞給unix domain client
12834
									$fwrite=fwrite($unixConn,$unmask["content"]);
12835
 
12836
									#如果要 debug
12837
									if($conf["debug"]==="true"){
12838
 
12839
										#debug
12840
										var_dump(__LINE__,$fwrite);
12841
 
12842
										}#if end
12843
 
12844
									#關閉連線
12845
									fclose($unixConn);
12846
 
12847
									}#if end
12848
 
12849
								}#if end
12850
 
12851
							#如果收到ping
12852
							if($unmask["type"]==="ping"){
12853
 
12854
								#函式說明:
12855
								#加密 handshake 後要傳送的 webSocket 訊息 
12856
								#回傳結果:
12857
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12858
								#$result["error"],執行不正常結束的錯訊息陣列.
12859
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12860
								#$result["argu"],陣列,使用的參數.
12861
								#必填參數:
12862
								#$conf["text"],字串,要加密的訊息.
12863
								$conf["webSock::encode"]["text"]=""; 
12864
								#可省略參數:
12865
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12866
								#$conf["ping"]="true";
12867
								#$conf["pong"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12868
								$conf["webSock::encode"]["pong"]="true";
12869
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12870
								#$conf["frames"]=array();
12871
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12872
								$conf["webSock::encode"]["mask"]="true";
12873
								#參考資料:
12874
								#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
12875
								#備註:
12876
								#無.
12877
								$encode=webSock::encode($conf["webSock::encode"]);
12878
								unset($conf["webSock::encode"]);
12879
 
12880
								#如果要 debug
12881
								if($conf["debug"]==="true"){
12882
 
12883
									#debug
12884
									var_dump(__LINE__,$encode);
12885
 
12886
									}#if end
12887
 
12888
								#如果出錯
12889
								if($encode["status"]==="false"){
12890
 
12891
									#設置執行失敗
12892
									$result["status"]="false";
12893
 
12894
									#設置執行錯誤訊息
12895
									$result["error"]=$encode;
12896
 
12897
									#回傳結果
12898
									return $result;
12899
 
12900
									}#if end
12901
 
12902
								#如果要 debug
12903
								if($conf["debug"]==="true"){
12904
 
12905
									#debug
12906
									var_dump(__LINE__,$encode);
12907
 
12908
									}#if end
12909
 
12910
								#針對每個 frame
12911
								foreach($encode["content"] as $fNo => $frame){
12912
 
12913
									#傳遞給 web socket server
12914
									$fwrite=fwrite($stream_socket_client,$frame);
12915
 
12916
									#如果傳遞失敗
12917
									if($fwrite===false){
12918
 
12919
										#關閉 web socket 連線
12920
										@fclose($stream_socket_client);
12921
 
12922
										#關閉unix domain socket
12923
										@fclose($usock);
12924
 
12925
										#移除unix domain socket
12926
										@unlink($socketAddr);
12927
 
12928
										#設置執行失敗
12929
										$result["status"]="false";
12930
 
12931
										#設置執行錯誤訊息
12932
										$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
12933
 
12934
										#回傳結果
12935
										return $result;
12936
 
12937
										}#if end
12938
 
12939
									}#foreach end
12940
 
12941
								}#if end
12942
 
12943
							}#if end
12944
 
12945
						#反之若為來自 unix domain socket 的訊息
12946
						else if($readStream===$usock){
12947
 
12948
							#當等待別人連線時,若有人連線進來.
12949
							$unixConn = stream_socket_accept($usock);
12950
 
12951
							#如果要 debug
12952
							if($conf["debug"]==="true"){
12953
 
12954
								#debug
12955
								var_dump(__LINE__,"有收到來自 unix domain socket 的訊息");
12956
 
12957
								}#if end
12958
 
12959
							#讀取內容
12960
							$fgets=trim(fgets($unixConn,1024));
12961
 
12962
							#如果要 debug
12963
							if($conf["debug"]==="true"){
12964
 
12965
								#debug
12966
								var_dump(__LINE__,strlen($fgets),$fgets);
12967
 
12968
								}#if end
12969
 
12970
							#轉換成 web socket 的格式
12971
							#函式說明:
12972
							#加密 handshake 後要傳送的 webSocket 訊息 
12973
							#回傳結果:
12974
							#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
12975
							#$result["error"],執行不正常結束的錯訊息陣列.
12976
							#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
12977
							#$result["argu"],陣列,使用的參數.
12978
							#必填參數:
12979
							#$conf["text"],字串,要加密的訊息.
12980
							$conf["webSock::encode"]["text"]=$fgets; 
12981
							#可省略參數:
12982
							#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
12983
							#$conf["ping"]="true";
12984
							#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
12985
							#$conf["frames"]=array();
12986
							#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
12987
							$conf["webSock::encode"]["mask"]="true";
12988
							#參考資料:
12989
							#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
12990
							#備註:
12991
							#無.
12992
							$encode=webSock::encode($conf["webSock::encode"]);
12993
							unset($conf["webSock::encode"]);
12994
 
12995
							#如果要 debug
12996
							if($conf["debug"]==="true"){
12997
 
12998
								#debug
12999
								var_dump(__LINE__,$encode);
13000
 
13001
								}#if end
13002
 
13003
							#如果出錯
13004
							if($encode["status"]==="false"){
13005
 
13006
								#設置執行失敗
13007
								$result["status"]="false";
13008
 
13009
								#設置執行錯誤訊息
13010
								$result["error"]=$encode;
13011
 
13012
								#回傳結果
13013
								return $result;
13014
 
13015
								}#if end
13016
 
13017
							#針對每個frame
13018
							foreach($encode["content"] as $fNo => $frame){
13019
 
13020
								#傳遞給 web socket server
13021
								$fwrite=fwrite($stream_socket_client,$frame);
13022
 
13023
								#如果要 debug
13024
								if($conf["debug"]==="true"){
13025
 
13026
									#debug
13027
									var_dump(__LINE__,$fwrite,"傳遞".strlen($frame)."bytes給webSocketServer",$frame);
13028
 
13029
									}#if end
13030
 
13031
								#如果傳遞失敗
13032
								if($fwrite===false){
13033
 
13034
									#關閉 web socket 連線
13035
									@fclose($stream_socket_client);
13036
 
13037
									#關閉unix domain socket
13038
									@fclose($usock);
13039
 
13040
									#移除unix domain socket
13041
									@unlink($socketAddr);
13042
 
13043
									#設置執行失敗
13044
									$result["status"]="false";
13045
 
13046
									#設置執行錯誤訊息
13047
									$result["error"][]="傳遞第 ".($fNo+1)." 個 frame 時出錯(總共有".count($encode["content"])."個frame)";
13048
 
13049
									#回傳結果
13050
									return $result;
13051
 
13052
									}#if end
13053
 
13054
								}#foreach end
13055
 
13056
							}#if end
13057
 
13058
						#例外狀況
13059
						else{
13060
 
13061
							#如果要 debug
13062
							if($conf["debug"]==="true"){
13063
 
13064
								#debug
13065
								var_dump(__LINE__,$readStream);
13066
 
13067
								}#if end
13068
 
13069
							#關閉 web socket 連線
13070
							@fclose($stream_socket_client);
13071
 
13072
							#關閉unix domain socket
13073
							@fclose($usock);
13074
 
13075
							#移除unix domain socket
13076
							@unlink($socketAddr);
13077
 
13078
							#顯示 socket 的狀態
13079
							echo "非預期的錯誤,偵測到不應存在資源有異動".PHP_EOL;
13080
 
13081
							#結束執行並回傳1,代表異常結束
13082
							exit(1);
13083
 
13084
							}#else end
13085
 
13086
						}#foreach end
13087
 
13088
					}#else
13089
 
13090
				#等待1秒
13091
				sleep(1);
13092
 
13093
				}#while end
13094
 
13095
			#設置執行正常
13096
			$result["status"]="true";
13097
 
13098
			#回傳結果
13099
			return $result;
13100
 
13101
			}#if end
13102
 
13103
		#反之不用
13104
		else{
13105
 
13106
			#如果要 debug
13107
			if($conf["debug"]==="true"){
13108
 
13109
				#提示用戶端的文字
13110
				echo "TCP/IP Connection".PHP_EOL;
13111
 
13112
				}#if end
13113
 
13114
			/* Get the port for the WWW service. */
13115
			#http://php.net/manual/en/function.getservbyname.php
13116
			#$service_port = getservbyname('www', 'tcp');
13117
 
13118
			/* Get the IP address for the target host. */
13119
			#http://php.net/manual/en/function.gethostbyname.php
13120
			$ServerAddress = gethostbyname($conf["targetServr"]);
13121
 
13122
			/* Create a TCP/IP socket. */
13123
			$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
13124
 
13125
			#如果建立 socket 失敗
13126
			if ($socket === false) {
13127
 
13128
				#設置執行失敗
13129
				$result["status"]="false";
13130
 
13131
				#設置執行錯誤訊息
13132
				$result["error"][]="socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
13133
 
13134
				#回傳結果
13135
				return $result;
13136
 
13137
				}#if end
13138
 
13139
			#反之
13140
			else {
13141
 
13142
				#如果要 debug
13143
				if($conf["debug"]==="true"){
13144
 
13145
					#印出建立成功訊息
13146
					echo "OK.".PHP_EOL;
13147
 
13148
					}#if end
13149
 
13150
				}#else end
13151
 
13152
			#如果要 debug
13153
			if($conf["debug"]==="true"){
13154
 
13155
				#提示要連線到哪個位址的哪個port
13156
				echo "Attempting to connect to ".$ServerAddress." on port ".$conf["targetPort"]."...";
13157
 
13158
				}#if end
13159
 
13160
			#連線到目標 socket
13161
			$socket_connect=socket_connect($socket, $ServerAddress, $conf["targetPort"]);
13162
 
13163
			#如果連線到 socket 失敗
13164
			if($socket_connect===false){
13165
 
13166
				#設置執行失敗
13167
				$result["status"]="false";
13168
 
13169
				#設置執行錯誤訊息
13170
				$result["error"][]="socket_connect() failed.".PHP_EOL."Reason: ($socket_connect) " . socket_strerror(socket_last_error($socket)) . PHP_EOL;
13171
 
13172
				#回傳結果
13173
				return $result;
13174
 
13175
				}#if end
13176
 
13177
			#反之
13178
			else {
13179
 
13180
				#如果要 debug
13181
				if($conf["debug"]==="true"){
13182
 
13183
					#印出連線成功訊息
13184
					echo "OK.".PHP_EOL;
13185
 
13186
					}#if end
13187
 
13188
				}#else end
13189
 
13190
			}#else end
13191
 
13192
		#初始化要傳送的HEAD資訊
13193
		$in="HEAD / HTTP/1.1"."\r\n";
13194
		$in=$in."Host: ".$ServerAddress.":".$conf["targetPort"]."\r\n";
13195
		$in=$in."Upgrade: websocket"."\r\n";
13196
		$in=$in."Connection: Upgrade"."\r\n";
13197
		$in=$in."Sec-WebSocket-Version: 13"."\r\n";
13198
		$in=$in."Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ=="."\r\n";
13199
		$in=$in."\r\n";
13200
 
13201
		#初始化回傳的內容
13202
		$out = '';
13203
 
13204
		#如果連線到 socket 失敗
13205
		if($socket_connect===false){
13206
 
13207
			#提示傳送HTTP HEAD中
13208
			echo "Sending HTTP HEAD request...";
13209
 
13210
			}#if end
13211
 
13212
		#將訊息傳送到socket去
13213
		socket_write($socket, $in, strlen($in));
13214
 
13215
		#如果連線到 socket 失敗
13216
		if($socket_connect===false){
13217
 
13218
			#提示傳送完畢
13219
			echo "OK.".PHP_EOL;
13220
 
13221
			#提示讀取回應中
13222
			echo "Reading response:".PHP_EOL;
13223
 
13224
			}#if end
13225
 
13226
		#無窮迴圈
13227
		while(true){
13228
 
13229
			#一次讀取2048bytes,判斷有無回應,並取得其內容.
13230
			$out = socket_read($socket, 2048);
13231
 
13232
			#如果尚未取得 Sec-WebSocket-Accept
13233
			if(!isset($result["Sec-WebSocket-Accept"])){
13234
 
13235
				#如果連線到 socket 失敗
13236
				if($socket_connect===false){
13237
 
13238
					#印出收到的內容
13239
					echo $out;
13240
 
13241
					}#if end
13242
 
13243
				#如果 $out 有資料
13244
				if($out){
13245
 
13246
					#如果接收到的是字串,且不為空
13247
					if(gettype($out)==="string" && !empty($out)){
13248
 
13249
						#如果有既有的前次回應內容
13250
						if(isset($result["content"])){
13251
 
13252
							#儲存回應的內容
13253
							$result["content"]=$result["content"].$out;
13254
 
13255
							}#if end
13256
 
13257
						#反之
13258
						else{
13259
 
13260
							#儲存回應的內容
13261
							$result["content"]=$out;
13262
 
13263
							}#else end
13264
 
13265
						#涵式說明:
13266
						#將固定格式的字串分開,並回傳分開的結果。
13267
						#回傳結果:
13268
						#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13269
						#$result["error"],錯誤訊息陣列
13270
						#$result["function"],當前執行的函數名稱.
13271
						#$result["argu"],使用的參數.
13272
						#$result["oriStr"],要分割的原始字串內容
13273
						#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
13274
						#$result["dataCounts"],爲總共分成幾段
13275
						#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
13276
						#必填的參數:
13277
						#$conf["stringIn"],字串,要處理的字串.
13278
						$conf["stringProcess::spiltString"]["stringIn"]=$out;
13279
						#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
13280
						$conf["stringProcess::spiltString"]["spiltSymbol"]="Sec-WebSocket-Accept: ";
13281
						#可省略參數:
13282
						#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
13283
						$conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
13284
						$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
13285
						unset($conf["stringProcess::spiltString"]);
13286
 
13287
						#如果執行失敗
13288
						if($spiltString["status"]==="false"){
13289
 
13290
							#設置執行失敗
13291
							$result["status"]="false";
13292
 
13293
							#設置執行錯誤訊息
13294
							$result["error"]=$spiltString;
13295
 
13296
							#回傳結果
13297
							return $result;
13298
 
13299
							}#if end
13300
 
13301
						#取得Sec-WebSocket-Accept
13302
						$result["Sec-WebSocket-Accept"]=trim($spiltString["dataArray"][1]);
13303
 
13304
						#初始化要傳遞的內容			
13305
						$in="id?";
13306
 
13307
						#初始化傳遞的內容長度
13308
						$len=strlen($in);
13309
 
13310
						#設置儲存每個元素為8bit字串的陣列
13311
						$bit8=array();
13312
						$bit8[0]="10000001";
13313
						$bit8[1]="1".sprintf("%07s",base_convert($len,10,2));
13314
 
13315
						#mask key
13316
						$bit8[2]="00000000";
13317
						$bit8[3]="00000000";
13318
						$bit8[4]="00000000";
13319
						$bit8[5]="00000000";
13320
 
13321
						#mask key
13322
						$mask_key=$bit8[2].$bit8[3].$bit8[4].$bit8[5];
13323
 
13324
						#針對每個字,進行mask
13325
						for($i=0;$i<$len;$i++){
13326
 
13327
							$j=$i%4;
13328
 
13329
							$in[$i]=$in[$i] xor $mask_key[$j];
13330
 
13331
							}#for end
13332
 
13333
						#如果連線到 socket 失敗
13334
						if($socket_connect===false){
13335
 
13336
							#提示傳送資料
13337
							echo "Sending Data...".PHP_EOL;
13338
 
13339
							}#if end
13340
 
13341
						#data frame
13342
						$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;
13343
 
13344
						#將訊息傳送到socket去
13345
						socket_write($socket, $in, strlen($in));
13346
 
13347
						}#if end
13348
 
13349
					}#if end	
13350
 
13351
				}#if end
13352
 
13353
			#反之取得了 Sec-WebSocket-Accept 就結束 HTTP/1.1
13354
			else{
13355
 
13356
				#如果連線到 socket 失敗
13357
				if($socket_connect===false){
13358
 
13359
					echo "解密前的內容:".PHP_EOL;
13360
 
13361
					}#if end
13362
 
13363
				#函式說明:
13364
				#將字串中的每個字變成bytes陣列
13365
				#回傳結果:
13366
				#$result...
13367
				#必填參數:
13368
				#$conf["input"],字串,要轉換成bytes陣列的字串
13369
				$conf["stringProcess::str2bytesArray"]["input"]=$out;
13370
				#可省略參數:
13371
				#無
13372
				#建構中...
13373
				$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
13374
				unset($conf["stringProcess::str2bytesArray"]);
13375
 
13376
				#針對每個bytes				
13377
				foreach($str2bytesArray["content"] as $byte){
13378
 
13379
					#函式說明:
13380
					#將bytes數字轉換為bit字串(0跟1來表述)
13381
					#回傳結果:
13382
					#$result...
13383
					#必填參數:
13384
					#$conf["input"],字串,要轉換成byte的字串
13385
					$conf["stringProcess::str2bytesArray"]["bytes"]=$byte;
13386
					#可省略參數:
13387
					#無
13388
					#建構中...
13389
					$bytes2bitString=stringProcess::bytes2bitString($conf["stringProcess::str2bytesArray"]);
13390
					unset($conf["stringProcess::str2bytesArray"]);
13391
 
13392
					#如果連線到 socket 失敗
13393
					if($socket_connect===false){
13394
 
13395
						#debug
13396
						var_dump($bytes2bitString["content"]);
13397
 
13398
						}#if end
13399
 
13400
					}#foreach end
13401
 
13402
				#如果連線到 socket 失敗
13403
				if($socket_connect===false){
13404
 
13405
					echo "解密後接收的內容:".PHP_EOL;
13406
 
13407
					}#if end
13408
 
13409
				#函式說明:
13410
				#解密 handshake 後要接收的訊息
13411
				#回傳結果:
13412
				#$result["function"],當前函式的名稱.
13413
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
13414
				#$result["content"],unmask後的內容.
13415
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
13416
				#$result["error"],錯誤訊息陣列.
13417
				#必填參數:
13418
				#$conf["payload"],字串,要解密的訊息.
13419
				$conf["webSock::unmask"]["payload"]=$out; 
13420
				#可省略參數:
13421
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
13422
				$conf["webSock::unmask"]["allowUnmask"]="true";
13423
				#參考資料
13424
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
13425
				#https://tools.ietf.org/html/rfc6455
13426
				#https://tools.ietf.org/html/rfc5234
13427
				#備註:
13428
				#無.
13429
				$unmask=webSock::unmask($conf["webSock::unmask"]);
13430
				unset($conf["webSock::unmask"]);
13431
 
13432
				#如果執行失敗
13433
				if($unmask["status"]==="false"){
13434
 
13435
					#設置執行失敗
13436
					$result["status"]="false";
13437
 
13438
					#設置執行錯誤訊息
13439
					$result["error"]=$unmask;
13440
 
13441
					#回傳結果
13442
					return $result;
13443
 
13444
					}#if end
13445
 
13446
				#記錄接收到的內容
13447
				$received=$unmask["content"];
13448
 
13449
				#如果連線到 socket 失敗
13450
				if($socket_connect===false){	
13451
 
13452
					#debug
13453
					var_dump($received);
13454
 
13455
					}#if end
13456
 
13457
				}#else end
13458
 
13459
			#休息1秒
13460
			sleep(1);
13461
 
13462
			}#while end
13463
 
13464
		#如果連線到 socket 失敗
13465
		if($socket_connect===false){
13466
 
13467
			#提示關閉與 socket 的連線
13468
			echo "Closing socket...";
13469
 
13470
			}#if end
13471
 
13472
		#關閉與 socket 的連線
13473
		socket_close($socket);
13474
 
13475
		#如果連線到 socket 失敗
13476
		if($socket_connect===false){
13477
 
13478
			#提示關閉連線成功
13479
			echo "OK.".PHP_EOL;
13480
 
13481
			}#if end
13482
 
13483
		#設置執行正常
13484
		$result["status"]="true";
13485
 
13486
		#回傳結果
13487
		return $result;
13488
 
13489
		}#function clientDaemon end
13490
 
13491
	/*	
13492
	#函式說明:
13493
	#webSocket的javaScript用戶端
13494
	#回傳結果:
13495
	#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.
13496
	#$result["error"],錯誤訊息陣列.
13497
	#$resutl["function"],當前執行的涵式名稱.
13498
	#$result["argu"],所使用的參數.
13499
	#$result["content"],語法.
13500
	#必填參數:
13501
	#$conf["url"],字串要拜訪的web socket,請省略"ws://".
13502
	$conf["url"]="";
13503
	#可省略參數:
13504
	#$conf["entry"],字串,是否要用加密的wss,預設為"false",代表用ws,若為"true"則為wss.
13505
	#$conf["entry"]="false";
13506
	#$conf["connVar"],字串,用來儲存webSocket連線的物件名稱,預設為"conn".
13507
	#$conf["connVar"]="conn";
13508
	#參考資料:
13509
	#無.
13510
	#備註:
13511
	#無.
13512
	*/
13513
	public static function client(&$conf){
13514
 
13515
		#初始化要回傳的結果
13516
		$result=array();
13517
 
13518
		#取得當前執行的函數名稱
13519
		$result["function"]=__FUNCTION__;
13520
 
13521
		#如果沒有參數
13522
		if(func_num_args()==0){
13523
 
13524
			#設置執行失敗
13525
			$result["status"]="false";
13526
 
13527
			#設置執行錯誤訊息
13528
			$result["error"]="函數".$result["function"]."需要參數";
13529
 
13530
			#回傳結果
13531
			return $result;
13532
 
13533
			}#if end
13534
 
13535
		#取得參數
13536
		$result["argu"]=$conf;
13537
 
13538
		#如果 $conf 不為陣列
13539
		if(gettype($conf)!=="array"){
13540
 
13541
			#設置執行失敗
13542
			$result["status"]="false";
13543
 
13544
			#設置執行錯誤訊息
13545
			$result["error"][]="\$conf變數須為陣列形態";
13546
 
13547
			#如果傳入的參數為 null
13548
			if($conf===null){
13549
 
13550
				#設置執行錯誤訊息
13551
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
13552
 
13553
				}#if end
13554
 
13555
			#回傳結果
13556
			return $result;
13557
 
13558
			}#if end
13559
 
13560
		#檢查參數
13561
		#函式說明:
13562
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
13563
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13564
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
13565
		#$result["function"],當前執行的函式名稱.
13566
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
13567
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
13568
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
13569
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
13570
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
13571
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
13572
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
13573
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
13574
		#必填寫的參數:
13575
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
13576
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
13577
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
13578
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("url");
13579
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
13580
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
13581
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
13582
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
13583
		#可以省略的參數:
13584
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
13585
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
13586
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
13587
		#$conf["canNotBeEmpty"]=array();
13588
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
13589
		#$conf["canBeEmpty"]=array();
13590
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
13591
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array();
13592
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
13593
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("entry","connVar");
13594
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double"); 
13595
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
13596
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
13597
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","conn");
13598
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
13599
		#$conf["arrayCountEqualCheck"][]=array();
13600
		#參考資料來源:
13601
		#array_keys=>http://php.net/manual/en/function.array-keys.php
13602
		#建議:
13603
		#增加可省略參數全部不能為空字串或空陣列的參數功能.
13604
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
13605
		unset($conf["variableCheck::checkArguments"]);
13606
 
13607
		#如果檢查參數失敗
13608
		if($checkArguments["status"]==="false"){
13609
 
13610
			#設置執行失敗
13611
			$result["status"]="false";
13612
 
13613
			#設置執行錯誤訊息
13614
			$result["error"]=$checkArguments;
13615
 
13616
			#回傳結果
13617
			return $result;
13618
 
13619
			}#if end
13620
 
13621
		#如果參數檢查不通過
13622
		if($checkArguments["passed"]==="false"){
13623
 
13624
			#設置執行失敗
13625
			$result["status"]="false";
13626
 
13627
			#設置執行錯誤訊息
13628
			$result["error"]=$checkArguments;
13629
 
13630
			#回傳結果
13631
			return $result;
13632
 
13633
			}#if end		
13634
 
13635
		#初始化 web socket 的協定
13636
		$webSockUrl="ws://";
13637
 
13638
		#如果要加密
13639
		if($conf["entry"]==="true"){
13640
 
13641
			$webSockUrl="wss://";
13642
 
13643
			}#if end
13644
 
13645
		#設置用戶端連線到webSocket的範例
13646
		$script="<script>
13647
 
13648
			//建立 web socket 連線到 ".$webSockUrl.$conf["url"]."
13649
			var ".$conf["connVar"]." = new WebSocket('".$webSockUrl.$conf["url"]."');
13650
 
13651
			//當連線成功後
13652
			".$conf["connVar"].".onopen = function(e)
13653
			{
13654
				//印出連線成功訊息到console
13655
				console.log(\"Connection established!\");
13656
			};
13657
 
13658
			//當有收到訊息時
13659
			".$conf["connVar"].".onmessage = function(e) {
13660
 
13661
				//將訊息顯現在console
13662
				console.log(e.data);
13663
			};
13664
			</script>";
13665
 
13666
		#設置建立webSocket連線的按鈕
13667
		#函式說明:
13668
		#放置按鈕
13669
		#回傳結果:
13670
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13671
		#$result["function"],當前執行的函數.
13672
		#$result["error"],錯誤訊息陣列.
13673
		#$result["content"],按鈕語法. 
13674
		#必要的參數:
13675
		$conf["form::button"]["buttonDisplayValue"]="Send Hello!";#爲按鈕上顯示的文字。
13676
		#可省略的參數:
13677
		#$conf["buttonStyleName"]="";#可省略,爲按鈕所要使用的css樣式類別名稱,預設的css樣式爲 __simpleButtonLinkDefaultButtonCssStyle 。
13678
			#其屬性爲   "width","height","font-size","text-align"
13679
			#其屬性值爲 "100%" ,  "50"  ,    "30"   ,   "center"
13680
		$conf["form::button"]["buttonActionScriptFunction"]="conn.send('Hello!');";#可省略,爲按下按鈕時所要執行的javaScript函式或程式,預設不設定。
13681
			#"document.forms.formName.submit()"爲傳送名爲testForm的表單內容
13682
			#"window.print()"爲使用瀏覽器內建工具列印當前網頁
13683
			#若搭配 javaScript 類別的 confirmWindow 函數的回傳結果,則會有確認視窗的效果.
13684
		#$conf["buttonBorder"]="";#可省略,爲IE9內會自動產生外框,此爲外框的厚度,屬性值爲正整數,預設爲0。
13685
		#$conf["disabled"]="true";#可省略,為按鈕的功能是否要取消,若為"true"則代表要取消,若為"false"則代表功能正常,預設為"false".
13686
		#$conf["tableStart"]="true";#爲是否要表格開始。"false"代表否,"true"代表是。預設爲"false"。
13687
		#$conf["tableClass"]="";#表格要套用的css樣式,若省略的話,則預設爲 __defaultTbaleCsssStyle 其屬性爲 table-layout:fixed word-break:break-all width:100% ,須搭配 $conf["tablStart"] 與 $conf["tableEnd"] 使用。
13688
		#$conf["trStart"]="true";#爲是否要以<tr>開頭,"true"表示"是"。也可以看作新的一列開始,預設為"false".
13689
		#$conf["trClass"]="__withoutBorder";#<tr>要套用的css樣式,預設為"__withoutBorder",亦即沒有框線的樣式;"__withBorder"則爲有框線的樣式
13690
		#$conf["tdStart"]="true";#爲是否要以<td>開頭,"true"表示"是"。也可以看成列裏面的元素開始,預設為"false".
13691
		#$conf["tdClass"]="__withoutBorder";#<td>要套用的css樣式,"__withoutBorder"爲沒有框線的樣式;__withBorder爲有框線的樣式
13692
		#$conf["tdEnd"]="true";#爲是否要以</td>結尾,"true"表示"是"。也可以看成列裏面的元素結束,預設為"false".
13693
		#$conf["trEnd"]="true";#爲是否要以</tr>結尾,"true"表示"是"。也可以看作該列結束,預設為"false".
13694
		#$conf["tableEnd"]="true";#爲是否要表格結束。"false"代表否,"true"代表是,預設爲"false"。
13695
		#$conf["formStart"]="true";#爲是否要表單開始,如果爲"true"則代表要表單開始,預設為"false".
13696
		#$conf["action"]="";#爲表單要傳送到哪個頁面,須搭配$conf["formStart"]與$conf["formEnd"]參數使用
13697
		#$conf["target"]="";#為目標表單顯示的方式,若沒設定則預設爲"_self",其他可用的參數爲 "_blank"、"_parent"、"_top",也可以是iframe的名稱。須搭配$conf["formStart"]與$conf["formEnd"]參數使用
13698
		#$conf["formEnd"]="true";#爲是否要表單結束,如果爲"true"則代表要表單結束,預設為"false".
13699
		#$conf["formId"],字串,表單的id.
13700
		#$conf["formId"]="";
13701
		#$conf["buttonId"],字串,按鈕的id.
13702
		#$conf["buttonId"]="";
13703
		#參考資料來源:
13704
		#http://stackoverflow.com/questions/3014649/how-to-disable-html-button-using-javascript
13705
		$button=form::button($conf["form::button"]);
13706
		unset($conf["form::button"]);
13707
 
13708
		#如果建立按鈕失敗
13709
		if($button["status"]==="false"){
13710
 
13711
			#設置執行失敗
13712
			$result["status"]="false";
13713
 
13714
			#設置執行錯誤訊息
13715
			$result["error"]=$button;
13716
 
13717
			#回傳結果
13718
			return $result;
13719
 
13720
			}#if end	
13721
 
13722
		#設置用戶端的html與js語法
13723
		$result["content"]=$button["content"].$script;
13724
 
13725
		#設置執行正常
13726
		$result["status"]="true";
13727
 
13728
		#回傳結果
13729
		return $result;
13730
 
13731
		}#function client end
13732
 
13733
	/*
13734
	#函式說明:
13735
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
13736
	#回傳結果:
13737
	#$result["function"],當前函式的名稱.
13738
	#$result["argu"],使用的參數.
13739
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
13740
	#$result["content"],unmask後的內容.
13741
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
13742
	#$result["error"],錯誤訊息陣列.
13743
	#必填參數:
13744
	#$conf["payload"],字串,要解密的訊息.
13745
	$conf["payload"]=""; 
13746
	#可省略參數:
13747
	$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
13748
	$conf["allowUnmask"]="false";
13749
	#參考資料
13750
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
13751
	#https://tools.ietf.org/html/rfc6455
13752
	#https://tools.ietf.org/html/rfc5234
13753
	#備註:
13754
	#無.
13755
	*/
13756
	public static function mask(&$conf){
13757
 
13758
		#改呼叫 webSock::umask
13759
		return webSock::unmask($conf);
13760
 
13761
		}#function mask end
13762
 
13763
	/*
13764
	#函式說明:
13765
	#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
13766
	#回傳結果:
13767
	#$result["function"],當前函式的名稱.
13768
	#$result["argu"],使用的參數.
13769
	#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
13770
	#$result["content"],unmask後的內容.
13771
	#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
13772
	#$result["error"],錯誤訊息陣列.
13773
	#必填參數:
13774
	#$conf["payload"],字串,要解密的訊息.
13775
	$conf["payload"]=""; 
13776
	#可省略參數:
13777
	#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
13778
	#$conf["allowUnmask"]="false";
13779
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
13780
	#$conf["debug"]="false";
13781
	#參考資料
13782
	#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
13783
	#https://tools.ietf.org/html/rfc6455
13784
	#https://tools.ietf.org/html/rfc5234
13785
	#備註:
13786
	#無.
13787
	*/
13788
	public static function unmask(&$conf) {
13789
 
13790
		#初始化要回傳的結果
13791
		$result=array();
13792
 
13793
		#取得當前執行的函數名稱
13794
		$result["function"]=__FUNCTION__;
13795
 
13796
		#取得參數內容
13797
		$result["argu"]=$conf;
13798
 
13799
		#檢查參數
13800
		#函式說明:
13801
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
13802
		#回傳結果:
13803
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
13804
		#$result["error"],執行不正常結束的錯訊息陣列.
13805
		#$result["simpleError"],簡單表示的錯誤訊息.
13806
		#$result["function"],當前執行的函式名稱.
13807
		#$result["argu"],設置給予的參數.
13808
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
13809
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
13810
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
13811
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
13812
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
13813
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
13814
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
13815
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
13816
		#必填參數:
13817
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
13818
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
13819
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
13820
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
13821
		#可省略參數:
13822
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
13823
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("payload");
13824
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
13825
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
13826
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
13827
		#$conf["canBeEmptyString"]="false";
13828
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
13829
		#$conf["canNotBeEmpty"]=array();
13830
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
13831
		#$conf["canBeEmpty"]=array();
13832
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
13833
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("allowUnmask","debug");
13834
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
13835
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("allowUnmask","debug");
13836
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
13837
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");
13838
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
13839
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false");
13840
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
13841
		#$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="";
13842
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
13843
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
13844
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
13845
		#$conf["disallowAllSkipableVarNotExist"]="";
13846
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
13847
		#$conf["arrayCountEqualCheck"][]=array();
13848
		#參考資料:
13849
		#array_keys=>http://php.net/manual/en/function.array-keys.php
13850
		#備註:
13851
		#無.
13852
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
13853
		unset($conf["variableCheck::checkArguments"]);
13854
 
13855
		#如果檢查參數失敗
13856
		if($checkArguments["status"]==="false"){
13857
 
13858
			#設置執行不正常
13859
			$result["status"]="false";
13860
 
13861
			#設置錯誤訊息
13862
			$result["error"]=$checkArguments;
13863
 
13864
			#回傳結果
13865
			return $result;
13866
 
13867
			}#if end
13868
 
13869
		#如果檢查參數不通過
13870
		if($checkArguments["passed"]==="false"){
13871
 
13872
			#設置執行不正常
13873
			$result["status"]="false";
13874
 
13875
			#設置錯誤訊息
13876
			$result["error"]=$checkArguments;
13877
 
13878
			#回傳結果
13879
			return $result;
13880
 
13881
			}#if end
13882
 
13883
		#取得變數
13884
		$payload=$conf["payload"];
13885
 
13886
		#如果要debug
13887
		if($conf["debug"]==="true"){
13888
 
13889
			#debug payload length
13890
			echo __LINE__." strlen(\$payload)=".strlen($payload).PHP_EOL;
13891
 
13892
			}#if end
13893
 
13894
		#web socket frame 最少為 2bytes
13895
		if(strlen($payload)<2){
13896
 
13897
			#函式說明:
13898
			#將字串中的每個字變成hex的字串陣列
13899
			#回傳結果:
13900
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
13901
			#$result["function"],當前執行的函式內容.
13902
			#$result["error"],錯誤訊息陣列.
13903
			#$result["content"],hex的字串陣列.
13904
			#必填參數:
13905
			#$conf["input"],字串,要轉換成bytes陣列的字串.
13906
			$conf["stringProcess::str2bytesArray"]["input"]=$payload;
13907
			#可省略參數:
13908
			#無.
13909
			#參考資料:
13910
			#無.
13911
			#備註:
13912
			#無.
13913
			$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
13914
			unset($conf["stringProcess::str2bytesArray"]);
13915
 
13916
			#如果檢查參數失敗
13917
			if($str2bytesArray["status"]==="false"){
13918
 
13919
				#設置執行不正常
13920
				$result["status"]="false";
13921
 
13922
				#設置錯誤訊息
13923
				$result["error"]=$str2bytesArray;
13924
 
13925
				#回傳結果
13926
				return $result;
13927
 
13928
				}#if end
13929
 
13930
			#設置警告訊息
13931
			$result["warning"][]="web socket frame 最少為 2 bytes,目前收到得為 ".strlen($payload)." bytes";
13932
 
13933
			#設置警告訊息
13934
			$result["warning"][]="接收到的 web socket frame 內容";
13935
 
13936
			#設置警告訊息
13937
			$result["warning"][]="(ASCII):".$payload;
13938
 
13939
			#開始截取輸出
13940
			ob_start();
13941
 
13942
			#針對每個bytes
13943
			for($i=0;$i<count($str2bytesArray["content"]);$i++){
13944
 
13945
				#印出其內容
13946
				echo "[".$str2bytesArray["content"][$i]."]";
13947
 
13948
				#若不是最後一個byte
13949
				if($i===count($str2bytesArray["content"])-1){
13950
 
13951
					#空一格
13952
					echo " ";
13953
 
13954
					}#if end
13955
 
13956
				}#if end
13957
 
13958
			#取得用HEX表示的內容
13959
			$hexStr=ob_get_contents();
13960
 
13961
			#結束截取輸出
13962
			ob_end_clean();
13963
 
13964
			#設置警告訊息
13965
			$result["warning"][]="(HEX):".$hexStr;
13966
 
13967
			#設置為非 web socket frame
13968
			$result["type"]="invalid";
13969
 
13970
			#設置執行正常
13971
			$result["status"]="true";
13972
 
13973
			#回傳結果
13974
			return $result;
13975
 
13976
			}#if end
13977
 
13978
		#如果要debug
13979
		if($conf["debug"]==="true"){
13980
 
13981
			#debug data length
13982
			echo __LINE__." \$length=".(ord($payload[1]) & 127).PHP_EOL;
13983
 
13984
			}#if end
13985
 
13986
		#取得字串長度
13987
		$psl=strlen($payload);
13988
 
13989
		#初始化儲存每個bytes
13990
		$bytes=array();
13991
 
13992
		#函式說明:
13993
		#將字串中的每個字變成bytes陣列
13994
		#回傳結果:
13995
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
13996
		#$result["function"],當前執行的函式內容.
13997
		#$result["error"],錯誤訊息陣列.
13998
		#$result["content"],hex的字串陣列.
13999
		#必填參數:
14000
		#$conf["input"],字串,要轉換成bytes陣列的字串
14001
		$conf["stringProcess::str2bytesArray"]["input"]=$payload;
14002
		#可省略參數:
14003
		#無
14004
		$str2bytesArray=stringProcess::str2bytesArray($conf["stringProcess::str2bytesArray"]);
14005
		unset($conf["stringProcess::str2bytesArray"]);
14006
 
14007
		#如果執行失敗
14008
		if($str2bytesArray["status"]==="false"){
14009
 
14010
			#設置執行不正常
14011
			$result["status"]="false";
14012
 
14013
			#設置錯誤訊息
14014
			$result["error"]=$str2bytesArray;
14015
 
14016
			#回傳結果
14017
			return $result;
14018
 
14019
			}#if end
14020
 
14021
		#針對每個bytes
14022
		foreach($str2bytesArray["content"] as $bytesNum => $oneByte){
14023
 
14024
			#函式說明:
14025
			#將bytes數字轉換為bit陣列(0跟1來表述)
14026
			#回傳結果:
14027
			#$result...
14028
			#必填參數:
14029
			#$conf["input"],字串,要轉換成byte的字串
14030
			$conf["stringProcess::bytes2byte"]["bytes"]=$oneByte;
14031
			#可省略參數:
14032
			#無
14033
			$bytes2byte=stringProcess::bytes2bitString($conf["stringProcess::bytes2byte"]);
14034
			unset($conf["stringProcess::bytes2byte"]);
14035
 
14036
			#儲存bytes與其bit
14037
			$bytes[$bytesNum]["content"]=$bytes2byte["content"];
14038
 
14039
			}#foreach end
14040
 
14041
		#frame-fin 1 bit
14042
		#%x0 ; more frames of this message follow
14043
		#%x1 ; final frame of this message
14044
		$frameFin=$bytes[0]["content"][0];
14045
 
14046
		#如果不是最後一個 frame
14047
		if($frameFin==="0"){
14048
 
14049
			#如果要debug
14050
			if($conf["debug"]==="true"){
14051
 
14052
				#debug
14053
				echo __LINE__." frame-fin = 0, not supported".PHP_EOL;
14054
 
14055
				}#if end
14056
 
14057
			#設置警告訊息
14058
			$result["warning"][]="目前不支援大於一個frame的mask/unmask功能";
14059
 
14060
			#設置警告訊息
14061
			$result["warning"][]=$bytes;
14062
 
14063
			#設置為非 web socket frame
14064
			$result["type"]="invalid";
14065
 
14066
			#設置執行正常
14067
			$result["status"]="true";
14068
 
14069
			#回傳結果
14070
			return $result;
14071
 
14072
			}#if end
14073
 
14074
		#反之是最後一個 data frame
14075
		else{
14076
 
14077
			#如果要debug
14078
			if($conf["debug"]==="true"){
14079
 
14080
				#debug
14081
				echo __LINE__." frame-fin = 1, means this is a last data frame".PHP_EOL;
14082
 
14083
				}#if end
14084
 
14085
			}#else end
14086
 
14087
		#frame-rsv1 1 bit
14088
		#MUST be 0 unless negotiated otherwise
14089
		$frameRsv1=$bytes[0]["content"][1];
14090
 
14091
		#frame-rsv2 1 bit
14092
		#MUST be 0 unless negotiated otherwise
14093
		$frameRsv2=$bytes[0]["content"][2];
14094
 
14095
		#frame-rsv3 1 bit
14096
		#MUST be 0 unless negotiated otherwise
14097
		$frameRsv3=$bytes[0]["content"][3];
14098
 
14099
		#如果bit[1~3]都為0
14100
		if($frameRsv1===$frameRsv2 && $frameRsv2===$frameRsv3 && $frameRsv3==="0"){
14101
 
14102
			#如果要debug
14103
			if($conf["debug"]==="true"){
14104
 
14105
				#debug
14106
				echo __LINE__." frame-rsv1~3 = 0".PHP_EOL;
14107
 
14108
				}#if end
14109
 
14110
			}#if end
14111
 
14112
		#如果不存在第5個bit
14113
		if(!isset($bytes[0]["content"][4])){
14114
 
14115
			#如果要debug
14116
			if($conf["debug"]==="true"){
14117
 
14118
				#debug
14119
				echo __LINE__." $bytes[0]['content'][4] not set!".PHP_EOL;
14120
 
14121
				}#if end
14122
 
14123
			}#if end
14124
 
14125
		/*
14126
		frame-opcode 4 bit
14127
		frame-opcode-cont       = %x0 ; frame continuation
14128
 
14129
		frame-opcode-non-control= %x1 ; text frame
14130
					/ %x2 ; binary frame
14131
					/ %x3-7
14132
					; 4 bits in length,
14133
					; reserved for further non-control frames
14134
 
14135
		frame-opcode-control    = %x8 ; connection close
14136
					/ %x9 ; ping
14137
					/ %xA ; pong
14138
					/ %xB-F ; reserved for further control
14139
					; frames
14140
					; 4 bits in length
14141
		*/
14142
		#如果 bytes[0] 長度不足 8
14143
		if(gettype($bytes[0]["content"])==="array"){
14144
 
14145
			if(count($bytes[0]["content"])!==8){
14146
 
14147
				#$i為4~7
14148
				for($i=4;$i<8;$i++){
14149
 
14150
					#如果未設置
14151
					if(!isset($bytes[0]["content"][$i])){
14152
 
14153
						#用 "0" 去補
14154
						$bytes[0]["content"][$i]="0";
14155
 
14156
						}#if end
14157
 
14158
					}#for end
14159
 
14160
				}#if end
14161
 
14162
			}#if end
14163
 
14164
		$frameOpcode=$bytes[0]["content"][4].$bytes[0]["content"][5].$bytes[0]["content"][6].$bytes[0]["content"][7];
14165
 
14166
		#如果要debug
14167
		if($conf["debug"]==="true"){
14168
 
14169
			#debug
14170
			echo __LINE__." frame-opcode = ".$frameOpcode.PHP_EOL;
14171
 
14172
			}#if end
14173
 
14174
		$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); 
14175
 
14176
		#設置預設訊息類型為 unknow
14177
		$result["type"]="unknow";
14178
 
14179
		#如果 Opcode 等於 1
14180
		if($frameOpcodeIntX===1){
14181
 
14182
			#如果要debug
14183
			if($conf["debug"]==="true"){
14184
 
14185
				#debug
14186
				echo "It is a text frame".PHP_EOL;
14187
 
14188
				}#if end
14189
 
14190
			#設置該訊息類型為 text
14191
			$result["type"]="text";
14192
 
14193
			}#if end
14194
 
14195
		#如果 Opcode 等於 9
14196
		else if($frameOpcodeIntX===9){
14197
 
14198
			#如果要debug
14199
			if($conf["debug"]==="true"){
14200
 
14201
				#debug
14202
				echo "It is a ping frame".PHP_EOL;
14203
 
14204
				}#if end
14205
 
14206
			#設置該訊息類型為 text
14207
			$result["type"]="ping";
14208
 
14209
			}#if end
14210
 
14211
		#如果是 pong
14212
		else if($frameOpcodeIntX===10){
14213
 
14214
			#如果要debug
14215
			if($conf["debug"]==="true"){
14216
 
14217
				#debug
14218
				echo "It is a pong frame".PHP_EOL;
14219
 
14220
				}#if end
14221
 
14222
			#設置該訊息類型為 pong
14223
			$result["type"]="pong";
14224
 
14225
			}#if end
14226
 
14227
		#frame-masked 1 bit
14228
		#%x0 ;frame is not masked, no frame-masking-key
14229
		#%x1 ;frame is masked, frame-masking-key present 1 bit in lengt
14230
		$frameMasked=$bytes[1]["content"][0]; 
14231
 
14232
		#預設收到的訊息有mask過.
14233
		$masked=true;	
14234
 
14235
		#如果沒有 masked 
14236
		if($frameMasked!=='1'){
14237
 
14238
			#如果不允許沒有設置 masked bit 
14239
			if($conf["allowUnmask"]!=="true"){
14240
 
14241
				#如果要debug
14242
				if($conf["debug"]==="true"){
14243
 
14244
					#debug
14245
					echo __LINE__." frame-masked !== 1, differ with https://tools.ietf.org/html/rfc6455#section-5.3".PHP_EOL;
14246
 
14247
					}#if end
14248
 
14249
				#設置為非 web socket frame
14250
				$result["type"]="invalid";
14251
 
14252
				#設置執行正常
14253
				$result["status"]="true";
14254
 
14255
				#回傳結果
14256
				return $result;
14257
 
14258
				}#if end
14259
 
14260
			#設置收到的訊息沒有mask過.
14261
			$masked=false;
14262
 
14263
			}#if end
14264
 
14265
		#debug
14266
		#echo __LINE__." frame-masked = ".$frameMasked.PHP_EOL;
14267
 
14268
		#frame-payload-length 7 bit, 7+16 bits, or 7+64 bits
14269
		/*
14270
		The length of the "Payload data", in bytes: if 0-125, that is the
14271
		payload length.  If 126, the following 2 bytes interpreted as a
14272
		16-bit unsigned integer are the payload length.  If 127, the
14273
		following 8 bytes interpreted as a 64-bit unsigned integer (the
14274
		most significant bit MUST be 0) are the payload length.  Multibyte
14275
		length quantities are expressed in network byte order.  Note that
14276
		in all cases, the minimal number of bytes MUST be used to encode
14277
		the length, for example, the length of a 124-byte-long string
14278
		can't be encoded as the sequence 126, 0, 124.  The payload length
14279
		is the length of the "Extension data" + the length of the
14280
		"Application data".  The length of the "Extension data" may be
14281
		zero, in which case the payload length is the length of the
14282
		"Application data".
14283
		*/
14284
		if(gettype($bytes[1]["content"])==="array"){
14285
 
14286
			if(count($bytes[1]["content"])!==8){	
14287
 
14288
				#如果要debug
14289
				if($conf["debug"]==="true"){
14290
 
14291
					#debug
14292
					echo __LINE__." payloadLengthBit length !== 8".PHP_EOL;
14293
 
14294
					}#if end
14295
 
14296
				#如果 bit 不存在,用 0 補上
14297
				for($i=1;$i<8;$i++){
14298
 
14299
					#如果未設置
14300
					if(!isset($bytes[1]["content"][$i])){
14301
 
14302
						#用"0"替代
14303
						$bytes[1]["content"][$i]="0";
14304
 
14305
						}#if end
14306
 
14307
					}#for end
14308
 
14309
				#代表是用戶在連線.
14310
				#return "client connected!";
14311
 
14312
				}#if end
14313
 
14314
			}#if end
14315
 
14316
		$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];
14317
 
14318
		#length from 0~127(0~125)
14319
		$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);
14320
 
14321
		#如果長度小於 126
14322
		if($payloadLength<126){
14323
 
14324
			#mask bit start bytes index 
14325
			$maskBitStartBytesIndex=2;
14326
 
14327
			#如果要debug
14328
			if($conf["debug"]==="true"){
14329
 
14330
				#debug
14331
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14332
 
14333
				}#if end
14334
 
14335
			}#if end
14336
 
14337
		#如果長度是 126
14338
		if($payloadLength===126){
14339
 
14340
			$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];
14341
 
14342
			#初始化 payload 長度
14343
			$payloadLength=0;
14344
 
14345
			#2次迴圈,兩個bytes
14346
			for($i=0;$i<2;$i++){
14347
 
14348
				#8次迴圈,1個byte等於8個bit
14349
				for($j=0;$j<8;$j++){
14350
 
14351
					#次方數
14352
					$k=$j+8*$i;
14353
 
14354
					#加總 payload 長度
14355
					$payloadLength=$payloadLength+$bytes[3-$i]["content"][7-$j]*pow(2,$k);
14356
 
14357
					}#for end
14358
 
14359
				}#for end
14360
 
14361
			#mask bit start bytes index 
14362
			$maskBitStartBytesIndex=4;
14363
 
14364
			#如果要debug
14365
			if($conf["debug"]==="true"){
14366
 
14367
				#debug
14368
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14369
 
14370
				}#if end
14371
 
14372
			}#if end
14373
 
14374
		#如果長度是 127	
14375
		else if($payloadLength===127){
14376
 
14377
			$payloadLengthBit="";
14378
 
14379
			#四次迴圈(4個bytes)
14380
			for($i=0;$i<4;$i++){
14381
 
14382
				#8次迴圈,1個byte等於8個bit
14383
				for($j=0;$j<8;$j++){
14384
 
14385
					$payloadLengthBit=$payloadLengthBit.$bytes[4+$i]["content"][0+$j];
14386
 
14387
					}#for end
14388
 
14389
				}#for end
14390
 
14391
			#初始化 payload 長度
14392
			$payloadLength=0;
14393
 
14394
			#四次迴圈(4個bytes)
14395
			for($i=0;$i<4;$i++){
14396
 
14397
				#8次迴圈,1個byte等於8個bit
14398
				for($j=0;$j<8;$j++){
14399
 
14400
					#次方數
14401
					$k=$j+8*$i;
14402
 
14403
					$payloadLength=$payloadLength+$bytes[7-$i]["content"][7-$j]*pow(2,$k);
14404
 
14405
					}#for end
14406
 
14407
				}#for end
14408
 
14409
			#mask bit start bytes index 
14410
			$maskBitStartBytesIndex=8;
14411
 
14412
			#如果要debug
14413
			if($conf["debug"]==="true"){
14414
 
14415
				#debug
14416
				echo __LINE__." mask bit start bytes index = ".$maskBitStartBytesIndex.PHP_EOL;
14417
 
14418
				}#if end
14419
 
14420
			}#if end	
14421
 
14422
		#如果要debug
14423
		if($conf["debug"]==="true"){
14424
 
14425
			#debug
14426
			var_dump(__LINE__,$bytes);
14427
 
14428
			#debug 提示payload的長度的2進位表示法
14429
			echo __LINE__." payload data payloadLengthBit is ".$payloadLengthBit.PHP_EOL;	
14430
 
14431
			#debug 提示payload的長度
14432
			echo __LINE__." payload data length is ".$payloadLength." bytes".PHP_EOL;
14433
 
14434
			}#if end
14435
 
14436
		#如果有mask
14437
		if($masked){
14438
 
14439
			#組合 maskBit 字串
14440
			$maskBitStr=
14441
				chr(base_convert($bytes[$maskBitStartBytesIndex]["content"],2,10)).
14442
				chr(base_convert($bytes[$maskBitStartBytesIndex+1]["content"],2,10)).
14443
				chr(base_convert($bytes[$maskBitStartBytesIndex+2]["content"],2,10)).
14444
				chr(base_convert($bytes[$maskBitStartBytesIndex+3]["content"],2,10));
14445
 
14446
			#如果要debug
14447
			if($conf["debug"]==="true"){
14448
 
14449
				#debug 提示 mask bit 字串
14450
				echo __LINE__." maskBit str is ".$maskBitStr.PHP_EOL;
14451
 
14452
				}#if end
14453
 
14454
			}#if end
14455
 
14456
		#初始化 payload data 字串
14457
		$payloadDataStr="";
14458
 
14459
		#如果有mask
14460
		if($masked){
14461
 
14462
			#有多長就跑幾次
14463
			for($i=0;$i<$payloadLength;$i++){
14464
 
14465
				#串接 masked 的 payload data.
14466
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+4+$i]["content"],2,10));
14467
 
14468
				}#for end
14469
 
14470
			#如果要debug
14471
			if($conf["debug"]==="true"){
14472
 
14473
				#debug 提示 mask bit 字串
14474
				echo __LINE__." masked payload data str is ".$payloadDataStr.PHP_EOL;
14475
 
14476
				}#if end
14477
 
14478
			#unmask payload data
14479
			for($i=0;$i<$payloadLength;$i++){
14480
 
14481
				$payloadDataStr[$i]=$payloadDataStr[$i]^$maskBitStr[$i%4];
14482
 
14483
				}#for end
14484
 
14485
			}#if end
14486
 
14487
		#反之
14488
		else{
14489
 
14490
			#有多長就跑幾次
14491
			for($i=0;$i<$payloadLength;$i++){
14492
 
14493
				#串接 masked 的 payload data.
14494
				$payloadDataStr=$payloadDataStr.chr(base_convert($bytes[$maskBitStartBytesIndex+$i]["content"],2,10));
14495
 
14496
				}#for end
14497
 
14498
			}#else end
14499
 
14500
		#取得 umask 後的內容
14501
		$result["content"]=$payloadDataStr;
14502
 
14503
		#設置執行正常
14504
		$result["status"]="true";
14505
 
14506
		#回傳結果	
14507
		return $result;
14508
 
14509
		}#function unmask end
14510
 
14511
	/*
14512
	#函式說明:
14513
	#加密 handshake 後要傳送的 webSocket 訊息 
14514
	#回傳結果:
14515
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14516
	#$result["error"],執行不正常結束的錯訊息陣列.
14517
	#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
14518
	#$result["argu"],陣列,使用的參數.
14519
	#必填參數:
14520
	#$conf["text"],字串,要加密的訊息.
14521
	$conf["text"]=""; 
14522
	#可省略參數:
14523
	#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
14524
	#$conf["payloadIsBin"]="false";
14525
	#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
14526
	#$conf["ping"]="false";
14527
	#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
14528
	#$conf["pong"]="false";
14529
	#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
14530
	#$conf["frames"]=array();
14531
	#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
14532
	#$conf["mask"]="false";
14533
	#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
14534
	#$conf["debug"]="false";
14535
	#參考資料:
14536
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
14537
	#備註:
14538
	#無.
14539
	*/
14540
	public static function encode(&$conf){
14541
 
14542
		#初始化要回傳的結果
14543
		$result=array();
14544
 
14545
		#設置當其函數名稱
14546
		$result["function"]=__FUNCTION__;
14547
 
14548
		#初始化分割好的 web socket 封包
14549
		$result["content"]=array();
14550
 
14551
		#如果 $conf 不為陣列
14552
		if(gettype($conf)!="array"){
14553
 
14554
			#設置執行失敗
14555
			$result["status"]="false";
14556
 
14557
			#設置執行錯誤訊息
14558
			$result["error"][]="\$conf變數須為陣列形態";
14559
 
14560
			#如果傳入的參數為 null
14561
			if($conf==null){
14562
 
14563
				#設置執行錯誤訊息
14564
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
14565
 
14566
				}#if end
14567
 
14568
			}#if end
14569
 
14570
		#設置放置的參數
14571
		$result["argu"]=$conf;
14572
 
14573
		#函式說明:
14574
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
14575
		#回傳結果:
14576
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
14577
		#$reuslt["error"],執行不正常結束的錯訊息陣列.
14578
		#$result["simpleError"],簡單表示的錯誤訊息.
14579
		#$result["function"],當前執行的函式名稱.
14580
		#$result["argu"],設置給予的參數.
14581
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
14582
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
14583
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
14584
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
14585
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
14586
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
14587
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
14588
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
14589
		#必填參數:
14590
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
14591
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
14592
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
14593
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
14594
		#可省略參數:
14595
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
14596
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("text");
14597
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
14598
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
14599
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
14600
		#$conf["canBeEmptyString"]="false";
14601
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
14602
		#$conf["canNotBeEmpty"]=array();
14603
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
14604
		#$conf["canBeEmpty"]=array();
14605
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
14606
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("payloadIsBin","ping","pong","mask","debug");
14607
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
14608
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("payloadIsBin","ping","pong","frames","mask","debug");
14609
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
14610
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","string","string");
14611
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
14612
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("false","false","false",array(),"false","false");
14613
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
14614
		$conf["variableCheck::checkArguments"]["disallowAllSkipableVarIsEmpty"]="false";
14615
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
14616
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
14617
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
14618
		#$conf["arrayCountEqualCheck"][]=array();
14619
		#參考資料:
14620
		#array_keys=>http://php.net/manual/en/function.array-keys.php
14621
		#備註:
14622
		#無.
14623
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
14624
		unset($conf["variableCheck::checkArguments"]);
14625
 
14626
		#如果執行失敗
14627
		if($checkArguments["status"]==="false"){
14628
 
14629
			#設置執行失敗
14630
			$result["status"]="false";
14631
 
14632
			#設置執行錯誤訊息
14633
			$result["error"]=$checkArguments;
14634
 
14635
			#回傳結果
14636
			return $result;
14637
 
14638
			}#if end
14639
 
14640
		#如果參數檢查不通過
14641
		if($checkArguments["passed"]==="false"){
14642
 
14643
			#設置執行失敗
14644
			$result["status"]="false";
14645
 
14646
			#設置執行錯誤訊息
14647
			$result["error"]=$checkArguments;
14648
 
14649
			#回傳結果
14650
			return $result;
14651
 
14652
			}#if end
14653
 
14654
		#如果是要產生 ping/pong 的訊息
14655
		if($conf["ping"]==="true" || $conf["pong"]==="true"){
14656
 
14657
			#強制將payload設置為空
14658
			$conf["text"]="";
14659
 
14660
			}#if end
14661
 
14662
		#取得payload
14663
		$text=$conf["text"];
14664
 
14665
		#取得 payload length
14666
		$length=strlen($text);
14667
 
14668
		#如果沒有payload
14669
		if($length===0){
14670
 
14671
			#初始化第一個 frame 為 最後一個 frame.
14672
			$header="1000";
14673
 
14674
			#如果是ping
14675
			if($conf["ping"]==="true"){
14676
 
14677
				#其訊息類別為 ping
14678
				$header=$header."1001";
14679
 
14680
				}#if end
14681
 
14682
			#如果是pong
14683
			else if($conf["pong"]==="true"){
14684
 
14685
				#其訊息類別為 pong
14686
				$header=$header."1010";
14687
 
14688
				}#if end
14689
 
14690
			#例外狀況
14691
			else{
14692
 
14693
				#設置執行失敗
14694
				$result["status"]="false";
14695
 
14696
				#設置執行錯誤訊息
14697
				$result["error"][]="參數 text 為空時,需要 ping or pong 參數擇一";
14698
 
14699
				#設置執行錯誤訊息
14700
				$result["error"][]=$checkArguments;
14701
 
14702
				#回傳結果
14703
				return $result;
14704
 
14705
				}#else end
14706
 
14707
			}#if end
14708
 
14709
		#反之有payload
14710
		else{
14711
 
14712
			#初始化第一個 frame 為 最後一個 frame.
14713
			$header="1000";
14714
 
14715
			#如果 payload 是 2元碼
14716
			if($conf["payloadIsBin"]==="true"){
14717
 
14718
				#設置 opecode 為 0010
14719
				$header=$header."0010";
14720
 
14721
				}#if end
14722
 
14723
			#反之為 text
14724
			else{
14725
 
14726
				#設置 opecode 為 0001
14727
				$header=$header."0001";
14728
 
14729
				}#else end
14730
 
14731
			}#else end
14732
 
14733
		#如果 payload 長度大於 125
14734
		while($length > 125){
14735
 
14736
			#初始化第一個 frame 為 不為最後一個 frame, 
14737
			$header="0000";
14738
 
14739
			#如果 payload 是 2元碼
14740
			if($conf["payloadIsBin"]==="true"){
14741
 
14742
				#設置 opecode 為 0010
14743
				$header=$header."0010";
14744
 
14745
				}#if end
14746
 
14747
			#反之為 text
14748
			else{
14749
 
14750
				#設置 opecode 為 0001
14751
				$header=$header."0001";
14752
 
14753
				}#else end
14754
 
14755
			#如果已經有前面的內容了
14756
			if(count($result["content"])>0){
14757
 
14758
				#設置為中間的 frame, 其 opcode 為 continue data.
14759
				$header="00000000";
14760
 
14761
				}#if end
14762
 
14763
			#取得125bytes
14764
			$body=substr($text,0,125);
14765
 
14766
			#函式說明:
14767
			#將2進位的8位數字字串,變成bytes字串.
14768
			#回傳結果:
14769
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14770
			#$result["function"],當前執行的函式內容.
14771
			#$result["error"],錯誤訊息陣列.
14772
			#$result["content"],bytes字串,亦即其代表的一個字.
14773
			#必填參數:
14774
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
14775
			$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
14776
			#可省略參數:
14777
			#無.
14778
			#參考資料:
14779
			#無.
14780
			#備註:
14781
			#無.
14782
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
14783
			unset($conf["stringProcess::bit2byteStr"]);
14784
 
14785
			#如果執行失敗
14786
			if($bit2byteStr["status"]==="false"){
14787
 
14788
				#設置執行失敗
14789
				$result["status"]="false";
14790
 
14791
				#設置執行錯誤訊息
14792
				$result["error"]=$bit2byteStr;
14793
 
14794
				#回傳結果
14795
				return $result;
14796
 
14797
				}#if end
14798
 
14799
			#取得該 byte 字串
14800
			$headerInByte=$bit2byteStr["content"];
14801
 
14802
			#預設不用mask
14803
			$maskBitAndLengthIntString=(string)(125);
14804
 
14805
			#如果需要mask
14806
			if($conf["mask"]==="true"){
14807
 
14808
				$maskBitAndLengthIntString=(string)(125+128);
14809
 
14810
				}#if end
14811
 
14812
			#函式說明:
14813
			#將2進位的8位數字字串,變成bytes字串.
14814
			#回傳結果:
14815
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14816
			#$result["function"],當前執行的函式內容.
14817
			#$result["error"],錯誤訊息陣列.
14818
			#$result["content"],bytes字串,亦即其代表的一個字.
14819
			#必填參數:
14820
			#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
14821
			$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($maskBitAndLengthIntString,10,2);
14822
			#可省略參數:
14823
			#無.
14824
			#參考資料:
14825
			#無.
14826
			#備註:
14827
			#無.
14828
			$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
14829
			unset($conf["stringProcess::bit2byteStr"]);
14830
 
14831
			#如果要 debug
14832
			if($conf["debug"]==="true"){
14833
 
14834
				#debug
14835
				var_dump(__LINE__,$bit2byteStr);
14836
 
14837
				}#if end
14838
 
14839
			#如果執行失敗
14840
			if($bit2byteStr["status"]==="false"){
14841
 
14842
				#設置執行失敗
14843
				$result["status"]="false";
14844
 
14845
				#設置執行錯誤訊息
14846
				$result["error"]=$bit2byteStr;
14847
 
14848
				#回傳結果
14849
				return $result;
14850
 
14851
				}#if end
14852
 
14853
			#取得該 byte 字串
14854
			$lengthInByte=$bit2byteStr["content"];
14855
 
14856
			#初始化 4 bytes mask key.
14857
			$maskKey4bytes="";
14858
 
14859
			#如果需要mask
14860
			if($conf["mask"]==="true"){
14861
 
14862
				#函式說明:
14863
				#隨機產生任意byte(s)組成的字串.
14864
				#回傳結果:
14865
				#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14866
				#$result["function"],當前執行的函式內容.
14867
				#$result["error"],錯誤訊息陣列.
14868
				#$result["content"],用字串來表示的byte(s).
14869
				#必填參數:
14870
				#無.
14871
				#可省略參數:
14872
				#$conf["length"],字串,要產生多少bytes的字串,預設為1.
14873
				$conf["stringProcess::randomByte"]["length"]="4";
14874
				#參考資料:
14875
				#無.
14876
				#備註:
14877
				#無.
14878
				$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
14879
				unset($conf["stringProcess::randomByte"]);
14880
 
14881
				#如果執行失敗
14882
				if($randomByte["status"]==="false"){
14883
 
14884
					#設置執行失敗
14885
					$result["status"]="false";
14886
 
14887
					#設置執行錯誤訊息
14888
					$result["error"]=$randomByte;
14889
 
14890
					#回傳結果
14891
					return $result;
14892
 
14893
					}#if end
14894
 
14895
				#取得隨機產生的 mask key
14896
				$maskKey4bytes=$randomByte["content"];
14897
 
14898
				#函式說明:
14899
				#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
14900
				#回傳結果:
14901
				#$result["function"],當前函式的名稱.
14902
				#$result["argu"],使用的參數.
14903
				#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
14904
				#$result["content"],unmask後的內容.
14905
				#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
14906
				#$result["error"],錯誤訊息陣列.
14907
				#必填參數:
14908
				#$conf["payload"],字串,要解密的訊息.
14909
				$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$body; 
14910
				#可省略參數:
14911
				#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
14912
				$conf["webSock::unmask"]["allowUnmask"]="true";
14913
				#參考資料
14914
				#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
14915
				#https://tools.ietf.org/html/rfc6455
14916
				#https://tools.ietf.org/html/rfc5234
14917
				#備註:
14918
				#無.
14919
				$unmask=webSock::unmask($conf["webSock::unmask"]);
14920
				unset($conf["webSock::unmask"]);
14921
 
14922
				#debug
14923
				#var_dump(__LINE__,$unmask);
14924
 
14925
				#如果執行失敗
14926
				if($unmask["status"]==="false"){
14927
 
14928
					#設置執行失敗
14929
					$result["status"]="false";
14930
 
14931
					#設置執行錯誤訊息
14932
					$result["error"]=$unmask;
14933
 
14934
					#回傳結果
14935
					return $result;
14936
 
14937
					}#if end
14938
 
14939
				#取得該段的結果
14940
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
14941
 
14942
				}#if end
14943
 
14944
			#反之
14945
			else{
14946
 
14947
				#取得該段的結果
14948
				$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$body;
14949
 
14950
				}#else end
14951
 
14952
			#取得剩下的內容
14953
			$text=substr($text,125);
14954
 
14955
			#取得 payload length
14956
			$length=strlen($text);
14957
 
14958
			}#while end
14959
 
14960
		#執行到這邊代表剩下的長度用一個 frame 即可表達
14961
 
14962
		#如果已經有內容了
14963
		if(count($result["content"])>0){
14964
 
14965
			#代表不用表示為 text frame 但要表示為最後一個 frame.
14966
			$header="10000000";
14967
 
14968
			}#if end
14969
 
14970
		#函式說明:
14971
		#將2進位的8位數字字串,變成bytes字串.
14972
		#回傳結果:
14973
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
14974
		#$result["function"],當前執行的函式內容.
14975
		#$result["error"],錯誤訊息陣列.
14976
		#$result["content"],bytes字串,亦即其代表的一個字.
14977
		#必填參數:
14978
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
14979
		$conf["stringProcess::bit2byteStr"]["8bits"]=$header;
14980
		#可省略參數:
14981
		#無.
14982
		#參考資料:
14983
		#無.
14984
		#備註:
14985
		#無.
14986
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
14987
		unset($conf["stringProcess::bit2byteStr"]);
14988
 
14989
		#如果執行失敗
14990
		if($bit2byteStr["status"]==="false"){
14991
 
14992
			#設置執行失敗
14993
			$result["status"]="false";
14994
 
14995
			#設置執行錯誤訊息
14996
			$result["error"]=$bit2byteStr;
14997
 
14998
			#回傳結果
14999
			return $result;
15000
 
15001
			}#if end
15002
 
15003
		#取得該 byte 字串
15004
		$headerInByte=$bit2byteStr["content"];
15005
 
15006
		#如果要 debug
15007
		if($conf["debug"]==="true"){
15008
 
15009
			#debug
15010
			var_dump(__LINE__,$length,base_convert($length,10,2));
15011
 
15012
			}#if end
15013
 
15014
		#如果需要mask
15015
		if($conf["mask"]==="true"){
15016
 
15017
			#增加maskbit
15018
			$length=$length+128;
15019
 
15020
			}#if end
15021
 
15022
		#函式說明:
15023
		#將2進位的8位數字字串,變成bytes字串.
15024
		#回傳結果:
15025
		#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15026
		#$result["function"],當前執行的函式內容.
15027
		#$result["error"],錯誤訊息陣列.
15028
		#$result["content"],bytes字串,亦即其代表的一個字.
15029
		#必填參數:
15030
		#$conf["8bits"],字串,要轉換成byte字串的bit數字字串,小於8位會於前頭補0,若非2進位的bit數字字串,則會報錯.
15031
		$conf["stringProcess::bit2byteStr"]["8bits"]=base_convert($length,10,2);
15032
		#可省略參數:
15033
		#無.
15034
		#參考資料:
15035
		#無.
15036
		#備註:
15037
		#無.
15038
		$bit2byteStr=stringProcess::bit2byteStr($conf["stringProcess::bit2byteStr"]);
15039
		unset($conf["stringProcess::bit2byteStr"]);
15040
 
15041
		#如果要 debug
15042
		if($conf["debug"]==="true"){
15043
 
15044
			#debug
15045
			var_dump(__LINE__,$bit2byteStr);
15046
 
15047
			}#if end
15048
 
15049
		#如果執行失敗
15050
		if($bit2byteStr["status"]==="false"){
15051
 
15052
			#設置執行失敗
15053
			$result["status"]="false";
15054
 
15055
			#設置執行錯誤訊息
15056
			$result["error"]=$bit2byteStr;
15057
 
15058
			#回傳結果
15059
			return $result;
15060
 
15061
			}#if end
15062
 
15063
		#取得該 byte 字串
15064
		$lengthInByte=$bit2byteStr["content"];
15065
 
15066
		#初始化 4 bytes mask key.
15067
		$maskKey4bytes="";
15068
 
15069
		#如果需要mask
15070
		if($conf["mask"]==="true"){
15071
 
15072
			#函式說明:
15073
			#隨機產生任意byte(s)組成的字串.
15074
			#回傳結果:
15075
			#$result["status"],執行正常與否,"false"代表不正常,"true"代表正常.
15076
			#$result["function"],當前執行的函式內容.
15077
			#$result["error"],錯誤訊息陣列.
15078
			#$result["content"],用字串來表示的byte(s).
15079
			#必填參數:
15080
			#無.
15081
			#可省略參數:
15082
			#$conf["length"],字串,要產生多少bytes的字串,預設為1.
15083
			$conf["stringProcess::randomByte"]["length"]="4";
15084
			#參考資料:
15085
			#無.
15086
			#備註:
15087
			#無.
15088
			$randomByte=stringProcess::randomByte($conf["stringProcess::randomByte"]);
15089
			unset($conf["stringProcess::randomByte"]);
15090
 
15091
			#如果執行失敗
15092
			if($randomByte["status"]==="false"){
15093
 
15094
				#設置執行失敗
15095
				$result["status"]="false";
15096
 
15097
				#設置執行錯誤訊息
15098
				$result["error"]=$randomByte;
15099
 
15100
				#回傳結果
15101
				return $result;
15102
 
15103
				}#if end
15104
 
15105
			#取得隨機產生的 mask key
15106
			$maskKey4bytes=$randomByte["content"];
15107
 
15108
			}#if end
15109
 
15110
		#函式說明:
15111
		#將 handshake 後含有 mask bit 的 web socket 訊息進行  mask/unmask.
15112
		#回傳結果:
15113
		#$result["function"],當前函式的名稱.
15114
		#$result["argu"],使用的參數.
15115
		#$result["status"],執行結果狀態,"true"代表正常;"false"代表不正常.
15116
		#$result["content"],unmask後的內容.
15117
		#$result["type"],訊息的類型,"unknow":代表未定義;"text":代表為文字訊息;"pong":代表為pong;"invalid":代表不為web socket frame.
15118
		#$result["error"],錯誤訊息陣列.
15119
		#必填參數:
15120
		#$conf["payload"],字串,要解密的訊息.
15121
		$conf["webSock::unmask"]["payload"]=$headerInByte.$lengthInByte.$maskKey4bytes.$text; 
15122
		#可省略參數:
15123
		#$conf["allowUnmask"],字串,若發現沒有設置mask bit,也要繼續執行,則為"true";反之為"false".
15124
		$conf["webSock::unmask"]["allowUnmask"]="true";
15125
		#參考資料
15126
		#http://www.inanzzz.com/index.php/post/swf8/converting-string-to-binary-and-binary-to-string-with-php
15127
		#https://tools.ietf.org/html/rfc6455
15128
		#https://tools.ietf.org/html/rfc5234
15129
		#備註:
15130
		#無.
15131
		$unmask=webSock::unmask($conf["webSock::unmask"]);
15132
		unset($conf["webSock::unmask"]);
15133
 
15134
		#如果要 debug
15135
		if($conf["debug"]==="true"){
15136
 
15137
			#debug
15138
			var_dump(__LINE__,$unmask);
15139
 
15140
			}#if end
15141
 
15142
		#如果執行失敗
15143
		if($unmask["status"]==="false"){
15144
 
15145
			#設置執行失敗
15146
			$result["status"]="false";
15147
 
15148
			#設置執行錯誤訊息
15149
			$result["error"]=$unmask;
15150
 
15151
			#回傳結果
15152
			return $result;
15153
 
15154
			}#if end
15155
 
15156
		#儲存訊息
15157
		$result["content"][]=$headerInByte.$lengthInByte.$maskKey4bytes.$unmask["content"];
15158
 
15159
		#設置執行正常
15160
		$result["status"]="true";
15161
 
15162
		#回傳結果
15163
		return $result;
15164
 
15165
		}#function encode end
15166
 
15167
	/*
15168
	函式說明:
15169
	提供webSock::nativeSocketTcpIpServer的processFuncs參數所用的函式,可以接受要求傳遞檔案的內容給用戶.
15170
	#回傳結果:
15171
	#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常,"continue"代表不適用.
15172
	#$result["error"],執行不正常結束的錯訊息陣列.
15173
	#$result["argu"],陣列,使用的參數.
15174
	#必填參數:
15175
	#$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.
15176
	$conf["data"]="";
15177
	#$conf["serverSock"],resource,web socket server socket
15178
	$conf["serverSock"]=$resource;
15179
	#$conf["clientSock"],$resource,web socket client socket
15180
	$conf["clientSock"]=$resource;
15181
	#$conf["clientInfo"],陣列,web socket client info.
15182
	$conf["clientInfo"]=array();
15183
	#$conf["clientIndex"],整數.web socket client index.
15184
	$conf["clientIndex"];
15185
	#$conf["allConn"],陣列,all web socket client info.
15186
	$conf["allConn"]=array();
15187
	#可省略參數:
15188
	#無.
15189
	#參考資料:
15190
	#https://www.rfc-editor.org/rfc/rfc6455#page-28, Web Socket Base Framing Protocol.
15191
	#備註:
15192
	#無.
15193
	*/
15194
	public static function getFileContent(&$conf){
15195
 
15196
		#初始化要回傳的結果
15197
		$result=array();
15198
 
15199
		#取得當前執行的函數名稱
15200
		$result["function"]=__FUNCTION__;
15201
 
15202
		#如果沒有參數
15203
		if(func_num_args()==0){
15204
 
15205
			#設置執行失敗
15206
			$result["status"]="false";
15207
 
15208
			#設置執行錯誤訊息
15209
			$result["error"]="函數".$result["function"]."需要參數";
15210
 
15211
			#回傳結果
15212
			return $result;
15213
 
15214
			}#if end
15215
 
15216
		#涵式說明:
15217
		#判斷當前環境為web還是cmd
15218
		#回傳結果:
15219
		#$result,"web"或"cmd"
15220
		if(csInformation::getEnv()==="web"){
15221
 
15222
			#設置執行失敗
15223
			$result["status"]="false";
15224
 
15225
			#設置執行錯誤訊息
15226
			$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";
15227
 
15228
			#回傳結果
15229
			return $result;
15230
 
15231
			}#if end
15232
 
15233
		#取得參數
15234
		$result["argu"]=$conf;
15235
 
15236
		#如果 $conf 不為陣列
15237
		if(gettype($conf)!=="array"){
15238
 
15239
			#設置執行失敗
15240
			$result["status"]="false";
15241
 
15242
			#設置執行錯誤訊息
15243
			$result["error"][]="\$conf變數須為陣列形態";
15244
 
15245
			#如果傳入的參數為 null
15246
			if(is_null($conf)){
15247
 
15248
				#設置執行錯誤訊息
15249
				$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";
15250
 
15251
				}#if end
15252
 
15253
			#回傳結果
15254
			return $result;
15255
 
15256
			}#if end
15257
 
15258
		#debug
15259
		#var_dump(__FUNCTION__,__LINE__,$conf);
15260
 
15261
		#檢查參數
15262
		#函式說明:
15263
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15264
		#回傳結果:
15265
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15266
		#$result["error"],執行不正常結束的錯訊息陣列.
15267
		#$result["simpleError"],簡單表示的錯誤訊息.
15268
		#$result["function"],當前執行的函式名稱.
15269
		#$result["argu"],設置給予的參數.
15270
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15271
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15272
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15273
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15274
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15275
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15276
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15277
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15278
		#必填參數:
15279
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15280
		$conf["variableCheck::checkArguments"]["varInput"]=&$conf;
15281
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15282
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15283
		#可省略參數:
15284
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15285
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","serverSock","clientSock","clientInfo","clientIndex","allConn");
15286
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
15287
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","resource","array","integer","array");
15288
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15289
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
15290
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15291
		#$conf["canNotBeEmpty"]=array();
15292
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15293
		#$conf["canBeEmpty"]=array();
15294
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15295
		#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("Range","partSize");
15296
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15297
		#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("Range","partSize");
15298
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15299
		#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","partSize");
15300
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15301
		#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,"1024000");
15302
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15303
		#$conf["disallowAllSkipableVarIsEmpty"]="";
15304
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15305
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15306
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
15307
		#$conf["disallowAllSkipableVarNotExist"]="";
15308
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15309
		#$conf["arrayCountEqualCheck"][]=array();
15310
		#參考資料:
15311
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15312
		#備註:
15313
		#無.
15314
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15315
		unset($conf["variableCheck::checkArguments"]);
15316
 
15317
		#debug
15318
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
15319
 
15320
		#如果執行失敗
15321
		if($checkArguments["status"]==="false"){
15322
 
15323
			#設置錯誤訊息
15324
			$result["error"]=$checkArguments;
15325
 
15326
			#var_dump,交給下個 processFuncs 處理
15327
			$result["status"]="false";
15328
 
15329
			#回傳結果
15330
			return $result;
15331
 
15332
			}#if end
15333
 
15334
		#如果檢查不通過
15335
		if($checkArguments["passed"]==="false"){
15336
 
15337
			#不處理,略過,交給下個 processFuncs 處理
15338
			$result["status"]="continue";
15339
 
15340
			#回傳結果
15341
			return $result;
15342
 
15343
			}#if end
15344
 
15345
		#檢查收到的訊息是否為json格式
15346
		$revJson=@json_decode($conf["data"]);
15347
 
15348
		#如果不是 json
15349
		if($revJson===null){
15350
 
15351
			#不處理,略過,交給下個 processFuncs 處理
15352
			$result["status"]="continue";
15353
 
15354
			#回傳結果
15355
			return $result;
15356
 
15357
			}#if enf
15358
 
15359
		#轉換為陣列
15360
		$revJson=(array)($revJson);
15361
 
15362
		#檢查參數
15363
		#函式說明:
15364
		#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.
15365
		#回傳結果:
15366
		#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15367
		#$result["error"],執行不正常結束的錯訊息陣列.
15368
		#$result["simpleError"],簡單表示的錯誤訊息.
15369
		#$result["function"],當前執行的函式名稱.
15370
		#$result["argu"],設置給予的參數.
15371
		#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
15372
		#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
15373
		#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
15374
		#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息
15375
		#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.
15376
		#$result["argu"],字串陣列,目前輸入的參數名稱陣列.
15377
		#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
15378
		#$result["notNeedVar"],字串陣列,多餘的參數名稱.
15379
		#必填參數:
15380
		#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
15381
		$conf["variableCheck::checkArguments"]["varInput"]=&$revJson;
15382
		#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
15383
		$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
15384
		#可省略參數:
15385
		#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
15386
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("Method","Host","File");
15387
		#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
15388
		$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string");
15389
		#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.
15390
		$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";
15391
		#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.
15392
		#$conf["canNotBeEmpty"]=array();
15393
		#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.
15394
		#$conf["canBeEmpty"]=array();
15395
		#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.
15396
		$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("id","Range","partSize");
15397
		#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
15398
		$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","Range","partSize");
15399
		#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
15400
		$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string");
15401
		#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
15402
		$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,null,"1024000");
15403
		#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".
15404
		#$conf["disallowAllSkipableVarIsEmpty"]="";
15405
		#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".
15406
		#$conf["disallowAllSkipableVarIsEmptyArray"]="";
15407
		#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".
15408
		#$conf["disallowAllSkipableVarNotExist"]="";
15409
		#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.
15410
		#$conf["arrayCountEqualCheck"][]=array();
15411
		#參考資料:
15412
		#array_keys=>http://php.net/manual/en/function.array-keys.php
15413
		#備註:
15414
		#無.
15415
		$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);
15416
		unset($conf["variableCheck::checkArguments"]);
15417
 
15418
		#debug
15419
		#var_dump(__FUNCTION__,__LINE__,$checkArguments);
15420
 
15421
		#如果執行失敗
15422
		if($checkArguments["status"]==="false"){
15423
 
15424
			#設置錯誤訊息
15425
			$result["error"]=$checkArguments;
15426
 
15427
			#var_dump,交給下個 processFuncs 處理
15428
			$result["status"]="false";
15429
 
15430
			#回傳結果
15431
			return $result;
15432
 
15433
			}#if end
15434
 
15435
		#如果檢查不通過
15436
		if($checkArguments["passed"]==="false"){
15437
 
15438
			#不處理,略過,交給下個 processFuncs 處理
15439
			$result["status"]="continue";
15440
 
15441
			#回傳結果
15442
			return $result;
15443
 
15444
			}#if end
15445
 
15446
		#如果是 GET Method
15447
		if($revJson["Method"]==="GET"){
15448
 
15449
			#解析 apache vhost info
15450
			#函式說明:
15451
			#使用 linux 的 httpd 指令來取得 vhost 資訊.
15452
			#回傳結果:
15453
			#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15454
			#$result["error"],錯誤訊息.
15455
			#$result["function"],當前執行的函式名稱.
15456
			#$result["content"],得到的結果陣列,每個元素可能會含有的key有ServerName、DocumentRoot、ServerAlias,其中DocumentRoot的數值會是用""包起來的路徑.
15457
			#必填參數:
15458
			#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
15459
			$conf["cmd::httpdGetVhostInfo"]["fileArgu"]=__FILE__;
15460
			#可省略參數:
15461
			#無.
15462
			#參考資料:
15463
			#無
15464
			#備註:
15465
			#無.
15466
			$httpdGetVhostInfo=cmd::httpdGetVhostInfo($conf["cmd::httpdGetVhostInfo"]);
15467
			unset($conf["cmd::httpdGetVhostInfo"]);
15468
 
15469
			#debug
15470
			#var_dump(__FUNCTION__,__LINE__,$httpdGetVhostInfo);
15471
 
15472
			#如果執行失敗
15473
			if($httpdGetVhostInfo["status"]==="false"){
15474
 
15475
				#設置錯誤訊息
15476
				$result["error"]=$httpdGetVhostInfo;
15477
 
15478
				#var_dump,交給下個 processFuncs 處理
15479
				$result["status"]="false";
15480
 
15481
				#回傳結果
15482
				return $result;
15483
 
15484
				}#if end
15485
 
15486
			#針對每個結果
15487
			foreach($httpdGetVhostInfo["content"] as $vhost){
15488
 
15489
				#如果有 ServerName
15490
				if(isset($vhost["ServerName"])){
15491
 
15492
					#如果是要找的 Host
15493
					if($vhost["ServerName"]===$revJson["Host"]){
15494
 
15495
						#如果有 DocumentRoot
15496
						if(isset($vhost["DocumentRoot"])){
15497
 
15498
							#組合要取得的檔案路徑與名稱
15499
							$file=$vhost["DocumentRoot"]."/".$revJson["File"];
15500
 
15501
							#debug
15502
							#var_dump(__LINE__,$file);
15503
 
15504
							#如果有 Range 參數
15505
							if(isset($revJson["Range"])){
15506
 
15507
								#格式參考
15508
								#bytes=0-499
15509
 
15510
								#函式說明:
15511
								#將字串特定關鍵字與其前面的內容剔除
15512
								#回傳結果:
15513
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15514
								#$result["error"],錯誤訊息陣列.
15515
								#$result["warning"],警告訊息鎮列.
15516
								#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.
15517
								#$result["function"],當前執行的函數名稱.
15518
								#$result["argu"],使用的參數.
15519
								#$result["oriStr"],要處理的原始字串內容.
15520
								#$result["content"],處理好的的字串內容.	
15521
								#必填參數:
15522
								#$conf["stringIn"],字串,要處理的字串.
15523
								$conf["stringProcess::delStrBeforeKeyWord"]["stringIn"]=$revJson["Range"];
15524
								#$conf["keyWord"],字串,特定字串.
15525
								$conf["stringProcess::delStrBeforeKeyWord"]["keyWord"]="bytes=";
15526
								#可省略參數:
15527
								#$conf["recursive"],字串,預設為"false"代表找到一個關鍵字就會停止;"true"代表會即重複執行,知道沒有關鍵字為止.
15528
								#$conf["recursive"]="true";
15529
								#$conf["lastResult"],陣列,本函式前次執行的結果,若沒有找到關鍵字,則會改回傳該內容.
15530
								#$conf["lastResult"]=$delStrBeforeKeyWord;
15531
								#參考資料:
15532
								#無.
15533
								#備註:
15534
								#無.
15535
								$delStrBeforeKeyWord=stringProcess::delStrBeforeKeyWord($conf["stringProcess::delStrBeforeKeyWord"]);
15536
								unset($conf["stringProcess::delStrBeforeKeyWord"]);
15537
 
15538
								#如果執行失敗
15539
								if($delStrBeforeKeyWord["status"]==="false"){
15540
 
15541
									#設置錯誤訊息
15542
									$result["error"]=$delStrBeforeKeyWord;
15543
 
15544
									#var_dump,交給下個 processFuncs 處理
15545
									$result["status"]="false";
15546
 
15547
									#回傳結果
15548
									return $result;
15549
 
15550
									}#if end
15551
 
15552
								#如果沒有該有的關鍵字
15553
								if($delStrBeforeKeyWord["founded"]==="false"){
15554
 
15555
									#設置錯誤訊息
15556
									$result["error"]=$delStrBeforeKeyWord;
15557
 
15558
									#var_dump,交給下個 processFuncs 處理
15559
									$result["status"]="false";
15560
 
15561
									#回傳結果
15562
									return $result;
15563
 
15564
									}#if end
15565
 
15566
								#解析 bytes start and end
15567
								#函式說明:
15568
								#將固定格式的字串分開,並回傳分開的結果.
15569
								#回傳結果:
15570
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15571
								#$result["error"],錯誤訊息陣列
15572
								#$result["function"],當前執行的函數名稱.
15573
								#$result["argu"],使用的參數.
15574
								#$result["oriStr"],要分割的原始字串內容
15575
								#$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
15576
								#$result["dataCounts"],爲總共分成幾段
15577
								#$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
15578
								#必填參數:
15579
								#$conf["stringIn"],字串,要處理的字串.
15580
								$conf["stringProcess::spiltString"]["stringIn"]=$delStrBeforeKeyWord["content"];
15581
								#$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
15582
								$conf["stringProcess::spiltString"]["spiltSymbol"]="-";
15583
								#可省略參數:
15584
								#$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
15585
								#$conf["allowEmptyStr"]="false";
15586
								#參考資料:
15587
								#無.
15588
								#備註:
15589
								#無.
15590
								$spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
15591
								unset($conf["stringProcess::spiltString"]);
15592
 
15593
								#如果執行失敗
15594
								if($spiltString["status"]==="false"){
15595
 
15596
									#設置錯誤訊息
15597
									$result["error"]=$spiltString;
15598
 
15599
									#var_dump,交給下個 processFuncs 處理
15600
									$result["status"]="false";
15601
 
15602
									#回傳結果
15603
									return $result;
15604
 
15605
									}#if end
15606
 
15607
								#如果沒有應該有的 - 符號
15608
								if($spiltString["found"]==="false"){
15609
 
15610
									#設置錯誤訊息
15611
									$result["error"]=$spiltString;
15612
 
15613
									#var_dump,交給下個 processFuncs 處理
15614
									$result["status"]="false";
15615
 
15616
									#回傳結果
15617
									return $result;
15618
 
15619
									}#if end
15620
 
15621
								#如果沒有分割成2段
15622
								if($spiltString["dataCounts"]!==2){
15623
 
15624
									#設置錯誤訊息
15625
									$result["error"]=$spiltString;
15626
 
15627
									#var_dump,交給下個 processFuncs 處理
15628
									$result["status"]="false";
15629
 
15630
									#回傳結果
15631
									return $result;
15632
 
15633
									}#if end
15634
 
15635
								#依照Range來取得檔案內容
15636
								#函式說明:
15637
								#取得檔案的部分內容
15638
								#回傳結果:
15639
								#$result["status"],"true"代表移除成功,"false"代表移除失敗.
15640
								#$result["error"],錯誤訊息陣列.
15641
								#$result["function"],當前執行的函數名稱.
15642
								#$result["cmd"],執行的指令.
15643
								#$result["content"],取得的檔案內容.
15644
								#$result["length"],取得的內容長度.
15645
								#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
15646
								#$result["mimeType"],檔案的 mime type.
15647
								#必填參數:
15648
								#$conf["file"],字串,檔案的路徑與名稱.
15649
								$conf["fileAccess::getFilePart"]["file"]=$file;
15650
								#$conf["fileArgu"],字串,__FILE__的內容.
15651
								$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
15652
								#$conf["bytes"],整數字串,要讀取多少bytes.
15653
								$conf["fileAccess::getFilePart"]["bytes"]=$spiltString["dataArray"][1]-$spiltString["dataArray"][0]+1;
15654
								#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
15655
								$conf["fileAccess::getFilePart"]["startIndex"]=$spiltString["dataArray"][0];
15656
								#可省略參數:
15657
								#無
15658
								#參考資料:
15659
								#無.
15660
								#備註:
15661
								#無
15662
								$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
15663
								unset($conf["fileAccess::getFilePart"]);
15664
 
15665
								#如果執行失敗
15666
								if($getFilePart["status"]==="false"){
15667
 
15668
									#設置錯誤訊息
15669
									$result["error"]=$getFilePart;
15670
 
15671
									#var_dump,交給下個 processFuncs 處理
15672
									$result["status"]="false";
15673
 
15674
									#回傳結果
15675
									return $result;
15676
 
15677
									}#if end
15678
 
15679
								#初始化要傳遞的訊息
15680
								$msg=array();
15681
 
15682
								#設置為最後一份了
15683
								$msg["LastPart"]="true";
15684
 
15685
								#設置資料內容類型為binary
15686
								$msg["dataType"]="binary";
15687
 
15688
								#設置內容
15689
								$msg["content"]=$getFilePart["content"];
15690
 
15691
								#設置 mimeType
15692
								$msg["mimeType"]=$getFilePart["mimeType"];
15693
 
15694
								#如果有設置 id
15695
								if(isset($revJson["id"])){
15696
 
15697
									#設置資料的 id
15698
									$msg["id"]=$revJson["id"];
15699
 
15700
									}#if end
15701
 
15702
								#函式說明:
15703
								#加密 handshake 後要傳送的訊息 
15704
								#回傳結果:
15705
								#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15706
								#$result["error"],執行不正常結束的錯訊息陣列.
15707
								#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
15708
								#$result["argu"],陣列,使用的參數.
15709
								#必填參數:
15710
								#$conf["text"],字串,要加密的訊息.
15711
								$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
15712
								#可省略參數:
15713
								#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
15714
								#$conf["webSock::encode"]["payloadIsBin"]="true";
15715
								#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
15716
								#$conf["ping"]="false";
15717
								#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
15718
								#$conf["pong"]="false";
15719
								#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
15720
								#$conf["frames"]=array();
15721
								#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
15722
								#$conf["webSock::encode"]["mask"]="false";
15723
								#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
15724
								#$conf["debug"]="false";
15725
								#參考資料:
15726
								#無.
15727
								#備註:
15728
								#無.
15729
								$talkback=webSock::encode($conf["webSock::encode"]);
15730
								unset($conf["webSock::encode"]);
15731
 
15732
								#如果執行失敗
15733
								if($talkback["status"]==="false"){
15734
 
15735
									#印出結果
15736
									var_dump($talkback);
15737
 
15738
									#結束執行
15739
									exit;
15740
 
15741
									}#if end
15742
 
15743
								#針對每個訊息的分段
15744
								foreach($talkback["content"] as $msg){
15745
 
15746
									#回傳訊息
15747
									$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
15748
 
15749
									#如果傳遞訊息給用戶失敗
15750
									if($socket_write===false){
15751
 
15752
										#取得錯誤代碼
15753
										$errorCode=socket_last_error($conf["clientSock"]);
15754
 
15755
										#設置執行失敗
15756
										$result["status"]="false";
15757
 
15758
										#設置錯誤代碼
15759
										$result["error"][]="error code:".$errorCode;
15760
 
15761
										#設置錯誤代碼說明
15762
										$result["erorr"][]="error description:".socket_strerror($errorCode);
15763
 
15764
										#回傳結果
15765
										return $result;
15766
 
15767
										}#if end
15768
 
15769
									}#foreach end
15770
 
15771
								#設置正常,結束後面函式的執行
15772
								$result["status"]="true";
15773
 
15774
								#回傳結果
15775
								return $result;
15776
 
15777
								}#if end
15778
 
15779
							#反之沒有 Rnage 參數
15780
							else{
15781
 
15782
								#執行到這邊代表要取得全部的檔案內容
15783
 
15784
								#debug
15785
								#var_dump(__LINE__,"get full file content");
15786
 
15787
								#第一部分的編號
15788
								$partNo=0;
15789
 
15790
								#無窮迴圈
15791
								while(true){
15792
 
15793
									#分段取得檔案
15794
									#函式說明:
15795
									#取得檔案的部分內容
15796
									#回傳結果:
15797
									#$result["status"],"true"代表移除成功,"false"代表移除失敗.
15798
									#$result["error"],錯誤訊息陣列.
15799
									#$result["function"],當前執行的函數名稱.
15800
									#$result["cmd"],執行的指令.
15801
									#$result["content"],取得的檔案內容.
15802
									#$result["length"],取得的內容長度.
15803
									#$result["EOF"],識別是否已經到檔案結尾,"true"代表是,"false"代表不是.
15804
									#$result["mimeType"],檔案的 mime type.
15805
									#必填參數:
15806
									#$conf["file"],字串,檔案的路徑與名稱.
15807
									$conf["fileAccess::getFilePart"]["file"]=$file;
15808
									#$conf["fileArgu"],字串,__FILE__的內容.
15809
									$conf["fileAccess::getFilePart"]["fileArgu"]=__FILE__;
15810
									#$conf["bytes"],整數字串,要讀取多少bytes.
15811
									$conf["fileAccess::getFilePart"]["bytes"]=$revJson["partSize"];
15812
									#$conf["startIndex"],要從哪個bytes位置開始,起始點為0.
15813
									$conf["fileAccess::getFilePart"]["startIndex"]=$partNo*$revJson["partSize"];
15814
									#可省略參數:
15815
									#無
15816
									#參考資料:
15817
									#無.
15818
									#備註:
15819
									#無
15820
									$getFilePart=fileAccess::getFilePart($conf["fileAccess::getFilePart"]);
15821
									unset($conf["fileAccess::getFilePart"]);
15822
 
15823
									#debug
15824
									#var_dump(__LINE__,$getFilePart);
15825
 
15826
									#如果執行失敗
15827
									if($getFilePart["status"]==="false"){
15828
 
15829
										#設置錯誤訊息
15830
										$result["error"]=$getFilePart;
15831
 
15832
										#var_dump,交給下個 processFuncs 處理
15833
										$result["status"]="false";
15834
 
15835
										#回傳結果
15836
										return $result;
15837
 
15838
										}#if end
15839
 
15840
									#初始化要傳遞的訊息
15841
									$msg=array();
15842
 
15843
									#設置不為最後一份
15844
									$msg["LastPart"]="false";
15845
 
15846
									#設置資料內容類型為binary
15847
									$msg["dataType"]="binary";
15848
 
15849
									#設置內容
15850
									$msg["content"]=$getFilePart["content"];
15851
 
15852
									#設置 mimeType
15853
									$msg["mimeType"]=$getFilePart["mimeType"];
15854
 
15855
									#如果有設置 id
15856
									if(isset($revJson["id"])){
15857
 
15858
										#設置資料的 id
15859
										$msg["id"]=$revJson["id"];
15860
 
15861
										}#if end
15862
 
15863
									#如果偵測到檔案結尾
15864
									if($getFilePart["EOF"]==="true"){
15865
 
15866
										#設置為最後一份了
15867
										$msg["LastPart"]="true";
15868
 
15869
										#如果沒有內容
15870
										if($getFilePart["length"]===0){
15871
 
15872
											#檔案區塊數字-1
15873
											$partNo--;
15874
 
15875
											}#if end
15876
 
15877
										#傳遞給 client - start
15878
 
15879
										#編碼後的訊息
15880
										$msgEncoded=base64_encode(urlencode(json_encode($msg)));
15881
 
15882
										#debug
15883
										#var_dump(__LINE__,$msg,$msgEncoded);
15884
 
15885
										#函式說明:
15886
										#加密 handshake 後要傳送的訊息 
15887
										#回傳結果:
15888
										#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15889
										#$result["error"],執行不正常結束的錯訊息陣列.
15890
										#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
15891
										#$result["argu"],陣列,使用的參數.
15892
										#必填參數:
15893
										#$conf["text"],字串,要加密的訊息.
15894
										$conf["webSock::encode"]["text"]=$msgEncoded; 
15895
										#可省略參數:
15896
										#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
15897
										#$conf["webSock::encode"]["payloadIsBin"]="false";
15898
										#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
15899
										#$conf["ping"]="false";
15900
										#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
15901
										#$conf["pong"]="false";
15902
										#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
15903
										#$conf["frames"]=array();
15904
										#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
15905
										#$conf["webSock::encode"]["mask"]="false";
15906
										#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
15907
										#$conf["debug"]="false";
15908
										#參考資料:
15909
										#無.
15910
										#備註:
15911
										#無.
15912
										$talkback=webSock::encode($conf["webSock::encode"]);
15913
										unset($conf["webSock::encode"]);
15914
 
15915
										#debug
15916
										#var_dump(__LINE__,$talkback);
15917
 
15918
										#如果執行失敗
15919
										if($talkback["status"]==="false"){
15920
 
15921
											#印出結果
15922
											var_dump($talkback);
15923
 
15924
											#結束執行
15925
											exit;
15926
 
15927
											}#if end
15928
 
15929
										#針對每個訊息的分段
15930
										foreach($talkback["content"] as $msg){
15931
 
15932
											#回傳訊息
15933
											$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
15934
 
15935
											#debug
15936
											#var_dump(__LINE__,$socket_write,$msg);
15937
 
15938
											#如果傳遞訊息給用戶失敗
15939
											if($socket_write===false){
15940
 
15941
												#取得錯誤代碼
15942
												$errorCode=socket_last_error($conf["clientSock"]);
15943
 
15944
												#設置執行失敗
15945
												$result["status"]="false";
15946
 
15947
												#設置錯誤代碼
15948
												$result["error"][]="error code:".$errorCode;
15949
 
15950
												#設置錯誤代碼說明
15951
												$result["erorr"][]="error description:".socket_strerror($errorCode);
15952
 
15953
												#回傳結果
15954
												return $result;
15955
 
15956
												}#if end
15957
 
15958
											}#foreach end
15959
 
15960
										#傳遞給 client - end
15961
 
15962
										#結束 while
15963
										break;
15964
 
15965
										}#if end
15966
 
15967
									#傳遞給 client - start
15968
 
15969
									#debug
15970
									#var_dump(__LINE__,"start tranfer");
15971
 
15972
									#函式說明:
15973
									#加密 handshake 後要傳送的訊息 
15974
									#回傳結果:
15975
									#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
15976
									#$result["error"],執行不正常結束的錯訊息陣列.
15977
									#$result["content"],陣列,加密 handshake 後要傳送給 client 的訊息,若有多個代表要分為多個 Fragmentation 來依序傳送.
15978
									#$result["argu"],陣列,使用的參數.
15979
									#必填參數:
15980
									#$conf["text"],字串,要加密的訊息.
15981
									$conf["webSock::encode"]["text"]=base64_encode(urlencode(json_encode($msg))); 
15982
									#可省略參數:
15983
									#$conf["payloadIsBin"],字串,"true"定義Payload data是為2元碼;預設為"false"代表為文字.
15984
									#$conf["webSock::encode"]["payloadIsBin"]="true";
15985
									#$conf["ping"],字串,"true"代表為ping訊息;反之為"false",預設為"false".
15986
									#$conf["ping"]="false";
15987
									#$conf["pong"],字串,"true"代表為pong訊息;反之為"false",預設為"false".
15988
									#$conf["pong"]="false";
15989
									#$conf["frames"],陣列,目前既有的訊息frame,預設為空陣列,代表沒有.
15990
									#$conf["frames"]=array();
15991
									#$conf["mask"],字串,代表是否要將內容進行mask,預設為"false",代表不要,適用於server to client;反之為"true"代表要,適用於client to server.
15992
									#$conf["webSock::encode"]["mask"]="false";
15993
									#$conf["debug"],字串,"true"代表要show debug訊息;反之為預設"false".
15994
									#$conf["debug"]="false";
15995
									#參考資料:
15996
									#無.
15997
									#備註:
15998
									#無.
15999
									$talkback=webSock::encode($conf["webSock::encode"]);
16000
									unset($conf["webSock::encode"]);
16001
 
16002
									#如果執行失敗
16003
									if($talkback["status"]==="false"){
16004
 
16005
										#印出結果
16006
										var_dump($talkback);
16007
 
16008
										#結束執行
16009
										exit;
16010
 
16011
										}#if end
16012
 
16013
									#針對每個訊息的分段
16014
									foreach($talkback["content"] as $msg){
16015
 
16016
										#回傳訊息
16017
										$socket_write=socket_write($conf["clientSock"], $msg, strlen($msg));
16018
 
16019
										#如果傳遞訊息給用戶失敗
16020
										if($socket_write===false){
16021
 
16022
											#取得錯誤代碼
16023
											$errorCode=socket_last_error($conf["clientSock"]);
16024
 
16025
											#設置執行失敗
16026
											$result["status"]="false";
16027
 
16028
											#設置錯誤代碼
16029
											$result["error"][]="error code:".$errorCode;
16030
 
16031
											#設置錯誤代碼說明
16032
											$result["erorr"][]="error description:".socket_strerror($errorCode);
16033
 
16034
											#回傳結果
16035
											return $result;
16036
 
16037
											}#if end
16038
 
16039
										}#foreach end
16040
 
16041
									#傳遞給 client - end
16042
 
16043
									#檔案區塊數字+1
16044
									$partNo++;
16045
 
16046
									}#while end
16047
 
16048
								#設置執行正常
16049
								$result["status"]="true";
16050
 
16051
								#回傳結果
16052
								return $result;
16053
 
16054
								}#else end
16055
 
16056
							}#if end
16057
 
16058
						}#if end
16059
 
16060
					}#if end
16061
 
16062
				}#foreach end
16063
 
16064
			#設置執行不正常
16065
			$result["status"]="false";
16066
 
16067
			#設置執行錯誤
16068
			$result["error"]="no matched ServerName";
16069
 
16070
			#debug
16071
			var_dump(__FUNCTION__,__LINE__,$result);	
16072
 
16073
			#回傳結果
16074
			return $result;
16075
 
16076
			}#if end
16077
 
16078
		#設置執行不正常
16079
		$result["status"]="false";
16080
 
16081
		#設置執行錯誤
16082
		$result["error"]="Method should be GET";
16083
 
16084
		#回傳結果
16085
		return $result;
16086
 
16087
		}#function getFileContent end
16088
 
16089
	}#class webSock end
16090
 
16091
?>