Subversion Repositories qbpwcf-lib(archive)

Rev

Rev 915 | Details | Compare with Previous | Last modification | View Log | RSS feed

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