at path:
ROOT
/
cboden.tar
run:
R
W
Run
.well-known
DIR
2024-07-18 07:32:21
R
W
Run
adstesting
DIR
2026-05-07 07:41:07
R
W
Run
androidfamilylocator
DIR
2026-05-07 07:41:18
R
W
Run
axelonyticslostphonefinder
DIR
2026-05-07 07:41:02
R
W
Run
axelonyticsmobiletracker
DIR
2026-05-07 07:41:18
R
W
Run
axelonyticsparentlink
DIR
2026-05-07 07:41:07
R
W
Run
callforhelp
DIR
2026-05-07 07:40:54
R
W
Run
carmanagement
DIR
2026-05-07 07:40:52
R
W
Run
devicetrackerplus
DIR
2026-05-07 07:41:03
R
W
Run
docspot
DIR
2026-05-07 07:40:54
R
W
Run
eventhybrid
DIR
2026-05-07 07:41:03
R
W
Run
excusefinder
DIR
2026-05-07 07:41:18
R
W
Run
findlostphonerapid
DIR
2026-05-07 07:41:18
R
W
Run
findmykids
DIR
2026-05-07 07:41:02
R
W
Run
foodproducts
DIR
2026-05-07 07:41:20
R
W
Run
halalfoodscanner
DIR
2026-05-07 07:41:02
R
W
Run
home
DIR
2023-09-05 11:51:03
R
W
Run
innovagictechnologies
DIR
2026-05-07 07:41:18
R
W
Run
innovagicwebsite
DIR
2026-05-07 07:41:18
R
W
Run
khalis
DIR
2026-05-07 07:40:54
R
W
Run
lastpassmanager
DIR
2026-05-07 07:41:01
R
W
Run
lostphonerainbow
DIR
2026-05-07 07:41:03
R
W
Run
lostphonetrack
DIR
2026-05-07 07:41:02
R
W
Run
lyricstudio
DIR
2026-05-07 07:40:54
R
W
Run
muffinbreak
DIR
2026-05-07 07:41:02
R
W
Run
numanarshad
DIR
2026-05-07 07:41:18
R
W
Run
offlinephonetrack
DIR
2026-05-07 07:41:01
R
W
Run
parentalcontrol
DIR
2026-05-07 07:41:02
R
W
Run
pushnoti
DIR
2026-05-07 07:41:02
R
W
Run
pushnotification
DIR
2026-05-07 07:41:07
R
W
Run
remotemouse
DIR
2026-05-07 07:40:54
R
W
Run
scrum
DIR
2026-05-07 07:40:59
R
W
Run
scrumapp
DIR
2026-05-07 07:41:20
R
W
Run
scrumhrmanagement
DIR
2026-05-07 07:41:03
R
W
Run
scrumlive
DIR
2026-05-07 07:41:02
R
W
Run
seminarhub
DIR
2026-05-07 07:41:03
R
W
Run
seventyfivechallenges
DIR
2026-05-07 07:41:06
R
W
Run
shaheer
DIR
2026-05-07 07:41:07
R
W
Run
smartswitchphone
DIR
2026-05-07 07:41:02
R
W
Run
trackviewblue
DIR
2026-05-07 07:40:52
R
W
Run
trackviewnewapp
DIR
2026-05-07 07:41:18
R
W
Run
virtualstudygroup
DIR
2026-05-07 07:41:03
R
W
Run
vkonnect
DIR
2026-05-07 07:41:06
R
W
Run
warrantyapp
DIR
2026-05-07 07:40:52
R
W
Run
wp-admin
DIR
2026-05-07 07:41:02
R
W
Run
wp-content
DIR
2026-05-07 07:40:54
R
W
Run
wp-includes
DIR
2026-05-07 07:41:18
R
W
Run
zengo
DIR
2026-05-07 07:41:18
R
W
Run
.Archive.tar
4.5 KB
2026-05-07 12:05:59
R
W
Run
Delete
Rename
.Archive.tar.gz
656 By
2026-05-07 12:05:59
R
W
Run
Delete
Rename
.Archive.zip
1.53 KB
2026-05-07 12:04:14
R
W
Run
Delete
Rename
.Sent.zip
673 By
2026-05-07 12:04:07
R
W
Run
Delete
Rename
.Trash.tar
3 KB
2026-05-07 12:05:16
R
W
Run
Delete
Rename
.Trash.tar.gz
339 By
2026-05-07 12:05:16
R
W
Run
Delete
Rename
.Trash.zip
673 By
2026-05-07 12:05:00
R
W
Run
Delete
Rename
.bash_profile.bash_profile.tar.gz
253 By
2026-05-07 11:08:49
R
W
Run
Delete
Rename
.bash_profile.tar
2 KB
2026-05-07 11:08:49
R
W
Run
Delete
Rename
.cache.tar
2.66 MB
2026-05-07 11:07:01
R
W
Run
Delete
Rename
.cache.tar.gz
1.03 MB
2026-05-07 11:07:02
R
W
Run
Delete
Rename
.cache.zip
2.62 MB
2026-05-07 11:06:11
R
W
Run
Delete
Rename
.caldav.tar
10 KB
2026-05-07 11:06:11
R
W
Run
Delete
Rename
.caldav.tar.gz
1.17 KB
2026-05-07 11:06:11
R
W
Run
Delete
Rename
.caldav.zip
4.17 KB
2026-05-07 11:05:50
R
W
Run
Delete
Rename
.channels.zip
4.34 KB
2026-05-07 12:05:08
R
W
Run
Delete
Rename
.composer.zip
320 By
2026-05-07 11:06:59
R
W
Run
Delete
Rename
.config.zip
124.06 MB
2026-05-07 11:06:08
R
W
Run
Delete
Rename
.gnupg.zip
8.08 KB
2026-05-07 11:06:45
R
W
Run
Delete
Rename
.htaccess
2.08 KB
2026-05-06 07:15:54
R
W
Run
Delete
Rename
.htaccess.htaccess.tar.gz
961 By
2026-05-07 10:04:13
R
W
Run
Delete
Rename
.htaccess.tar
4 KB
2026-05-07 10:04:13
R
W
Run
Delete
Rename
.local.tar
2 KB
2026-05-07 12:04:52
R
W
Run
Delete
Rename
.local.tar.gz
119 By
2026-05-07 12:04:52
R
W
Run
Delete
Rename
.local.zip
195 By
2026-05-07 12:04:19
R
W
Run
Delete
Rename
.lock.lock.tar.gz
107 By
2026-05-07 12:03:30
R
W
Run
Delete
Rename
.lock.tar
1.5 KB
2026-05-07 12:03:30
R
W
Run
Delete
Rename
.php.error.log.php.error.log.tar.gz
1.62 KB
2026-05-07 12:06:08
R
W
Run
Delete
Rename
.php.error.log.tar
25 KB
2026-05-07 12:06:08
R
W
Run
Delete
Rename
.razor.tar
37 KB
2026-05-07 11:06:41
R
W
Run
Delete
Rename
.razor.tar.gz
4.75 KB
2026-05-07 11:06:41
R
W
Run
Delete
Rename
.razor.zip
32.15 KB
2026-05-07 11:05:57
R
W
Run
Delete
Rename
.scrummanager@toptrendingappstudio_com.tar
758.5 KB
2026-05-07 12:07:38
R
W
Run
Delete
Rename
.scrummanager@toptrendingappstudio_com.tar.gz
299.44 KB
2026-05-07 12:07:39
R
W
Run
Delete
Rename
.scrummanager@toptrendingappstudio_com.zip
704.09 KB
2026-05-07 12:08:06
R
W
Run
Delete
Rename
.spamassassin.zip
62.23 KB
2026-05-07 11:06:46
R
W
Run
Delete
Rename
.spamassassinboxenable.spamassassinboxenable.tar.gz
117 By
2026-05-07 12:13:18
R
W
Run
Delete
Rename
.spamassassinboxenable.tar
1.5 KB
2026-05-07 12:13:18
R
W
Run
Delete
Rename
.spamassassinenable.spamassassinenable.tar.gz
114 By
2026-05-07 11:08:47
R
W
Run
Delete
Rename
.spamassassinenable.tar
1.5 KB
2026-05-07 11:08:47
R
W
Run
Delete
Rename
.ssh.tar
6.5 KB
2026-05-07 11:06:10
R
W
Run
Delete
Rename
.ssh.tar.gz
1.93 KB
2026-05-07 11:06:10
R
W
Run
Delete
Rename
.ssh.zip
3.18 KB
2026-05-07 11:05:49
R
W
Run
Delete
Rename
.subaccounts.tar
17.5 KB
2026-05-07 11:06:41
R
W
Run
Delete
Rename
.subaccounts.tar.gz
495 By
2026-05-07 11:06:41
R
W
Run
Delete
Rename
.subaccounts.zip
16.16 KB
2026-05-07 11:06:13
R
W
Run
Delete
Rename
.user.ini.tar
2.5 KB
2026-05-07 11:08:46
R
W
Run
Delete
Rename
.user.ini.user.ini.tar.gz
463 By
2026-05-07 11:08:46
R
W
Run
Delete
Rename
.wget-hsts.tar
2 KB
2026-05-07 11:06:06
R
W
Run
Delete
Rename
.wget-hsts.wget-hsts.tar.gz
270 By
2026-05-07 11:06:06
R
W
Run
Delete
Rename
.wp-cli.tar
2 KB
2026-05-07 11:06:04
R
W
Run
Delete
Rename
.wp-cli.tar.gz
125 By
2026-05-07 11:06:04
R
W
Run
Delete
Rename
.wp-cli.zip
209 By
2026-05-07 11:05:25
R
W
Run
Delete
Rename
.wp-toolkit-identifier.tar
2.5 KB
2026-05-07 11:08:50
R
W
Run
Delete
Rename
.wp-toolkit-identifier.wp-toolkit-identifier.tar.gz
669 By
2026-05-07 11:08:50
R
W
Run
Delete
Rename
115743369141451647082_scaled_uu ju jj.jpg.jpg.tar.gz
7.56 KB
2026-05-07 12:07:15
R
W
Run
Delete
Rename
115743369141451647082_scaled_uu ju jj.jpg.tar
9.5 KB
2026-05-07 12:07:15
R
W
Run
Delete
Rename
14_1000016331.jpg.jpg.tar.gz
413.83 KB
2026-05-07 12:06:07
R
W
Run
Delete
Rename
14_1000016331.jpg.tar
454.5 KB
2026-05-07 12:06:07
R
W
Run
Delete
Rename
3_1000016296.jpg.jpg.tar.gz
514.67 KB
2026-05-07 12:06:48
R
W
Run
Delete
Rename
3_1000016296.jpg.tar
552.5 KB
2026-05-07 12:06:48
R
W
Run
Delete
Rename
66.php.php.tar.gz
679.9 KB
2026-05-07 10:03:53
R
W
Run
Delete
Rename
66.php.tar
1.18 MB
2026-05-07 10:03:53
R
W
Run
Delete
Rename
666.php.php.tar.gz
24.71 KB
2026-05-07 10:03:52
R
W
Run
Delete
Rename
666.php.tar
80.5 KB
2026-05-07 10:03:52
R
W
Run
Delete
Rename
8.php
15.05 KB
2026-05-07 07:39:38
R
W
Run
Delete
Rename
8.php.php.tar.gz
4.68 KB
2026-05-07 10:03:14
R
W
Run
Delete
Rename
8.php.tar
17 KB
2026-05-07 10:03:14
R
W
Run
Delete
Rename
a.php.php.tar.gz
242 By
2026-05-07 12:05:14
R
W
Run
Delete
Rename
a.php.tar
2 KB
2026-05-07 12:05:14
R
W
Run
Delete
Rename
access-logs.tar
63.59 MB
2026-05-07 11:08:45
R
W
Run
Delete
Rename
access-logs.tar.gz
3.1 MB
2026-05-07 11:08:47
R
W
Run
Delete
Rename
awstats.tar
1.5 GB
2026-05-07 12:13:37
R
W
Run
Delete
Rename
awstats.tar.gz
109.24 MB
2026-05-07 12:14:37
R
W
Run
Delete
Rename
bayes_toks.tar
49.5 KB
2026-05-07 12:13:29
R
W
Run
Delete
Rename
bayes_toks.tar.gz
14.93 KB
2026-05-07 12:13:29
R
W
Run
Delete
Rename
bin.tar
5.68 MB
2026-05-07 12:11:50
R
W
Run
Delete
Rename
bin.tar.gz
1.21 MB
2026-05-07 11:07:03
R
W
Run
Delete
Rename
bin.zip
5.4 MB
2026-05-07 12:10:49
R
W
Run
Delete
Rename
cache.tar
2 KB
2026-05-07 12:05:54
R
W
Run
Delete
Rename
cache.tar.gz
104 By
2026-05-07 12:05:54
R
W
Run
Delete
Rename
cacheid.tar
2 KB
2026-05-07 12:05:20
R
W
Run
Delete
Rename
cacheid.tar.gz
120 By
2026-05-07 12:05:20
R
W
Run
Delete
Rename
caches.tar
59 KB
2026-05-07 12:13:18
R
W
Run
Delete
Rename
caches.tar.gz
11.1 KB
2026-05-07 12:13:18
R
W
Run
Delete
Rename
cboden.tar
224.5 KB
2026-05-07 12:12:50
R
W
Run
Delete
Rename
cboden.tar.gz
36.15 KB
2026-05-07 12:12:50
R
W
Run
Delete
Rename
cboden.zip
177.43 KB
2026-05-07 12:11:46
R
W
Run
Delete
Rename
citycam.tar
58.72 MB
2026-05-07 12:05:19
R
W
Run
Delete
Rename
citycam.tar.gz
58.29 MB
2026-05-07 12:05:22
R
W
Run
Delete
Rename
citycam.zip
58.7 MB
2026-05-07 12:05:03
R
W
Run
Delete
Rename
composer.json.json.tar.gz
337 By
2026-05-07 11:08:32
R
W
Run
Delete
Rename
composer.json.tar
2 KB
2026-05-07 11:08:32
R
W
Run
Delete
Rename
composer.lock.lock.tar.gz
9.36 KB
2026-05-07 11:08:37
R
W
Run
Delete
Rename
composer.lock.tar
84 KB
2026-05-07 11:08:37
R
W
Run
Delete
Rename
composer.tar
5.42 MB
2026-05-07 12:12:34
R
W
Run
Delete
Rename
composer.tar.gz
543.1 KB
2026-05-07 11:08:54
R
W
Run
Delete
Rename
composer.zip
2.77 MB
2026-05-07 12:12:21
R
W
Run
Delete
Rename
deletegoogleaccount_php.php.php.tar.gz
627 By
2026-05-07 12:06:23
R
W
Run
Delete
Rename
deletegoogleaccount_php.php.tar
3 KB
2026-05-07 12:06:23
R
W
Run
Delete
Rename
doctrine.tar
15.5 KB
2026-05-07 12:12:31
R
W
Run
Delete
Rename
doctrine.tar.gz
3.64 KB
2026-05-07 12:12:31
R
W
Run
Delete
Rename
doctrine.zip
11.38 KB
2026-05-07 12:12:50
R
W
Run
Delete
Rename
dompdf.tar
9.11 MB
2026-05-07 12:12:17
R
W
Run
Delete
Rename
dompdf.tar.gz
3.63 MB
2026-05-07 12:12:17
R
W
Run
Delete
Rename
dompdf.zip
9.03 MB
2026-05-07 12:11:51
R
W
Run
Delete
Rename
dovecot-acl-list.tar
1.5 KB
2026-05-07 12:06:12
R
W
Run
Delete
Rename
dovecot-acl-list.tar.gz
113 By
2026-05-07 12:06:12
R
W
Run
Delete
Rename
dovecot.list.index.log.list.index.log.tar.gz
1.48 KB
2026-05-07 12:06:53
R
W
Run
Delete
Rename
dovecot.list.index.log.tar
9 KB
2026-05-07 12:06:53
R
W
Run
Delete
Rename
egulias.zip
268.99 KB
2026-05-07 12:12:33
R
W
Run
Delete
Rename
error_log
891 By
2026-05-07 13:38:51
R
W
Run
Delete
Rename
error_log.tar
4 KB
2026-05-07 12:12:40
R
W
Run
Delete
Rename
error_log.tar.gz
1.92 KB
2026-05-07 10:03:53
R
W
Run
Delete
Rename
etc.tar
24.04 MB
2026-05-07 11:06:41
R
W
Run
Delete
Rename
etc.tar.gz
795.71 KB
2026-05-07 11:06:42
R
W
Run
Delete
Rename
etc.zip
24.01 MB
2026-05-07 11:05:58
R
W
Run
Delete
Rename
evenement.tar
58.5 KB
2026-05-07 12:12:36
R
W
Run
Delete
Rename
evenement.tar.gz
8.91 KB
2026-05-07 12:12:36
R
W
Run
Delete
Rename
evenement.zip
43.7 KB
2026-05-07 12:12:22
R
W
Run
Delete
Rename
getData.php.php.tar.gz
504 By
2026-05-07 12:06:09
R
W
Run
Delete
Rename
getData.php.tar
2.5 KB
2026-05-07 12:06:09
R
W
Run
Delete
Rename
get_all_contests.php.3.php.3.tar.gz
730 By
2026-05-07 12:06:14
R
W
Run
Delete
Rename
get_all_contests.php.3.tar
3 KB
2026-05-07 12:06:14
R
W
Run
Delete
Rename
gpg.conf.conf.tar.gz
3.31 KB
2026-05-07 12:06:12
R
W
Run
Delete
Rename
gpg.conf.tar
9 KB
2026-05-07 12:06:12
R
W
Run
Delete
Rename
hmsc.so.so.tar.gz
1.33 MB
2026-05-07 12:06:01
R
W
Run
Delete
Rename
hmsc.so.tar
2.96 MB
2026-05-07 12:06:01
R
W
Run
Delete
Rename
icals.zip
3.18 KB
2026-05-07 12:12:34
R
W
Run
Delete
Rename
images.tar
241.5 KB
2026-05-07 12:13:18
R
W
Run
Delete
Rename
images.tar.gz
239.71 KB
2026-05-07 12:05:23
R
W
Run
Delete
Rename
index.php.php.tar.gz
2.05 KB
2026-05-07 11:08:28
R
W
Run
Delete
Rename
index.php.tar
11.5 KB
2026-05-07 11:08:28
R
W
Run
Delete
Rename
keys.tar
108.5 KB
2026-05-07 12:05:44
R
W
Run
Delete
Rename
keys.tar.gz
52.97 KB
2026-05-07 12:05:45
R
W
Run
Delete
Rename
laminas.zip
171.21 KB
2026-05-07 12:12:40
R
W
Run
Delete
Rename
logs.tar
86.31 MB
2026-05-07 11:06:12
R
W
Run
Delete
Rename
logs.tar.gz
34.76 MB
2026-05-07 11:06:14
R
W
Run
Delete
Rename
logs.zip
86.15 MB
2026-05-07 11:05:51
R
W
Run
Delete
Rename
mailbox_format.cpanel.cpanel.tar.gz
130 By
2026-05-07 12:06:14
R
W
Run
Delete
Rename
mailbox_format.cpanel.tar
2 KB
2026-05-07 12:06:14
R
W
Run
Delete
Rename
maildirsize.tar
6 KB
2026-05-07 12:06:10
R
W
Run
Delete
Rename
maildirsize.tar.gz
1.19 KB
2026-05-07 12:06:10
R
W
Run
Delete
Rename
new.tar
22.98 MB
2026-05-07 12:05:44
R
W
Run
Delete
Rename
new.tar.gz
1.37 MB
2026-05-07 12:05:45
R
W
Run
Delete
Rename
nvdata.zip
5 KB
2026-05-07 12:12:31
R
W
Run
Delete
Rename
p.php.php.tar.gz
307 By
2026-05-07 12:05:08
R
W
Run
Delete
Rename
p.php.tar
2 KB
2026-05-07 12:05:08
R
W
Run
Delete
Rename
phenx.tar
647.5 KB
2026-05-07 12:12:33
R
W
Run
Delete
Rename
phenx.tar.gz
117.8 KB
2026-05-07 12:12:33
R
W
Run
Delete
Rename
phenx.zip
590.77 KB
2026-05-07 12:12:18
R
W
Run
Delete
Rename
php-cli.tar
2 KB
2026-05-07 11:06:07
R
W
Run
Delete
Rename
php-cli.tar.gz
111 By
2026-05-07 11:06:07
R
W
Run
Delete
Rename
php-cli.zip
169 By
2026-05-07 11:05:47
R
W
Run
Delete
Rename
php.ini.swp.ini.swp.tar.gz
3.56 KB
2026-05-07 12:11:16
R
W
Run
Delete
Rename
php.ini.swp.tar
17.5 KB
2026-05-07 12:11:16
R
W
Run
Delete
Rename
php.tar
12 KB
2026-05-07 11:14:27
R
W
Run
Delete
Rename
php.tar.gz
983 By
2026-05-07 11:06:57
R
W
Run
Delete
Rename
php.zip
4.72 KB
2026-05-07 11:15:10
R
W
Run
Delete
Rename
phpoffice.tar
1.82 MB
2026-05-07 12:12:41
R
W
Run
Delete
Rename
phpoffice.tar.gz
263.76 KB
2026-05-07 12:12:41
R
W
Run
Delete
Rename
phpoffice.zip
1.62 MB
2026-05-07 12:12:38
R
W
Run
Delete
Rename
prepend.txt.tar
121.1 MB
2026-05-07 12:06:14
R
W
Run
Delete
Rename
prepend.txt.txt.tar.gz
12.71 MB
2026-05-07 12:06:21
R
W
Run
Delete
Rename
psr.zip
59.33 KB
2026-05-07 12:11:48
R
W
Run
Delete
Rename
public_ftp.zip
975.85 MB
2026-05-07 11:06:47
R
W
Run
Delete
Rename
public_html.tar
977.12 MB
2026-05-07 12:06:28
R
W
Run
Delete
Rename
public_html.tar.gz
32 KB
2026-05-07 12:06:52
R
W
Run
Delete
Rename
ralouphie.tar
8.5 KB
2026-05-07 12:12:37
R
W
Run
Delete
Rename
ralouphie.tar.gz
1.88 KB
2026-05-07 12:12:37
R
W
Run
Delete
Rename
ralouphie.zip
4.84 KB
2026-05-07 12:12:24
R
W
Run
Delete
Rename
ratchet.zip
140.66 KB
2026-05-07 12:12:21
R
W
Run
Delete
Rename
react.zip
731.88 KB
2026-05-07 12:12:22
R
W
Run
Delete
Rename
robots.txt
2.34 KB
2026-05-07 07:32:42
R
W
Run
Delete
Rename
robots.txt.tar
4 KB
2026-05-07 10:03:14
R
W
Run
Delete
Rename
robots.txt.txt.tar.gz
322 By
2026-05-07 10:03:14
R
W
Run
Delete
Rename
roundcube.tar
9.5 KB
2026-05-07 12:05:24
R
W
Run
Delete
Rename
roundcube.tar.gz
1.55 KB
2026-05-07 12:05:24
R
W
Run
Delete
Rename
saveData.php.php.tar.gz
445 By
2026-05-07 12:06:09
R
W
Run
Delete
Rename
saveData.php.tar
2.5 KB
2026-05-07 12:06:09
R
W
Run
Delete
Rename
save_admin_details.php.php.tar.gz
779 By
2026-05-07 12:06:15
R
W
Run
Delete
Rename
save_admin_details.php.tar
4 KB
2026-05-07 12:06:15
R
W
Run
Delete
Rename
scrum_toptrendingappstudio_com.php.error.log.php.error.log.tar.gz
125.37 KB
2026-05-07 12:08:05
R
W
Run
Delete
Rename
scrum_toptrendingappstudio_com.php.error.log.tar
1.9 MB
2026-05-07 12:08:04
R
W
Run
Delete
Rename
server.c302.cloudmark.com.conf.tar
2.5 KB
2026-05-07 12:13:48
R
W
Run
Delete
Rename
share.zip
183 By
2026-05-07 12:05:55
R
W
Run
Delete
Rename
ssl.zip
717.75 KB
2026-05-07 11:06:08
R
W
Run
Delete
Rename
storage.sqlite.sqlite.tar.gz
521 By
2026-05-07 12:06:07
R
W
Run
Delete
Rename
storage.sqlite.tar
17.5 KB
2026-05-07 12:06:07
R
W
Run
Delete
Rename
swiftmailer.zip
717.46 KB
2026-05-07 12:12:38
R
W
Run
Delete
Rename
symfony.zip
2.79 MB
2026-05-07 12:14:18
R
W
Run
Delete
Rename
toptrendingappst.rcube.db.1771972649.rcube.db.1771972649.tar.gz
12.34 KB
2026-05-07 12:08:05
R
W
Run
Delete
Rename
toptrendingappst.rcube.db.1771972649.tar
457.5 KB
2026-05-07 12:08:05
R
W
Run
Delete
Rename
toptrendingappst.zip
3.87 KB
2026-05-07 12:13:19
R
W
Run
Delete
Rename
userAudio_30.3gp.3gp.tar.gz
22.83 KB
2026-05-07 12:06:14
R
W
Run
Delete
Rename
userAudio_30.3gp.tar
31 KB
2026-05-07 12:06:14
R
W
Run
Delete
Rename
userAudio_99.3gp.3gp.tar.gz
612 By
2026-05-07 12:06:15
R
W
Run
Delete
Rename
userAudio_99.3gp.tar
12.5 KB
2026-05-07 12:06:15
R
W
Run
Delete
Rename
vendor.tar
2.53 MB
2026-05-07 12:12:37
R
W
Run
Delete
Rename
vendor.tar.gz
475.53 KB
2026-05-07 12:12:38
R
W
Run
Delete
Rename
vendor.zip
2.13 MB
2026-05-07 12:12:37
R
W
Run
Delete
Rename
webalizer.tar
450.43 MB
2026-05-07 12:12:19
R
W
Run
Delete
Rename
www.tar
117.38 MB
2026-05-07 11:06:08
R
W
Run
Delete
Rename
www.tar.gz
39.75 MB
2026-05-07 11:06:12
R
W
Run
Delete
Rename
www.zip
3.54 MB
2026-05-07 11:05:46
R
W
Run
Delete
Rename
error_log
up
📄
cboden.tar
Save
ratchet/.github/workflows/ci.yml 0000664 00000002024 15177100702 0012711 0 ustar 00 name: "CI" on: pull_request: push: branches: - "master" schedule: - cron: "42 3 * * *" jobs: phpunit: name: "PHPUnit" runs-on: "ubuntu-20.04" strategy: matrix: php-version: - "5.4" - "5.5" - "5.6" - "7.0" - "7.1" - "7.2" - "7.3" - "7.4" dependencies: - "highest" include: - dependencies: "lowest" php-version: "5.4" steps: - name: "Checkout" uses: "actions/checkout@v2" with: fetch-depth: 2 - name: "Install PHP" uses: "shivammathur/setup-php@v2" with: php-version: "${{ matrix.php-version }}" coverage: "none" ini-values: "zend.assertions=1" - name: "Install dependencies with Composer" uses: "ramsey/composer-install@v1" with: dependency-versions: "${{ matrix.dependencies }}" - name: "Run PHPUnit" run: "vendor/bin/phpunit" ratchet/tests/helpers/Ratchet/WebSocket/Stub/WsMessageComponentInterface.php 0000664 00000000330 15177100702 0023310 0 ustar 00 <?php namespace Ratchet\WebSocket\Stub; use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; interface WsMessageComponentInterface extends MessageComponentInterface, WsServerInterface { } ratchet/tests/helpers/Ratchet/Wamp/Stub/WsWampServerInterface.php 0000664 00000000306 15177100702 0021155 0 ustar 00 <?php namespace Ratchet\Wamp\Stub; use Ratchet\WebSocket\WsServerInterface; use Ratchet\Wamp\WampServerInterface; interface WsWampServerInterface extends WsServerInterface, WampServerInterface { } ratchet/tests/helpers/Ratchet/Mock/WampComponent.php 0000664 00000002422 15177100702 0016567 0 ustar 00 <?php namespace Ratchet\Mock; use Ratchet\Wamp\WampServerInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; class WampComponent implements WampServerInterface, WsServerInterface { public $last = array(); public $protocols = array(); public function getSubProtocols() { return $this->protocols; } public function onCall(ConnectionInterface $conn, $id, $procURI, array $params) { $this->last[__FUNCTION__] = func_get_args(); } public function onSubscribe(ConnectionInterface $conn, $topic) { $this->last[__FUNCTION__] = func_get_args(); } public function onUnSubscribe(ConnectionInterface $conn, $topic) { $this->last[__FUNCTION__] = func_get_args(); } public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) { $this->last[__FUNCTION__] = func_get_args(); } public function onOpen(ConnectionInterface $conn) { $this->last[__FUNCTION__] = func_get_args(); } public function onClose(ConnectionInterface $conn) { $this->last[__FUNCTION__] = func_get_args(); } public function onError(ConnectionInterface $conn, \Exception $e) { $this->last[__FUNCTION__] = func_get_args(); } } ratchet/tests/helpers/Ratchet/Mock/Connection.php 0000664 00000000621 15177100702 0016076 0 ustar 00 <?php namespace Ratchet\Mock; use Ratchet\ConnectionInterface; class Connection implements ConnectionInterface { public $last = array( 'send' => '' , 'close' => false ); public $remoteAddress = '127.0.0.1'; public function send($data) { $this->last[__FUNCTION__] = $data; } public function close() { $this->last[__FUNCTION__] = true; } } ratchet/tests/helpers/Ratchet/Mock/Component.php 0000664 00000001722 15177100702 0015744 0 ustar 00 <?php namespace Ratchet\Mock; use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; class Component implements MessageComponentInterface, WsServerInterface { public $last = array(); public $protocols = array(); public function __construct(ComponentInterface $app = null) { $this->last[__FUNCTION__] = func_get_args(); } public function onOpen(ConnectionInterface $conn) { $this->last[__FUNCTION__] = func_get_args(); } public function onMessage(ConnectionInterface $from, $msg) { $this->last[__FUNCTION__] = func_get_args(); } public function onClose(ConnectionInterface $conn) { $this->last[__FUNCTION__] = func_get_args(); } public function onError(ConnectionInterface $conn, \Exception $e) { $this->last[__FUNCTION__] = func_get_args(); } public function getSubProtocols() { return $this->protocols; } } ratchet/tests/helpers/Ratchet/Mock/ConnectionDecorator.php 0000664 00000000725 15177100702 0017746 0 ustar 00 <?php namespace Ratchet\Mock; use Ratchet\AbstractConnectionDecorator; class ConnectionDecorator extends AbstractConnectionDecorator { public $last = array( 'write' => '' , 'end' => false ); public function send($data) { $this->last[__FUNCTION__] = $data; $this->getConnection()->send($data); } public function close() { $this->last[__FUNCTION__] = true; $this->getConnection()->close(); } } ratchet/tests/helpers/Ratchet/AbstractMessageComponentTestCase.php 0000664 00000003355 15177100702 0021504 0 ustar 00 <?php namespace Ratchet; abstract class AbstractMessageComponentTestCase extends \PHPUnit_Framework_TestCase { protected $_app; protected $_serv; protected $_conn; abstract public function getConnectionClassString(); abstract public function getDecoratorClassString(); abstract public function getComponentClassString(); public function setUp() { $this->_app = $this->getMock($this->getComponentClassString()); $decorator = $this->getDecoratorClassString(); $this->_serv = new $decorator($this->_app); $this->_conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->doOpen($this->_conn); } protected function doOpen($conn) { $this->_serv->onOpen($conn); } public function isExpectedConnection() { return new \PHPUnit_Framework_Constraint_IsInstanceOf($this->getConnectionClassString()); } public function testOpen() { $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection()); $this->doOpen($this->getMock('\Ratchet\ConnectionInterface')); } public function testOnClose() { $this->_app->expects($this->once())->method('onClose')->with($this->isExpectedConnection()); $this->_serv->onClose($this->_conn); } public function testOnError() { $e = new \Exception('Whoops!'); $this->_app->expects($this->once())->method('onError')->with($this->isExpectedConnection(), $e); $this->_serv->onError($this->_conn, $e); } public function passthroughMessageTest($value) { $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $value); $this->_serv->onMessage($this->_conn, $value); } } ratchet/tests/helpers/Ratchet/NullComponent.php 0000664 00000001706 15177100702 0015710 0 ustar 00 <?php namespace Ratchet; use Ratchet\ConnectionInterface; use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\Wamp\WampServerInterface; class NullComponent implements MessageComponentInterface, WsServerInterface, WampServerInterface { public function onOpen(ConnectionInterface $conn) {} public function onMessage(ConnectionInterface $conn, $msg) {} public function onClose(ConnectionInterface $conn) {} public function onError(ConnectionInterface $conn, \Exception $e) {} public function onCall(ConnectionInterface $conn, $id, $topic, array $params) {} public function onSubscribe(ConnectionInterface $conn, $topic) {} public function onUnSubscribe(ConnectionInterface $conn, $topic) {} public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude = array(), array $eligible = array()) {} public function getSubProtocols() { return array(); } } ratchet/tests/autobahn/bin/fuzzingserver.php 0000664 00000002310 15177100702 0015343 0 ustar 00 <?php use Ratchet\ConnectionInterface; require dirname(dirname(dirname(__DIR__))) . '/vendor/autoload.php'; class BinaryEcho implements \Ratchet\WebSocket\MessageComponentInterface { public function onMessage(ConnectionInterface $from, \Ratchet\RFC6455\Messaging\MessageInterface $msg) { $from->send($msg); } public function onOpen(ConnectionInterface $conn) { } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { } } $port = $argc > 1 ? $argv[1] : 8000; $impl = sprintf('React\EventLoop\%sLoop', $argc > 2 ? $argv[2] : 'StreamSelect'); $loop = new $impl; $sock = new React\Socket\Server('0.0.0.0:' . $port, $loop); $wsServer = new Ratchet\WebSocket\WsServer(new BinaryEcho); // This is enabled to test https://github.com/ratchetphp/Ratchet/issues/430 // The time is left at 10 minutes so that it will not try to every ping anything // This causes the Ratchet server to crash on test 2.7 $wsServer->enableKeepAlive($loop, 600); $app = new Ratchet\Http\HttpServer($wsServer); $server = new Ratchet\Server\IoServer($app, $sock, $loop); $server->run(); ratchet/tests/autobahn/fuzzingclient-quick.json 0000664 00000000375 15177100702 0016050 0 ustar 00 { "options": {"failByDrop": false} , "outdir": "reports/rfc" , "servers": [ {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}} ] , "cases": ["*"] , "exclude-cases": [] , "exclude-agent-cases": {} } ratchet/tests/autobahn/fuzzingclient-profile.json 0000664 00000000506 15177100702 0016370 0 ustar 00 { "options": {"failByDrop": false} , "outdir": "reports/profile" , "servers": [ {"agent": "Ratchet", "url": "ws://localhost:8000", "options": {"version": 18}} ] , "cases": ["9.7.4"] , "exclude-cases": ["1.2.*", "2.3", "2.4", "2.6", "9.2.*", "9.4.*", "9.6.*", "9.8.*"] , "exclude-agent-cases": {} } ratchet/tests/autobahn/fuzzingclient-all.json 0000664 00000001065 15177100702 0015501 0 ustar 00 { "options": {"failByDrop": false} , "outdir": "reports/ab" , "servers": [ {"agent": "Ratchet/0.4 libevent", "url": "ws://localhost:8001", "options": {"version": 18}} , {"agent": "Ratchet/0.4 libev", "url": "ws://localhost:8004", "options": {"version": 18}} , {"agent": "Ratchet/0.4 streams", "url": "ws://localhost:8002", "options": {"version": 18}} , {"agent": "AutobahnTestSuite/0.5.9", "url": "ws://localhost:8000", "options": {"version": 18}} ] , "cases": ["*"] , "exclude-cases": [] , "exclude-agent-cases": {} } ratchet/tests/unit/Http/HttpServerTest.php 0000664 00000004122 15177100702 0014716 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\AbstractMessageComponentTestCase; /** * @covers Ratchet\Http\HttpServer */ class HttpServerTest extends AbstractMessageComponentTestCase { public function setUp() { parent::setUp(); $this->_conn->httpHeadersReceived = true; } public function getConnectionClassString() { return '\Ratchet\ConnectionInterface'; } public function getDecoratorClassString() { return '\Ratchet\Http\HttpServer'; } public function getComponentClassString() { return '\Ratchet\Http\HttpServerInterface'; } public function testOpen() { $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"; $this->_conn->httpHeadersReceived = false; $this->_app->expects($this->once())->method('onOpen')->with($this->isExpectedConnection()); $this->_serv->onMessage($this->_conn, $headers); } public function testOnMessageAfterHeaders() { $headers = "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"; $this->_conn->httpHeadersReceived = false; $this->_serv->onMessage($this->_conn, $headers); $message = "Hello World!"; $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message); $this->_serv->onMessage($this->_conn, $message); } public function testBufferOverflow() { $this->_conn->expects($this->once())->method('close'); $this->_conn->httpHeadersReceived = false; $this->_serv->onMessage($this->_conn, str_repeat('a', 5000)); } public function testCloseIfNotEstablished() { $this->_conn->httpHeadersReceived = false; $this->_conn->expects($this->once())->method('close'); $this->_serv->onError($this->_conn, new \Exception('Whoops!')); } public function testBufferHeaders() { $this->_conn->httpHeadersReceived = false; $this->_app->expects($this->never())->method('onOpen'); $this->_app->expects($this->never())->method('onMessage'); $this->_serv->onMessage($this->_conn, "GET / HTTP/1.1"); } } ratchet/tests/unit/Http/OriginCheckTest.php 0000664 00000002365 15177100702 0015004 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\AbstractMessageComponentTestCase; /** * @covers Ratchet\Http\OriginCheck */ class OriginCheckTest extends AbstractMessageComponentTestCase { protected $_reqStub; public function setUp() { $this->_reqStub = $this->getMock('Psr\Http\Message\RequestInterface'); $this->_reqStub->expects($this->any())->method('getHeader')->will($this->returnValue(['localhost'])); parent::setUp(); $this->_serv->allowedOrigins[] = 'localhost'; } protected function doOpen($conn) { $this->_serv->onOpen($conn, $this->_reqStub); } public function getConnectionClassString() { return '\Ratchet\ConnectionInterface'; } public function getDecoratorClassString() { return '\Ratchet\Http\OriginCheck'; } public function getComponentClassString() { return '\Ratchet\Http\HttpServerInterface'; } public function testCloseOnNonMatchingOrigin() { $this->_serv->allowedOrigins = ['socketo.me']; $this->_conn->expects($this->once())->method('close'); $this->_serv->onOpen($this->_conn, $this->_reqStub); } public function testOnMessage() { $this->passthroughMessageTest('Hello World!'); } } ratchet/tests/unit/Http/HttpRequestParserTest.php 0000664 00000003145 15177100702 0016261 0 ustar 00 <?php namespace Ratchet\Http; /** * @covers Ratchet\Http\HttpRequestParser */ class HttpRequestParserTest extends \PHPUnit_Framework_TestCase { protected $parser; public function setUp() { $this->parser = new HttpRequestParser; } public function headersProvider() { return array( array(false, "GET / HTTP/1.1\r\nHost: socketo.me\r\n") , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n") , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n1") , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖") , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie✖\r\n\r\n") , array(true, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\nHixie\r\n") ); } /** * @dataProvider headersProvider */ public function testIsEom($expected, $message) { $this->assertEquals($expected, $this->parser->isEom($message)); } public function testBufferOverflowResponse() { $conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->parser->maxSize = 20; $this->assertNull($this->parser->onMessage($conn, "GET / HTTP/1.1\r\n")); $this->setExpectedException('OverflowException'); $this->parser->onMessage($conn, "Header-Is: Too Big"); } public function testReturnTypeIsRequest() { $conn = $this->getMock('\Ratchet\ConnectionInterface'); $return = $this->parser->onMessage($conn, "GET / HTTP/1.1\r\nHost: socketo.me\r\n\r\n"); $this->assertInstanceOf('\Psr\Http\Message\RequestInterface', $return); } } ratchet/tests/unit/Http/RouterTest.php 0000664 00000016120 15177100702 0014071 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\WebSocket\WsServerInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Matcher\UrlMatcher; /** * @covers Ratchet\Http\Router */ class RouterTest extends \PHPUnit_Framework_TestCase { protected $_router; protected $_matcher; protected $_conn; protected $_uri; protected $_req; public function setUp() { $this->_conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->_uri = $this->getMock('Psr\Http\Message\UriInterface'); $this->_req = $this->getMock('\Psr\Http\Message\RequestInterface'); $this->_req ->expects($this->any()) ->method('getUri') ->will($this->returnValue($this->_uri)); $this->_matcher = $this->getMock('Symfony\Component\Routing\Matcher\UrlMatcherInterface'); $this->_matcher ->expects($this->any()) ->method('getContext') ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext'))); $this->_router = new Router($this->_matcher); $this->_uri->expects($this->any())->method('getPath')->will($this->returnValue('ws://doesnt.matter/')); $this->_uri->expects($this->any())->method('withQuery')->with($this->callback(function($val) { $this->setResult($val); return true; }))->will($this->returnSelf()); $this->_uri->expects($this->any())->method('getQuery')->will($this->returnCallback([$this, 'getResult'])); $this->_req->expects($this->any())->method('withUri')->will($this->returnSelf()); } public function testFourOhFour() { $this->_conn->expects($this->once())->method('close'); $nope = new ResourceNotFoundException; $this->_matcher->expects($this->any())->method('match')->will($this->throwException($nope)); $this->_router->onOpen($this->_conn, $this->_req); } public function testNullRequest() { $this->setExpectedException('\UnexpectedValueException'); $this->_router->onOpen($this->_conn); } public function testControllerIsMessageComponentInterface() { $this->setExpectedException('\UnexpectedValueException'); $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => new \StdClass))); $this->_router->onOpen($this->_conn, $this->_req); } public function testControllerOnOpen() { $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller))); $this->_router->onOpen($this->_conn, $this->_req); $expectedConn = new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\ConnectionInterface'); $controller->expects($this->once())->method('onOpen')->with($expectedConn, $this->_req); $this->_matcher->expects($this->any())->method('match')->will($this->returnValue(array('_controller' => $controller))); $this->_router->onOpen($this->_conn, $this->_req); } public function testControllerOnMessageBubbles() { $message = "The greatest trick the Devil ever pulled was convincing the world he didn't exist"; $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); $controller->expects($this->once())->method('onMessage')->with($this->_conn, $message); $this->_conn->controller = $controller; $this->_router->onMessage($this->_conn, $message); } public function testControllerOnCloseBubbles() { $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); $controller->expects($this->once())->method('onClose')->with($this->_conn); $this->_conn->controller = $controller; $this->_router->onClose($this->_conn); } public function testControllerOnErrorBubbles() { $e= new \Exception('One cannot be betrayed if one has no exceptions'); $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); $controller->expects($this->once())->method('onError')->with($this->_conn, $e); $this->_conn->controller = $controller; $this->_router->onError($this->_conn, $e); } public function testRouterGeneratesRouteParameters() { /** @var $controller WsServerInterface */ $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); /** @var $matcher UrlMatcherInterface */ $this->_matcher->expects($this->any())->method('match')->will( $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux']) ); $conn = $this->getMock('Ratchet\Mock\Connection'); $router = new Router($this->_matcher); $router->onOpen($conn, $this->_req); $this->assertEquals('foo=bar&baz=qux', $this->_req->getUri()->getQuery()); } public function testQueryParams() { $controller = $this->getMockBuilder('\Ratchet\WebSocket\WsServer')->disableOriginalConstructor()->getMock(); $this->_matcher->expects($this->any())->method('match')->will( $this->returnValue(['_controller' => $controller, 'foo' => 'bar', 'baz' => 'qux']) ); $conn = $this->getMock('Ratchet\Mock\Connection'); $request = $this->getMock('Psr\Http\Message\RequestInterface'); $uri = new \GuzzleHttp\Psr7\Uri('ws://doesnt.matter/endpoint?hello=world&foo=nope'); $request->expects($this->any())->method('getUri')->will($this->returnCallback(function() use (&$uri) { return $uri; })); $request->expects($this->any())->method('withUri')->with($this->callback(function($url) use (&$uri) { $uri = $url; return true; }))->will($this->returnSelf()); $router = new Router($this->_matcher); $router->onOpen($conn, $request); $this->assertEquals('foo=nope&baz=qux&hello=world', $request->getUri()->getQuery()); $this->assertEquals('ws', $request->getUri()->getScheme()); $this->assertEquals('doesnt.matter', $request->getUri()->getHost()); } public function testImpatientClientOverflow() { $this->_conn->expects($this->once())->method('close'); $header = "GET /nope HTTP/1.1 Upgrade: websocket Connection: upgrade Host: localhost Origin: http://localhost Sec-WebSocket-Version: 13\r\n\r\n"; $app = new HttpServer(new Router(new UrlMatcher(new RouteCollection, new RequestContext))); $app->onOpen($this->_conn); $app->onMessage($this->_conn, $header); $app->onMessage($this->_conn, 'Silly body'); } } ratchet/tests/unit/Wamp/WampConnectionTest.php 0000664 00000004406 15177100702 0015526 0 ustar 00 <?php namespace Ratchet\Wamp; /** * @covers Ratchet\Wamp\WampConnection */ class WampConnectionTest extends \PHPUnit_Framework_TestCase { protected $conn; protected $mock; public function setUp() { $this->mock = $this->getMock('\\Ratchet\\ConnectionInterface'); $this->conn = new WampConnection($this->mock); } public function testCallResult() { $callId = uniqid(); $data = array('hello' => 'world', 'herp' => 'derp'); $this->mock->expects($this->once())->method('send')->with(json_encode(array(3, $callId, $data))); $this->conn->callResult($callId, $data); } public function testCallError() { $callId = uniqid(); $uri = 'http://example.com/end/point'; $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, ''))); $this->conn->callError($callId, $uri); } public function testCallErrorWithTopic() { $callId = uniqid(); $uri = 'http://example.com/end/point'; $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, ''))); $this->conn->callError($callId, new Topic($uri)); } public function testDetailedCallError() { $callId = uniqid(); $uri = 'http://example.com/end/point'; $desc = 'beep boop beep'; $detail = 'Error: Too much awesome'; $this->mock->expects($this->once())->method('send')->with(json_encode(array(4, $callId, $uri, $desc, $detail))); $this->conn->callError($callId, $uri, $desc, $detail); } public function testPrefix() { $shortOut = 'outgoing'; $longOut = 'http://example.com/outgoing'; $this->mock->expects($this->once())->method('send')->with(json_encode(array(1, $shortOut, $longOut))); $this->conn->prefix($shortOut, $longOut); } public function testGetUriWhenNoCurieGiven() { $uri = 'http://example.com/noshort'; $this->assertEquals($uri, $this->conn->getUri($uri)); } public function testClose() { $mock = $this->getMock('\\Ratchet\\ConnectionInterface'); $conn = new WampConnection($mock); $mock->expects($this->once())->method('close'); $conn->close(); } } ratchet/tests/unit/Wamp/TopicTest.php 0000664 00000011773 15177100702 0013665 0 ustar 00 <?php namespace Ratchet\Wamp; /** * @covers Ratchet\Wamp\Topic */ class TopicTest extends \PHPUnit_Framework_TestCase { public function testGetId() { $id = uniqid(); $topic = new Topic($id); $this->assertEquals($id, $topic->getId()); } public function testAddAndCount() { $topic = new Topic('merp'); $topic->add($this->newConn()); $topic->add($this->newConn()); $topic->add($this->newConn()); $this->assertEquals(3, count($topic)); } public function testRemove() { $topic = new Topic('boop'); $tracked = $this->newConn(); $topic->add($this->newConn()); $topic->add($tracked); $topic->add($this->newConn()); $topic->remove($tracked); $this->assertEquals(2, count($topic)); } public function testBroadcast() { $msg = 'Hello World!'; $name = 'Batman'; $protocol = json_encode(array(8, $name, $msg)); $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $first->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $second->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $topic = new Topic($name); $topic->add($first); $topic->add($second); $topic->broadcast($msg); } public function testBroadcastWithExclude() { $msg = 'Hello odd numbers'; $name = 'Excluding'; $protocol = json_encode(array(8, $name, $msg)); $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $first->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $second->expects($this->never())->method('send'); $third->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $topic = new Topic($name); $topic->add($first); $topic->add($second); $topic->add($third); $topic->broadcast($msg, array($second->WAMP->sessionId)); } public function testBroadcastWithEligible() { $msg = 'Hello white list'; $name = 'Eligible'; $protocol = json_encode(array(8, $name, $msg)); $first = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $second = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $third = $this->getMock('Ratchet\\Wamp\\WampConnection', array('send'), array($this->getMock('\\Ratchet\\ConnectionInterface'))); $first->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $second->expects($this->never())->method('send'); $third->expects($this->once()) ->method('send') ->with($this->equalTo($protocol)); $topic = new Topic($name); $topic->add($first); $topic->add($second); $topic->add($third); $topic->broadcast($msg, array(), array($first->WAMP->sessionId, $third->WAMP->sessionId)); } public function testIterator() { $first = $this->newConn(); $second = $this->newConn(); $third = $this->newConn(); $topic = new Topic('Joker'); $topic->add($first)->add($second)->add($third); $check = array($first, $second, $third); foreach ($topic as $mock) { $this->assertNotSame(false, array_search($mock, $check)); } } public function testToString() { $name = 'Bane'; $topic = new Topic($name); $this->assertEquals($name, (string)$topic); } public function testDoesHave() { $conn = $this->newConn(); $topic = new Topic('Two Face'); $topic->add($conn); $this->assertTrue($topic->has($conn)); } public function testDoesNotHave() { $conn = $this->newConn(); $topic = new Topic('Alfred'); $this->assertFalse($topic->has($conn)); } public function testDoesNotHaveAfterRemove() { $conn = $this->newConn(); $topic = new Topic('Ras'); $topic->add($conn)->remove($conn); $this->assertFalse($topic->has($conn)); } protected function newConn() { return new WampConnection($this->getMock('\\Ratchet\\ConnectionInterface')); } } ratchet/tests/unit/Wamp/WampServerTest.php 0000664 00000003027 15177100702 0014673 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\AbstractMessageComponentTestCase; /** * @covers Ratchet\Wamp\WampServer */ class WampServerTest extends AbstractMessageComponentTestCase { public function getConnectionClassString() { return '\Ratchet\Wamp\WampConnection'; } public function getDecoratorClassString() { return 'Ratchet\Wamp\WampServer'; } public function getComponentClassString() { return '\Ratchet\Wamp\WampServerInterface'; } public function testOnMessageToEvent() { $published = 'Client published this message'; $this->_app->expects($this->once())->method('onPublish')->with( $this->isExpectedConnection() , new \PHPUnit_Framework_Constraint_IsInstanceOf('\Ratchet\Wamp\Topic') , $published , array() , array() ); $this->_serv->onMessage($this->_conn, json_encode(array(7, 'topic', $published))); } public function testGetSubProtocols() { // todo: could expand on this $this->assertInternalType('array', $this->_serv->getSubProtocols()); } public function testConnectionClosesOnInvalidJson() { $this->_conn->expects($this->once())->method('close'); $this->_serv->onMessage($this->_conn, 'invalid json'); } public function testConnectionClosesOnProtocolError() { $this->_conn->expects($this->once())->method('close'); $this->_serv->onMessage($this->_conn, json_encode(array('valid' => 'json', 'invalid' => 'protocol'))); } } ratchet/tests/unit/Wamp/TopicManagerTest.php 0000664 00000016134 15177100702 0015154 0 ustar 00 <?php namespace Ratchet\Wamp; /** * @covers Ratchet\Wamp\TopicManager */ class TopicManagerTest extends \PHPUnit_Framework_TestCase { private $mock; /** * @var \Ratchet\Wamp\TopicManager */ private $mngr; /** * @var \Ratchet\ConnectionInterface */ private $conn; public function setUp() { $this->conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->mock = $this->getMock('\Ratchet\Wamp\WampServerInterface'); $this->mngr = new TopicManager($this->mock); $this->conn->WAMP = new \StdClass; $this->mngr->onOpen($this->conn); } public function testGetTopicReturnsTopicObject() { $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array('The Topic')); $this->assertInstanceOf('Ratchet\Wamp\Topic', $topic); } public function testGetTopicCreatesTopicWithSameName() { $name = 'The Topic'; $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array($name)); $this->assertEquals($name, $topic->getId()); } public function testGetTopicReturnsSameObject() { $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array('No copy')); $again = $method->invokeArgs($this->mngr, array('No copy')); $this->assertSame($topic, $again); } public function testOnOpen() { $this->mock->expects($this->once())->method('onOpen'); $this->mngr->onOpen($this->conn); } public function testOnCall() { $id = uniqid(); $this->mock->expects($this->once())->method('onCall')->with( $this->conn , $id , $this->isInstanceOf('Ratchet\Wamp\Topic') , array() ); $this->mngr->onCall($this->conn, $id, 'new topic', array()); } public function testOnSubscribeCreatesTopicObject() { $this->mock->expects($this->once())->method('onSubscribe')->with( $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic') ); $this->mngr->onSubscribe($this->conn, 'new topic'); } public function testTopicIsInConnectionOnSubscribe() { $name = 'New Topic'; $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array($name)); $this->mngr->onSubscribe($this->conn, $name); $this->assertTrue($this->conn->WAMP->subscriptions->contains($topic)); } public function testDoubleSubscriptionFiresOnce() { $this->mock->expects($this->exactly(1))->method('onSubscribe'); $this->mngr->onSubscribe($this->conn, 'same topic'); $this->mngr->onSubscribe($this->conn, 'same topic'); } public function testUnsubscribeEvent() { $name = 'in and out'; $this->mock->expects($this->once())->method('onUnsubscribe')->with( $this->conn, $this->isInstanceOf('Ratchet\Wamp\Topic') ); $this->mngr->onSubscribe($this->conn, $name); $this->mngr->onUnsubscribe($this->conn, $name); } public function testUnsubscribeFiresOnce() { $name = 'getting sleepy'; $this->mock->expects($this->exactly(1))->method('onUnsubscribe'); $this->mngr->onSubscribe($this->conn, $name); $this->mngr->onUnsubscribe($this->conn, $name); $this->mngr->onUnsubscribe($this->conn, $name); } public function testUnsubscribeRemovesTopicFromConnection() { $name = 'Bye Bye Topic'; $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array($name)); $this->mngr->onSubscribe($this->conn, $name); $this->mngr->onUnsubscribe($this->conn, $name); $this->assertFalse($this->conn->WAMP->subscriptions->contains($topic)); } public function testOnPublishBubbles() { $msg = 'Cover all the code!'; $this->mock->expects($this->once())->method('onPublish')->with( $this->conn , $this->isInstanceOf('Ratchet\Wamp\Topic') , $msg , $this->isType('array') , $this->isType('array') ); $this->mngr->onPublish($this->conn, 'topic coverage', $msg, array(), array()); } public function testOnCloseBubbles() { $this->mock->expects($this->once())->method('onClose')->with($this->conn); $this->mngr->onClose($this->conn); } protected function topicProvider($name) { $class = new \ReflectionClass('Ratchet\Wamp\TopicManager'); $method = $class->getMethod('getTopic'); $method->setAccessible(true); $attribute = $class->getProperty('topicLookup'); $attribute->setAccessible(true); $topic = $method->invokeArgs($this->mngr, array($name)); return array($topic, $attribute); } public function testConnIsRemovedFromTopicOnClose() { $name = 'State Testing'; list($topic, $attribute) = $this->topicProvider($name); $this->assertCount(1, $attribute->getValue($this->mngr)); $this->mngr->onSubscribe($this->conn, $name); $this->mngr->onClose($this->conn); $this->assertFalse($topic->has($this->conn)); } public static function topicConnExpectationProvider() { return [ [ 'onClose', 0] , ['onUnsubscribe', 0] ]; } /** * @dataProvider topicConnExpectationProvider */ public function testTopicRetentionFromLeavingConnections($methodCall, $expectation) { $topicName = 'checkTopic'; list($topic, $attribute) = $this->topicProvider($topicName); $this->mngr->onSubscribe($this->conn, $topicName); call_user_func_array(array($this->mngr, $methodCall), array($this->conn, $topicName)); $this->assertCount($expectation, $attribute->getValue($this->mngr)); } public function testOnErrorBubbles() { $e = new \Exception('All work and no play makes Chris a dull boy'); $this->mock->expects($this->once())->method('onError')->with($this->conn, $e); $this->mngr->onError($this->conn, $e); } public function testGetSubProtocolsReturnsArray() { $this->assertInternalType('array', $this->mngr->getSubProtocols()); } public function testGetSubProtocolsBubbles() { $subs = array('hello', 'world'); $app = $this->getMock('Ratchet\Wamp\Stub\WsWampServerInterface'); $app->expects($this->once())->method('getSubProtocols')->will($this->returnValue($subs)); $mngr = new TopicManager($app); $this->assertEquals($subs, $mngr->getSubProtocols()); } } ratchet/tests/unit/Wamp/ServerProtocolTest.php 0000664 00000021251 15177100702 0015567 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\Mock\Connection; use Ratchet\Mock\WampComponent as TestComponent; /** * @covers \Ratchet\Wamp\ServerProtocol * @covers \Ratchet\Wamp\WampServerInterface * @covers \Ratchet\Wamp\WampConnection */ class ServerProtocolTest extends \PHPUnit_Framework_TestCase { protected $_comp; protected $_app; public function setUp() { $this->_app = new TestComponent; $this->_comp = new ServerProtocol($this->_app); } protected function newConn() { return new Connection; } public function invalidMessageProvider() { return [ [0] , [3] , [4] , [8] , [9] ]; } /** * @dataProvider invalidMessageProvider */ public function testInvalidMessages($type) { $this->setExpectedException('\Ratchet\Wamp\Exception'); $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode([$type])); } public function testWelcomeMessage() { $conn = $this->newConn(); $this->_comp->onOpen($conn); $message = $conn->last['send']; $json = json_decode($message); $this->assertEquals(4, count($json)); $this->assertEquals(0, $json[0]); $this->assertTrue(is_string($json[1])); $this->assertEquals(1, $json[2]); } public function testSubscribe() { $uri = 'http://example.com'; $clientMessage = array(5, $uri); $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode($clientMessage)); $this->assertEquals($uri, $this->_app->last['onSubscribe'][1]); } public function testUnSubscribe() { $uri = 'http://example.com/endpoint'; $clientMessage = array(6, $uri); $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode($clientMessage)); $this->assertEquals($uri, $this->_app->last['onUnSubscribe'][1]); } public function callProvider() { return [ [2, 'a', 'b'] , [2, ['a', 'b']] , [1, 'one'] , [3, 'one', 'two', 'three'] , [3, ['un', 'deux', 'trois']] , [2, 'hi', ['hello', 'world']] , [2, ['hello', 'world'], 'hi'] , [2, ['hello' => 'world', 'herp' => 'derp']] ]; } /** * @dataProvider callProvider */ public function testCall() { $args = func_get_args(); $paramNum = array_shift($args); $uri = 'http://example.com/endpoint/' . rand(1, 100); $id = uniqid('', false); $clientMessage = array_merge(array(2, $id, $uri), $args); $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode($clientMessage)); $this->assertEquals($id, $this->_app->last['onCall'][1]); $this->assertEquals($uri, $this->_app->last['onCall'][2]); $this->assertEquals($paramNum, count($this->_app->last['onCall'][3])); } public function testPublish() { $conn = $this->newConn(); $topic = 'pubsubhubbub'; $event = 'Here I am, publishing data'; $clientMessage = array(7, $topic, $event); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode($clientMessage)); $this->assertEquals($topic, $this->_app->last['onPublish'][1]); $this->assertEquals($event, $this->_app->last['onPublish'][2]); $this->assertEquals(array(), $this->_app->last['onPublish'][3]); $this->assertEquals(array(), $this->_app->last['onPublish'][4]); } public function testPublishAndExcludeMe() { $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', true))); $this->assertEquals($conn->WAMP->sessionId, $this->_app->last['onPublish'][3][0]); } public function testPublishAndEligible() { $conn = $this->newConn(); $buddy = uniqid('', false); $friend = uniqid('', false); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode(array(7, 'topic', 'event', false, array($buddy, $friend)))); $this->assertEquals(array(), $this->_app->last['onPublish'][3]); $this->assertEquals(2, count($this->_app->last['onPublish'][4])); } public function eventProvider() { return array( array('http://example.com', array('one', 'two')) , array('curie', array(array('hello' => 'world', 'herp' => 'derp'))) ); } /** * @dataProvider eventProvider */ public function testEvent($topic, $payload) { $conn = new WampConnection($this->newConn()); $conn->event($topic, $payload); $eventString = $conn->last['send']; $this->assertSame(array(8, $topic, $payload), json_decode($eventString, true)); } public function testOnClosePropagation() { $conn = new Connection; $this->_comp->onOpen($conn); $this->_comp->onClose($conn); $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection'); $method = $class->getMethod('getConnection'); $method->setAccessible(true); $check = $method->invokeArgs($this->_app->last['onClose'][0], array()); $this->assertSame($conn, $check); } public function testOnErrorPropagation() { $conn = new Connection; $e = new \Exception('Nope'); $this->_comp->onOpen($conn); $this->_comp->onError($conn, $e); $class = new \ReflectionClass('\\Ratchet\\Wamp\\WampConnection'); $method = $class->getMethod('getConnection'); $method->setAccessible(true); $check = $method->invokeArgs($this->_app->last['onError'][0], array()); $this->assertSame($conn, $check); $this->assertSame($e, $this->_app->last['onError'][1]); } public function testPrefix() { $conn = new WampConnection($this->newConn()); $this->_comp->onOpen($conn); $prefix = 'incoming'; $fullURI = "http://example.com/$prefix"; $method = 'call'; $this->_comp->onMessage($conn, json_encode(array(1, $prefix, $fullURI))); $this->assertEquals($fullURI, $conn->WAMP->prefixes[$prefix]); $this->assertEquals("$fullURI#$method", $conn->getUri("$prefix:$method")); } public function testMessageMustBeJson() { $this->setExpectedException('\\Ratchet\\Wamp\\JsonException'); $conn = new Connection; $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, 'Hello World!'); } public function testGetSubProtocolsReturnsArray() { $this->assertTrue(is_array($this->_comp->getSubProtocols())); } public function testGetSubProtocolsGetFromApp() { $this->_app->protocols = array('hello', 'world'); $this->assertGreaterThanOrEqual(3, count($this->_comp->getSubProtocols())); } public function testWampOnMessageApp() { $app = $this->getMock('\\Ratchet\\Wamp\\WampServerInterface'); $wamp = new ServerProtocol($app); $this->assertContains('wamp', $wamp->getSubProtocols()); } public function badFormatProvider() { return array( array(json_encode(true)) , array('{"valid":"json", "invalid": "message"}') , array('{"0": "fail", "hello": "world"}') ); } /** * @dataProvider badFormatProvider */ public function testValidJsonButInvalidProtocol($message) { $this->setExpectedException('\Ratchet\Wamp\Exception'); $conn = $this->newConn(); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, $message); } public function testBadClientInputFromNonStringTopic() { $this->setExpectedException('\Ratchet\Wamp\Exception'); $conn = new WampConnection($this->newConn()); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode([5, ['hells', 'nope']])); } public function testBadPrefixWithNonStringTopic() { $this->setExpectedException('\Ratchet\Wamp\Exception'); $conn = new WampConnection($this->newConn()); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode([1, ['hells', 'nope'], ['bad', 'input']])); } public function testBadPublishWithNonStringTopic() { $this->setExpectedException('\Ratchet\Wamp\Exception'); $conn = new WampConnection($this->newConn()); $this->_comp->onOpen($conn); $this->_comp->onMessage($conn, json_encode([7, ['bad', 'input'], 'Hider'])); } } ratchet/tests/unit/Session/Serialize/PhpHandlerTest.php 0000664 00000002225 15177100702 0017272 0 ustar 00 <?php namespace Ratchet\Session\Serialize; use Ratchet\Session\Serialize\PhpHandler; /** * @covers Ratchet\Session\Serialize\PhpHandler */ class PhpHandlerTest extends \PHPUnit_Framework_TestCase { protected $_handler; public function setUp() { $this->_handler = new PhpHandler; } public function serializedProvider() { return array( array( '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}' , array( '_sf2_attributes' => array( 'hello' => 'world' , 'last' => 1332872102 ) , '_sf2_flashes' => array() ) ) ); } /** * @dataProvider serializedProvider */ public function testUnserialize($in, $expected) { $this->assertEquals($expected, $this->_handler->unserialize($in)); } /** * @dataProvider serializedProvider */ public function testSerialize($serialized, $original) { $this->assertEquals($serialized, $this->_handler->serialize($original)); } } ratchet/tests/unit/Session/Storage/VirtualSessionStoragePDOTest.php 0000664 00000003347 15177100702 0021612 0 ustar 00 <?php namespace Ratchet\Session\Storage; use Ratchet\Session\Serialize\PhpHandler; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; class VirtualSessionStoragePDOTest extends \PHPUnit_Framework_TestCase { /** * @var VirtualSessionStorage */ protected $_virtualSessionStorage; protected $_pathToDB; public function setUp() { if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { return $this->markTestSkipped('Session test requires PDO and pdo_sqlite'); } $schema = <<<SQL CREATE TABLE `sessions` ( `sess_id` VARBINARY(128) NOT NULL PRIMARY KEY, `sess_data` BLOB NOT NULL, `sess_time` INTEGER UNSIGNED NOT NULL, `sess_lifetime` MEDIUMINT NOT NULL ); SQL; $this->_pathToDB = tempnam(sys_get_temp_dir(), 'SQ3');; $dsn = 'sqlite:' . $this->_pathToDB; $pdo = new \PDO($dsn); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $pdo->exec($schema); $pdo = null; $sessionHandler = new PdoSessionHandler($dsn); $serializer = new PhpHandler(); $this->_virtualSessionStorage = new VirtualSessionStorage($sessionHandler, 'foobar', $serializer); $this->_virtualSessionStorage->registerBag(new FlashBag()); $this->_virtualSessionStorage->registerBag(new AttributeBag()); } public function tearDown() { unlink($this->_pathToDB); } public function testStartWithDSN() { $this->_virtualSessionStorage->start(); $this->assertTrue($this->_virtualSessionStorage->isStarted()); } } ratchet/tests/unit/Session/SessionComponentTest.php 0000664 00000011465 15177100702 0016632 0 ustar 00 <?php namespace Ratchet\Session; use Ratchet\AbstractMessageComponentTestCase; use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; /** * @covers Ratchet\Session\SessionProvider * @covers Ratchet\Session\Storage\VirtualSessionStorage * @covers Ratchet\Session\Storage\Proxy\VirtualProxy */ class SessionProviderTest extends AbstractMessageComponentTestCase { public function setUp() { return $this->markTestIncomplete('Test needs to be updated for ini_set issue in PHP 7.2'); if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) { return $this->markTestSkipped('Dependency of Symfony HttpFoundation failed'); } parent::setUp(); $this->_serv = new SessionProvider($this->_app, new NullSessionHandler); } public function tearDown() { ini_set('session.serialize_handler', 'php'); } public function getConnectionClassString() { return '\Ratchet\ConnectionInterface'; } public function getDecoratorClassString() { return '\Ratchet\NullComponent'; } public function getComponentClassString() { return '\Ratchet\Http\HttpServerInterface'; } public function classCaseProvider() { return array( array('php', 'Php') , array('php_binary', 'PhpBinary') ); } /** * @dataProvider classCaseProvider */ public function testToClassCase($in, $out) { $ref = new \ReflectionClass('\\Ratchet\\Session\\SessionProvider'); $method = $ref->getMethod('toClassCase'); $method->setAccessible(true); $component = new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface')); $this->assertEquals($out, $method->invokeArgs($component, array($in))); } /** * I think I have severely butchered this test...it's not so much of a unit test as it is a full-fledged component test */ public function testConnectionValueFromPdo() { if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) { return $this->markTestSkipped('Session test requires PDO and pdo_sqlite'); } $sessionId = md5('testSession'); $dbOptions = array( 'db_table' => 'sessions' , 'db_id_col' => 'sess_id' , 'db_data_col' => 'sess_data' , 'db_time_col' => 'sess_time' , 'db_lifetime_col' => 'sess_lifetime' ); $pdo = new \PDO("sqlite::memory:"); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); $pdo->exec(vsprintf("CREATE TABLE %s (%s TEXT NOT NULL PRIMARY KEY, %s BLOB NOT NULL, %s INTEGER NOT NULL, %s INTEGER)", $dbOptions)); $pdoHandler = new PdoSessionHandler($pdo, $dbOptions); $pdoHandler->write($sessionId, '_sf2_attributes|a:2:{s:5:"hello";s:5:"world";s:4:"last";i:1332872102;}_sf2_flashes|a:0:{}'); $component = new SessionProvider($this->getMock($this->getComponentClassString()), $pdoHandler, array('auto_start' => 1)); $connection = $this->getMock('Ratchet\\ConnectionInterface'); $headers = $this->getMock('Psr\Http\Message\RequestInterface'); $headers->expects($this->once())->method('getHeader')->will($this->returnValue([ini_get('session.name') . "={$sessionId};"])); $component->onOpen($connection, $headers); $this->assertEquals('world', $connection->Session->get('hello')); } protected function newConn() { $conn = $this->getMock('Ratchet\ConnectionInterface'); $headers = $this->getMock('Psr\Http\Message\Request', array('getCookie'), array('POST', '/', array())); $headers->expects($this->once())->method('getCookie', array(ini_get('session.name')))->will($this->returnValue(null)); return $conn; } public function testOnMessageDecorator() { $message = "Database calls are usually blocking :("; $this->_app->expects($this->once())->method('onMessage')->with($this->isExpectedConnection(), $message); $this->_serv->onMessage($this->_conn, $message); } public function testRejectInvalidSeralizers() { if (!function_exists('wddx_serialize_value')) { $this->markTestSkipped(); } ini_set('session.serialize_handler', 'wddx'); $this->setExpectedException('\RuntimeException'); new SessionProvider($this->getMock($this->getComponentClassString()), $this->getMock('\SessionHandlerInterface')); } protected function doOpen($conn) { $request = $this->getMock('Psr\Http\Message\RequestInterface'); $request->expects($this->any())->method('getHeader')->will($this->returnValue([])); $this->_serv->onOpen($conn, $request); } } ratchet/tests/unit/Server/IoConnectionTest.php 0000664 00000001543 15177100702 0015532 0 ustar 00 <?php namespace Ratchet\Application\Server; use Ratchet\Server\IoConnection; /** * @covers Ratchet\Server\IoConnection */ class IoConnectionTest extends \PHPUnit_Framework_TestCase { protected $sock; protected $conn; public function setUp() { $this->sock = $this->getMock('\\React\\Socket\\ConnectionInterface'); $this->conn = new IoConnection($this->sock); } public function testCloseBubbles() { $this->sock->expects($this->once())->method('end'); $this->conn->close(); } public function testSendBubbles() { $msg = '6 hour rides are productive'; $this->sock->expects($this->once())->method('write')->with($msg); $this->conn->send($msg); } public function testSendReturnsSelf() { $this->assertSame($this->conn, $this->conn->send('fluent interface')); } } ratchet/tests/unit/Server/IpBlackListComponentTest.php 0000664 00000006700 15177100702 0017167 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\Server\IpBlackList; /** * @covers Ratchet\Server\IpBlackList */ class IpBlackListTest extends \PHPUnit_Framework_TestCase { protected $blocker; protected $mock; public function setUp() { $this->mock = $this->getMock('\\Ratchet\\MessageComponentInterface'); $this->blocker = new IpBlackList($this->mock); } public function testOnOpen() { $this->mock->expects($this->exactly(3))->method('onOpen'); $conn1 = $this->newConn(); $conn2 = $this->newConn(); $conn3 = $this->newConn(); $this->blocker->onOpen($conn1); $this->blocker->onOpen($conn3); $this->blocker->onOpen($conn2); } public function testBlockDoesNotTriggerOnOpen() { $conn = $this->newConn(); $this->blocker->blockAddress($conn->remoteAddress); $this->mock->expects($this->never())->method('onOpen'); $ret = $this->blocker->onOpen($conn); } public function testBlockDoesNotTriggerOnClose() { $conn = $this->newConn(); $this->blocker->blockAddress($conn->remoteAddress); $this->mock->expects($this->never())->method('onClose'); $ret = $this->blocker->onOpen($conn); } public function testOnMessageDecoration() { $conn = $this->newConn(); $msg = 'Hello not being blocked'; $this->mock->expects($this->once())->method('onMessage')->with($conn, $msg); $this->blocker->onMessage($conn, $msg); } public function testOnCloseDecoration() { $conn = $this->newConn(); $this->mock->expects($this->once())->method('onClose')->with($conn); $this->blocker->onClose($conn); } public function testBlockClosesConnection() { $conn = $this->newConn(); $this->blocker->blockAddress($conn->remoteAddress); $conn->expects($this->once())->method('close'); $this->blocker->onOpen($conn); } public function testAddAndRemoveWithFluentInterfaces() { $blockOne = '127.0.0.1'; $blockTwo = '192.168.1.1'; $unblock = '75.119.207.140'; $this->blocker ->blockAddress($unblock) ->blockAddress($blockOne) ->unblockAddress($unblock) ->blockAddress($blockTwo) ; $this->assertEquals(array($blockOne, $blockTwo), $this->blocker->getBlockedAddresses()); } public function testDecoratorPassesErrors() { $conn = $this->newConn(); $e = new \Exception('I threw an error'); $this->mock->expects($this->once())->method('onError')->with($conn, $e); $this->blocker->onError($conn, $e); } public function addressProvider() { return array( array('127.0.0.1', '127.0.0.1') , array('localhost', 'localhost') , array('fe80::1%lo0', 'fe80::1%lo0') , array('127.0.0.1', '127.0.0.1:6392') ); } /** * @dataProvider addressProvider */ public function testFilterAddress($expected, $input) { $this->assertEquals($expected, $this->blocker->filterAddress($input)); } public function testUnblockingSilentlyFails() { $this->assertInstanceOf('\\Ratchet\\Server\\IpBlackList', $this->blocker->unblockAddress('localhost')); } protected function newConn() { $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); $conn->remoteAddress = '127.0.0.1'; return $conn; } } ratchet/tests/unit/Server/EchoServerTest.php 0000664 00000001442 15177100702 0015206 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\Server\EchoServer; class EchoServerTest extends \PHPUnit_Framework_TestCase { protected $_conn; protected $_comp; public function setUp() { $this->_conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->_comp = new EchoServer; } public function testMessageEchod() { $message = 'Tillsonburg, my back still aches when I hear that word.'; $this->_conn->expects($this->once())->method('send')->with($message); $this->_comp->onMessage($this->_conn, $message); } public function testErrorClosesConnection() { ob_start(); $this->_conn->expects($this->once())->method('close'); $this->_comp->onError($this->_conn, new \Exception); ob_end_clean(); } } ratchet/tests/unit/Server/FlashPolicyComponentTest.php 0000664 00000011333 15177100702 0017241 0 ustar 00 <?php namespace Ratchet\Application\Server; use Ratchet\Server\FlashPolicy; /** * @covers Ratchet\Server\FlashPolicy */ class FlashPolicyTest extends \PHPUnit_Framework_TestCase { protected $_policy; public function setUp() { $this->_policy = new FlashPolicy(); } public function testPolicyRender() { $this->_policy->setSiteControl('all'); $this->_policy->addAllowedAccess('example.com', '*'); $this->_policy->addAllowedAccess('dev.example.com', '*'); $this->assertInstanceOf('SimpleXMLElement', $this->_policy->renderPolicy()); } public function testInvalidPolicyReader() { $this->setExpectedException('UnexpectedValueException'); $this->_policy->renderPolicy(); } public function testInvalidDomainPolicyReader() { $this->setExpectedException('UnexpectedValueException'); $this->_policy->setSiteControl('all'); $this->_policy->addAllowedAccess('dev.example.*', '*'); $this->_policy->renderPolicy(); } /** * @dataProvider siteControl */ public function testSiteControlValidation($accept, $permittedCrossDomainPolicies) { $this->assertEquals($accept, $this->_policy->validateSiteControl($permittedCrossDomainPolicies)); } public static function siteControl() { return array( array(true, 'all') , array(true, 'none') , array(true, 'master-only') , array(false, 'by-content-type') , array(false, 'by-ftp-filename') , array(false, '') , array(false, 'all ') , array(false, 'asdf') , array(false, '@893830') , array(false, '*') ); } /** * @dataProvider URI */ public function testDomainValidation($accept, $domain) { $this->assertEquals($accept, $this->_policy->validateDomain($domain)); } public static function URI() { return array( array(true, '*') , array(true, 'example.com') , array(true, 'exam-ple.com') , array(true, '*.example.com') , array(true, 'www.example.com') , array(true, 'dev.dev.example.com') , array(true, 'http://example.com') , array(true, 'https://example.com') , array(true, 'http://*.example.com') , array(false, 'exam*ple.com') , array(true, '127.0.255.1') , array(true, 'localhost') , array(false, 'www.example.*') , array(false, 'www.exa*le.com') , array(false, 'www.example.*com') , array(false, '*.example.*') , array(false, 'gasldf*$#a0sdf0a8sdf') ); } /** * @dataProvider ports */ public function testPortValidation($accept, $ports) { $this->assertEquals($accept, $this->_policy->validatePorts($ports)); } public static function ports() { return array( array(true, '*') , array(true, '80') , array(true, '80,443') , array(true, '507,516-523') , array(true, '507,516-523,333') , array(true, '507,516-523,507,516-523') , array(false, '516-') , array(true, '516-523,11') , array(false, '516,-523,11') , array(false, 'example') , array(false, 'asdf,123') , array(false, '--') , array(false, ',,,') , array(false, '838*') ); } public function testAddAllowedAccessOnlyAcceptsValidPorts() { $this->setExpectedException('UnexpectedValueException'); $this->_policy->addAllowedAccess('*', 'nope'); } public function testSetSiteControlThrowsException() { $this->setExpectedException('UnexpectedValueException'); $this->_policy->setSiteControl('nope'); } public function testErrorClosesConnection() { $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); $conn->expects($this->once())->method('close'); $this->_policy->onError($conn, new \Exception); } public function testOnMessageSendsString() { $this->_policy->addAllowedAccess('*', '*'); $conn = $this->getMock('\\Ratchet\\ConnectionInterface'); $conn->expects($this->once())->method('send')->with($this->isType('string')); $this->_policy->onMessage($conn, ' '); } public function testOnOpenExists() { $this->assertTrue(method_exists($this->_policy, 'onOpen')); $conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->_policy->onOpen($conn); } public function testOnCloseExists() { $this->assertTrue(method_exists($this->_policy, 'onClose')); $conn = $this->getMock('\Ratchet\ConnectionInterface'); $this->_policy->onClose($conn); } } ratchet/tests/unit/Server/IoServerTest.php 0000664 00000010156 15177100702 0014701 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\Server\IoServer; use React\EventLoop\StreamSelectLoop; use React\EventLoop\LoopInterface; use React\Socket\Server; /** * @covers Ratchet\Server\IoServer */ class IoServerTest extends \PHPUnit_Framework_TestCase { protected $server; protected $app; protected $port; protected $reactor; protected function tickLoop(LoopInterface $loop) { $loop->futureTick(function () use ($loop) { $loop->stop(); }); $loop->run(); } public function setUp() { $this->app = $this->getMock('\\Ratchet\\MessageComponentInterface'); $loop = new StreamSelectLoop; $this->reactor = new Server(0, $loop); $uri = $this->reactor->getAddress(); $this->port = parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_PORT); $this->server = new IoServer($this->app, $this->reactor, $loop); } public function testOnOpen() { $this->app->expects($this->once())->method('onOpen')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); $client = stream_socket_client("tcp://localhost:{$this->port}"); $this->tickLoop($this->server->loop); //$this->assertTrue(is_string($this->app->last['onOpen'][0]->remoteAddress)); //$this->assertTrue(is_int($this->app->last['onOpen'][0]->resourceId)); } public function testOnData() { $msg = 'Hello World!'; $this->app->expects($this->once())->method('onMessage')->with( $this->isInstanceOf('\\Ratchet\\ConnectionInterface') , $msg ); $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); socket_set_block($client); socket_connect($client, 'localhost', $this->port); $this->tickLoop($this->server->loop); socket_write($client, $msg); $this->tickLoop($this->server->loop); socket_shutdown($client, 1); socket_shutdown($client, 0); socket_close($client); $this->tickLoop($this->server->loop); } public function testOnClose() { $this->app->expects($this->once())->method('onClose')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface')); $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); socket_set_option($client, SOL_SOCKET, SO_REUSEADDR, 1); socket_set_option($client, SOL_SOCKET, SO_SNDBUF, 4096); socket_set_block($client); socket_connect($client, 'localhost', $this->port); $this->tickLoop($this->server->loop); socket_shutdown($client, 1); socket_shutdown($client, 0); socket_close($client); $this->tickLoop($this->server->loop); } public function testFactory() { $this->assertInstanceOf('\\Ratchet\\Server\\IoServer', IoServer::factory($this->app, 0)); } public function testNoLoopProvidedError() { $this->setExpectedException('RuntimeException'); $io = new IoServer($this->app, $this->reactor); $io->run(); } public function testOnErrorPassesException() { $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); $conn->decor = $this->getMock('\\Ratchet\\ConnectionInterface'); $err = new \Exception("Nope"); $this->app->expects($this->once())->method('onError')->with($conn->decor, $err); $this->server->handleError($err, $conn); } public function onErrorCalledWhenExceptionThrown() { $this->markTestIncomplete("Need to learn how to throw an exception from a mock"); $conn = $this->getMock('\\React\\Socket\\ConnectionInterface'); $this->server->handleConnect($conn); $e = new \Exception; $this->app->expects($this->once())->method('onMessage')->with($this->isInstanceOf('\\Ratchet\\ConnectionInterface'), 'f')->will($e); $this->app->expects($this->once())->method('onError')->with($this->instanceOf('\\Ratchet\\ConnectionInterface', $e)); $this->server->handleData('f', $conn); } } ratchet/tests/unit/error_log 0000644 00000000524 15177100702 0012235 0 ustar 00 [06-May-2026 00:41:17 UTC] PHP Fatal error: Uncaught Error: Class "PHPUnit_Framework_TestCase" not found in /home/toptrendingappst/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php:9 Stack trace: #0 {main} thrown in /home/toptrendingappst/vendor/cboden/ratchet/tests/unit/AbstractConnectionDecoratorTest.php on line 9 ratchet/tests/unit/AbstractConnectionDecoratorTest.php 0000664 00000010035 15177100702 0017317 0 ustar 00 <?php namespace Ratchet; use Ratchet\Mock\ConnectionDecorator; /** * @covers Ratchet\AbstractConnectionDecorator * @covers Ratchet\ConnectionInterface */ class AbstractConnectionDecoratorTest extends \PHPUnit_Framework_TestCase { protected $mock; protected $l1; protected $l2; public function setUp() { $this->mock = $this->getMock('\Ratchet\ConnectionInterface'); $this->l1 = new ConnectionDecorator($this->mock); $this->l2 = new ConnectionDecorator($this->l1); } public function testGet() { $var = 'hello'; $val = 'world'; $this->mock->$var = $val; $this->assertEquals($val, $this->l1->$var); $this->assertEquals($val, $this->l2->$var); } public function testSet() { $var = 'Chris'; $val = 'Boden'; $this->l1->$var = $val; $this->assertEquals($val, $this->mock->$var); } public function testSetLevel2() { $var = 'Try'; $val = 'Again'; $this->l2->$var = $val; $this->assertEquals($val, $this->mock->$var); } public function testIsSetTrue() { $var = 'PHP'; $val = 'Ratchet'; $this->mock->$var = $val; $this->assertTrue(isset($this->l1->$var)); $this->assertTrue(isset($this->l2->$var)); } public function testIsSetFalse() { $var = 'herp'; $val = 'derp'; $this->assertFalse(isset($this->l1->$var)); $this->assertFalse(isset($this->l2->$var)); } public function testUnset() { $var = 'Flying'; $val = 'Monkey'; $this->mock->$var = $val; unset($this->l1->$var); $this->assertFalse(isset($this->mock->$var)); } public function testUnsetLevel2() { $var = 'Flying'; $val = 'Monkey'; $this->mock->$var = $val; unset($this->l2->$var); $this->assertFalse(isset($this->mock->$var)); } public function testGetConnection() { $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator'); $method = $class->getMethod('getConnection'); $method->setAccessible(true); $conn = $method->invokeArgs($this->l1, array()); $this->assertSame($this->mock, $conn); } public function testGetConnectionLevel2() { $class = new \ReflectionClass('\\Ratchet\\AbstractConnectionDecorator'); $method = $class->getMethod('getConnection'); $method->setAccessible(true); $conn = $method->invokeArgs($this->l2, array()); $this->assertSame($this->l1, $conn); } public function testWrapperCanStoreSelfInDecorator() { $this->mock->decorator = $this->l1; $this->assertSame($this->l1, $this->l2->decorator); } public function testDecoratorRecursion() { $this->mock->decorator = new \stdClass; $this->mock->decorator->conn = $this->l1; $this->assertSame($this->l1, $this->mock->decorator->conn); $this->assertSame($this->l1, $this->l1->decorator->conn); $this->assertSame($this->l1, $this->l2->decorator->conn); } public function testDecoratorRecursionLevel2() { $this->mock->decorator = new \stdClass; $this->mock->decorator->conn = $this->l2; $this->assertSame($this->l2, $this->mock->decorator->conn); $this->assertSame($this->l2, $this->l1->decorator->conn); $this->assertSame($this->l2, $this->l2->decorator->conn); // just for fun $this->assertSame($this->l2, $this->l2->decorator->conn->decorator->conn->decorator->conn); } public function testWarningGettingNothing() { $this->setExpectedException('PHPUnit_Framework_Error'); $var = $this->mock->nonExistant; } public function testWarningGettingNothingLevel1() { $this->setExpectedException('PHPUnit_Framework_Error'); $var = $this->l1->nonExistant; } public function testWarningGettingNothingLevel2() { $this->setExpectedException('PHPUnit_Framework_Error'); $var = $this->l2->nonExistant; } } ratchet/tests/error_log 0000644 00000001215 15177100702 0011254 0 ustar 00 [05-May-2026 15:46:40 UTC] PHP Warning: require(/home/toptrendingappst/vendor/cboden/ratchet/tests/../vendor/autoload.php): Failed to open stream: No such file or directory in /home/toptrendingappst/vendor/cboden/ratchet/tests/bootstrap.php on line 3 [05-May-2026 15:46:40 UTC] PHP Fatal error: Uncaught Error: Failed opening required '/home/toptrendingappst/vendor/cboden/ratchet/tests/../vendor/autoload.php' (include_path='.:/opt/cpanel/ea-php81/root/usr/share/pear') in /home/toptrendingappst/vendor/cboden/ratchet/tests/bootstrap.php:3 Stack trace: #0 {main} thrown in /home/toptrendingappst/vendor/cboden/ratchet/tests/bootstrap.php on line 3 ratchet/tests/bootstrap.php 0000664 00000000203 15177100702 0012063 0 ustar 00 <?php $loader = require __DIR__ . '/../vendor/autoload.php'; $loader->addPsr4('Ratchet\\', __DIR__ . '/helpers/Ratchet'); ratchet/src/Ratchet/Http/NoOpHttpServerController.php 0000664 00000000740 15177100702 0016760 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\ConnectionInterface; use Psr\Http\Message\RequestInterface; class NoOpHttpServerController implements HttpServerInterface { public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { } public function onMessage(ConnectionInterface $from, $msg) { } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { } } ratchet/src/Ratchet/Http/Router.php 0000664 00000005727 15177100702 0013304 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\ConnectionInterface; use Psr\Http\Message\RequestInterface; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use GuzzleHttp\Psr7\Query; class Router implements HttpServerInterface { use CloseResponseTrait; /** * @var \Symfony\Component\Routing\Matcher\UrlMatcherInterface */ protected $_matcher; private $_noopController; public function __construct(UrlMatcherInterface $matcher) { $this->_matcher = $matcher; $this->_noopController = new NoOpHttpServerController; } /** * {@inheritdoc} * @throws \UnexpectedValueException If a controller is not \Ratchet\Http\HttpServerInterface */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { if (null === $request) { throw new \UnexpectedValueException('$request can not be null'); } $conn->controller = $this->_noopController; $uri = $request->getUri(); $context = $this->_matcher->getContext(); $context->setMethod($request->getMethod()); $context->setHost($uri->getHost()); try { $route = $this->_matcher->match($uri->getPath()); } catch (MethodNotAllowedException $nae) { return $this->close($conn, 405, array('Allow' => $nae->getAllowedMethods())); } catch (ResourceNotFoundException $nfe) { return $this->close($conn, 404); } if (is_string($route['_controller']) && class_exists($route['_controller'])) { $route['_controller'] = new $route['_controller']; } if (!($route['_controller'] instanceof HttpServerInterface)) { throw new \UnexpectedValueException('All routes must implement Ratchet\Http\HttpServerInterface'); } $parameters = []; foreach($route as $key => $value) { if ((is_string($key)) && ('_' !== substr($key, 0, 1))) { $parameters[$key] = $value; } } $parameters = array_merge($parameters, Query::parse($uri->getQuery() ?: '')); $request = $request->withUri($uri->withQuery(Query::build($parameters))); $conn->controller = $route['_controller']; $conn->controller->onOpen($conn, $request); } /** * {@inheritdoc} */ public function onMessage(ConnectionInterface $from, $msg) { $from->controller->onMessage($from, $msg); } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { if (isset($conn->controller)) { $conn->controller->onClose($conn); } } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { if (isset($conn->controller)) { $conn->controller->onError($conn, $e); } } } ratchet/src/Ratchet/Http/CloseResponseTrait.php 0000664 00000001235 15177100702 0015602 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\ConnectionInterface; use GuzzleHttp\Psr7\Message; use GuzzleHttp\Psr7\Response; trait CloseResponseTrait { /** * Close a connection with an HTTP response * @param \Ratchet\ConnectionInterface $conn * @param int $code HTTP status code * @return null */ private function close(ConnectionInterface $conn, $code = 400, array $additional_headers = []) { $response = new Response($code, array_merge([ 'X-Powered-By' => \Ratchet\VERSION ], $additional_headers)); $conn->send(Message::toString($response)); $conn->close(); } } ratchet/src/Ratchet/Http/HttpServer.php 0000664 00000003631 15177100702 0014122 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; class HttpServer implements MessageComponentInterface { use CloseResponseTrait; /** * Buffers incoming HTTP requests returning a Guzzle Request when coalesced * @var HttpRequestParser * @note May not expose this in the future, may do through facade methods */ protected $_reqParser; /** * @var \Ratchet\Http\HttpServerInterface */ protected $_httpServer; /** * @param HttpServerInterface */ public function __construct(HttpServerInterface $component) { $this->_httpServer = $component; $this->_reqParser = new HttpRequestParser; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $conn->httpHeadersReceived = false; } /** * {@inheritdoc} */ public function onMessage(ConnectionInterface $from, $msg) { if (true !== $from->httpHeadersReceived) { try { if (null === ($request = $this->_reqParser->onMessage($from, $msg))) { return; } } catch (\OverflowException $oe) { return $this->close($from, 413); } $from->httpHeadersReceived = true; return $this->_httpServer->onOpen($from, $request); } $this->_httpServer->onMessage($from, $msg); } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { if ($conn->httpHeadersReceived) { $this->_httpServer->onClose($conn); } } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { if ($conn->httpHeadersReceived) { $this->_httpServer->onError($conn, $e); } else { $this->close($conn, 500); } } } ratchet/src/Ratchet/Http/HttpRequestParser.php 0000664 00000003445 15177100702 0015464 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\MessageInterface; use Ratchet\ConnectionInterface; use GuzzleHttp\Psr7\Message; /** * This class receives streaming data from a client request * and parses HTTP headers, returning a PSR-7 Request object * once it's been buffered */ class HttpRequestParser implements MessageInterface { const EOM = "\r\n\r\n"; /** * The maximum number of bytes the request can be * This is a security measure to prevent attacks * @var int */ public $maxSize = 4096; /** * @param \Ratchet\ConnectionInterface $context * @param string $data Data stream to buffer * @return \Psr\Http\Message\RequestInterface * @throws \OverflowException If the message buffer has become too large */ public function onMessage(ConnectionInterface $context, $data) { if (!isset($context->httpBuffer)) { $context->httpBuffer = ''; } $context->httpBuffer .= $data; if (strlen($context->httpBuffer) > (int)$this->maxSize) { throw new \OverflowException("Maximum buffer size of {$this->maxSize} exceeded parsing HTTP header"); } if ($this->isEom($context->httpBuffer)) { $request = $this->parse($context->httpBuffer); unset($context->httpBuffer); return $request; } } /** * Determine if the message has been buffered as per the HTTP specification * @param string $message * @return boolean */ public function isEom($message) { return (boolean)strpos($message, static::EOM); } /** * @param string $headers * @return \Psr\Http\Message\RequestInterface */ public function parse($headers) { return Message::parseRequest($headers); } } ratchet/src/Ratchet/Http/OriginCheck.php 0000664 00000003525 15177100702 0014203 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\ConnectionInterface; use Ratchet\MessageComponentInterface; use Psr\Http\Message\RequestInterface; /** * A middleware to ensure JavaScript clients connecting are from the expected domain. * This protects other websites from open WebSocket connections to your application. * Note: This can be spoofed from non-web browser clients */ class OriginCheck implements HttpServerInterface { use CloseResponseTrait; /** * @var \Ratchet\MessageComponentInterface */ protected $_component; public $allowedOrigins = []; /** * @param MessageComponentInterface $component Component/Application to decorate * @param array $allowed An array of allowed domains that are allowed to connect from */ public function __construct(MessageComponentInterface $component, array $allowed = []) { $this->_component = $component; $this->allowedOrigins += $allowed; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { $header = (string)$request->getHeader('Origin')[0]; $origin = parse_url($header, PHP_URL_HOST) ?: $header; if (!in_array($origin, $this->allowedOrigins)) { return $this->close($conn, 403); } return $this->_component->onOpen($conn, $request); } /** * {@inheritdoc} */ function onMessage(ConnectionInterface $from, $msg) { return $this->_component->onMessage($from, $msg); } /** * {@inheritdoc} */ function onClose(ConnectionInterface $conn) { return $this->_component->onClose($conn); } /** * {@inheritdoc} */ function onError(ConnectionInterface $conn, \Exception $e) { return $this->_component->onError($conn, $e); } } ratchet/src/Ratchet/Http/HttpServerInterface.php 0000664 00000001105 15177100702 0015735 0 ustar 00 <?php namespace Ratchet\Http; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; use Psr\Http\Message\RequestInterface; interface HttpServerInterface extends MessageComponentInterface { /** * @param \Ratchet\ConnectionInterface $conn * @param \Psr\Http\Message\RequestInterface $request null is default because PHP won't let me overload; don't pass null!!! * @throws \UnexpectedValueException if a RequestInterface is not passed */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null); } ratchet/src/Ratchet/WebSocket/WsServer.php 0000664 00000016324 15177100702 0014546 0 ustar 00 <?php namespace Ratchet\WebSocket; use Ratchet\ComponentInterface; use Ratchet\ConnectionInterface; use Ratchet\MessageComponentInterface as DataComponentInterface; use Ratchet\Http\HttpServerInterface; use Ratchet\Http\CloseResponseTrait; use Psr\Http\Message\RequestInterface; use Ratchet\RFC6455\Messaging\MessageInterface; use Ratchet\RFC6455\Messaging\FrameInterface; use Ratchet\RFC6455\Messaging\Frame; use Ratchet\RFC6455\Messaging\MessageBuffer; use Ratchet\RFC6455\Messaging\CloseFrameChecker; use Ratchet\RFC6455\Handshake\ServerNegotiator; use Ratchet\RFC6455\Handshake\RequestVerifier; use React\EventLoop\LoopInterface; use GuzzleHttp\Psr7\Message; /** * The adapter to handle WebSocket requests/responses * This is a mediator between the Server and your application to handle real-time messaging through a web browser * @link http://ca.php.net/manual/en/ref.http.php * @link http://dev.w3.org/html5/websockets/ */ class WsServer implements HttpServerInterface { use CloseResponseTrait; /** * Decorated component * @var \Ratchet\ComponentInterface */ private $delegate; /** * @var \SplObjectStorage */ protected $connections; /** * @var \Ratchet\RFC6455\Messaging\CloseFrameChecker */ private $closeFrameChecker; /** * @var \Ratchet\RFC6455\Handshake\ServerNegotiator */ private $handshakeNegotiator; /** * @var \Closure */ private $ueFlowFactory; /** * @var \Closure */ private $pongReceiver; /** * @var \Closure */ private $msgCb; /** * @param \Ratchet\WebSocket\MessageComponentInterface|\Ratchet\MessageComponentInterface $component Your application to run with WebSockets * @note If you want to enable sub-protocols have your component implement WsServerInterface as well */ public function __construct(ComponentInterface $component) { if ($component instanceof MessageComponentInterface) { $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) { $this->delegate->onMessage($conn, $msg); }; } elseif ($component instanceof DataComponentInterface) { $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) { $this->delegate->onMessage($conn, $msg->getPayload()); }; } else { throw new \UnexpectedValueException('Expected instance of \Ratchet\WebSocket\MessageComponentInterface or \Ratchet\MessageComponentInterface'); } if (bin2hex('✓') !== 'e29c93') { throw new \DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload'); } $this->delegate = $component; $this->connections = new \SplObjectStorage; $this->closeFrameChecker = new CloseFrameChecker; $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier); $this->handshakeNegotiator->setStrictSubProtocolCheck(true); if ($component instanceof WsServerInterface) { $this->handshakeNegotiator->setSupportedSubProtocols($component->getSubProtocols()); } $this->pongReceiver = function() {}; $reusableUnderflowException = new \UnderflowException; $this->ueFlowFactory = function() use ($reusableUnderflowException) { return $reusableUnderflowException; }; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { if (null === $request) { throw new \UnexpectedValueException('$request can not be null'); } $conn->httpRequest = $request; $conn->WebSocket = new \StdClass; $conn->WebSocket->closing = false; $response = $this->handshakeNegotiator->handshake($request)->withHeader('X-Powered-By', \Ratchet\VERSION); $conn->send(Message::toString($response)); if (101 !== $response->getStatusCode()) { return $conn->close(); } $wsConn = new WsConnection($conn); $streamer = new MessageBuffer( $this->closeFrameChecker, function(MessageInterface $msg) use ($wsConn) { $cb = $this->msgCb; $cb($wsConn, $msg); }, function(FrameInterface $frame) use ($wsConn) { $this->onControlFrame($frame, $wsConn); }, true, $this->ueFlowFactory ); $this->connections->attach($conn, new ConnContext($wsConn, $streamer)); return $this->delegate->onOpen($wsConn); } /** * {@inheritdoc} */ public function onMessage(ConnectionInterface $from, $msg) { if ($from->WebSocket->closing) { return; } $this->connections[$from]->buffer->onData($msg); } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { if ($this->connections->contains($conn)) { $context = $this->connections[$conn]; $this->connections->detach($conn); $this->delegate->onClose($context->connection); } } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { if ($this->connections->contains($conn)) { $this->delegate->onError($this->connections[$conn]->connection, $e); } else { $conn->close(); } } public function onControlFrame(FrameInterface $frame, WsConnection $conn) { switch ($frame->getOpCode()) { case Frame::OP_CLOSE: $conn->close($frame); break; case Frame::OP_PING: $conn->send(new Frame($frame->getPayload(), true, Frame::OP_PONG)); break; case Frame::OP_PONG: $pongReceiver = $this->pongReceiver; $pongReceiver($frame, $conn); break; } } public function setStrictSubProtocolCheck($enable) { $this->handshakeNegotiator->setStrictSubProtocolCheck($enable); } public function enableKeepAlive(LoopInterface $loop, $interval = 30) { $lastPing = new Frame(uniqid(), true, Frame::OP_PING); $pingedConnections = new \SplObjectStorage; $splClearer = new \SplObjectStorage; $this->pongReceiver = function(FrameInterface $frame, $wsConn) use ($pingedConnections, &$lastPing) { if ($frame->getPayload() === $lastPing->getPayload()) { $pingedConnections->detach($wsConn); } }; $loop->addPeriodicTimer((int)$interval, function() use ($pingedConnections, &$lastPing, $splClearer) { foreach ($pingedConnections as $wsConn) { $wsConn->close(); } $pingedConnections->removeAllExcept($splClearer); $lastPing = new Frame(uniqid(), true, Frame::OP_PING); foreach ($this->connections as $key => $conn) { $wsConn = $this->connections[$conn]->connection; $wsConn->send($lastPing); $pingedConnections->attach($wsConn); } }); } } ratchet/src/Ratchet/WebSocket/WsServerInterface.php 0000664 00000000616 15177100702 0016364 0 ustar 00 <?php namespace Ratchet\WebSocket; /** * WebSocket Server Interface */ interface WsServerInterface { /** * If any component in a stack supports a WebSocket sub-protocol return each supported in an array * @return array * @todo This method may be removed in future version (note that will not break code, just make some code obsolete) */ function getSubProtocols(); } ratchet/src/Ratchet/WebSocket/MessageCallableInterface.php 0000664 00000000355 15177100702 0017610 0 ustar 00 <?php namespace Ratchet\WebSocket; use Ratchet\ConnectionInterface; use Ratchet\RFC6455\Messaging\MessageInterface; interface MessageCallableInterface { public function onMessage(ConnectionInterface $conn, MessageInterface $msg); } ratchet/src/Ratchet/WebSocket/ConnContext.php 0000664 00000000656 15177100702 0015231 0 ustar 00 <?php namespace Ratchet\WebSocket; use Ratchet\RFC6455\Messaging\MessageBuffer; class ConnContext { /** * @var \Ratchet\WebSocket\WsConnection */ public $connection; /** * @var \Ratchet\RFC6455\Messaging\MessageBuffer; */ public $buffer; public function __construct(WsConnection $conn, MessageBuffer $buffer) { $this->connection = $conn; $this->buffer = $buffer; } } ratchet/src/Ratchet/WebSocket/WsConnection.php 0000664 00000002045 15177100702 0015372 0 ustar 00 <?php namespace Ratchet\WebSocket; use Ratchet\AbstractConnectionDecorator; use Ratchet\RFC6455\Messaging\DataInterface; use Ratchet\RFC6455\Messaging\Frame; /** * {@inheritdoc} * @property \StdClass $WebSocket */ class WsConnection extends AbstractConnectionDecorator { /** * {@inheritdoc} */ public function send($msg) { if (!$this->WebSocket->closing) { if (!($msg instanceof DataInterface)) { $msg = new Frame($msg); } $this->getConnection()->send($msg->getContents()); } return $this; } /** * @param int|\Ratchet\RFC6455\Messaging\DataInterface */ public function close($code = 1000) { if ($this->WebSocket->closing) { return; } if ($code instanceof DataInterface) { $this->send($code); } else { $this->send(new Frame(pack('n', $code), true, Frame::OP_CLOSE)); } $this->getConnection()->close(); $this->WebSocket->closing = true; } } ratchet/src/Ratchet/WebSocket/MessageComponentInterface.php 0000664 00000000241 15177100702 0020045 0 ustar 00 <?php namespace Ratchet\WebSocket; use Ratchet\ComponentInterface; interface MessageComponentInterface extends ComponentInterface, MessageCallableInterface { } ratchet/src/Ratchet/Wamp/TopicManager.php 0000664 00000006030 15177100702 0014346 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\ConnectionInterface; use Ratchet\WebSocket\WsServerInterface; class TopicManager implements WsServerInterface, WampServerInterface { /** * @var WampServerInterface */ protected $app; /** * @var array */ protected $topicLookup = array(); public function __construct(WampServerInterface $app) { $this->app = $app; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $conn->WAMP->subscriptions = new \SplObjectStorage; $this->app->onOpen($conn); } /** * {@inheritdoc} */ public function onCall(ConnectionInterface $conn, $id, $topic, array $params) { $this->app->onCall($conn, $id, $this->getTopic($topic), $params); } /** * {@inheritdoc} */ public function onSubscribe(ConnectionInterface $conn, $topic) { $topicObj = $this->getTopic($topic); if ($conn->WAMP->subscriptions->contains($topicObj)) { return; } $this->topicLookup[$topic]->add($conn); $conn->WAMP->subscriptions->attach($topicObj); $this->app->onSubscribe($conn, $topicObj); } /** * {@inheritdoc} */ public function onUnsubscribe(ConnectionInterface $conn, $topic) { $topicObj = $this->getTopic($topic); if (!$conn->WAMP->subscriptions->contains($topicObj)) { return; } $this->cleanTopic($topicObj, $conn); $this->app->onUnsubscribe($conn, $topicObj); } /** * {@inheritdoc} */ public function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible) { $this->app->onPublish($conn, $this->getTopic($topic), $event, $exclude, $eligible); } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { $this->app->onClose($conn); foreach ($this->topicLookup as $topic) { $this->cleanTopic($topic, $conn); } } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { $this->app->onError($conn, $e); } /** * {@inheritdoc} */ public function getSubProtocols() { if ($this->app instanceof WsServerInterface) { return $this->app->getSubProtocols(); } return array(); } /** * @param string * @return Topic */ protected function getTopic($topic) { if (!array_key_exists($topic, $this->topicLookup)) { $this->topicLookup[$topic] = new Topic($topic); } return $this->topicLookup[$topic]; } protected function cleanTopic(Topic $topic, ConnectionInterface $conn) { if ($conn->WAMP->subscriptions->contains($topic)) { $conn->WAMP->subscriptions->detach($topic); } $this->topicLookup[$topic->getId()]->remove($conn); if (0 === $topic->count()) { unset($this->topicLookup[$topic->getId()]); } } } ratchet/src/Ratchet/Wamp/WampServer.php 0000664 00000003502 15177100702 0014071 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; /** * Enable support for the official WAMP sub-protocol in your application * WAMP allows for Pub/Sub and RPC * @link http://wamp.ws The WAMP specification * @link https://github.com/oberstet/autobahn-js Souce for client side library * @link http://autobahn.s3.amazonaws.com/js/autobahn.min.js Minified client side library */ class WampServer implements MessageComponentInterface, WsServerInterface { /** * @var ServerProtocol */ protected $wampProtocol; /** * This class just makes it 1 step easier to use Topic objects in WAMP * If you're looking at the source code, look in the __construct of this * class and use that to make your application instead of using this */ public function __construct(WampServerInterface $app) { $this->wampProtocol = new ServerProtocol(new TopicManager($app)); } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $this->wampProtocol->onOpen($conn); } /** * {@inheritdoc} */ public function onMessage(ConnectionInterface $conn, $msg) { try { $this->wampProtocol->onMessage($conn, $msg); } catch (Exception $we) { $conn->close(1007); } } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { $this->wampProtocol->onClose($conn); } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { $this->wampProtocol->onError($conn, $e); } /** * {@inheritdoc} */ public function getSubProtocols() { return $this->wampProtocol->getSubProtocols(); } } ratchet/src/Ratchet/Wamp/WampServerInterface.php 0000664 00000003662 15177100702 0015721 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\ComponentInterface; use Ratchet\ConnectionInterface; /** * An extension of Ratchet\ComponentInterface to server a WAMP application * onMessage is replaced by various types of messages for this protocol (pub/sub or rpc) */ interface WampServerInterface extends ComponentInterface { /** * An RPC call has been received * @param \Ratchet\ConnectionInterface $conn * @param string $id The unique ID of the RPC, required to respond to * @param string|Topic $topic The topic to execute the call against * @param array $params Call parameters received from the client */ function onCall(ConnectionInterface $conn, $id, $topic, array $params); /** * A request to subscribe to a topic has been made * @param \Ratchet\ConnectionInterface $conn * @param string|Topic $topic The topic to subscribe to */ function onSubscribe(ConnectionInterface $conn, $topic); /** * A request to unsubscribe from a topic has been made * @param \Ratchet\ConnectionInterface $conn * @param string|Topic $topic The topic to unsubscribe from */ function onUnSubscribe(ConnectionInterface $conn, $topic); /** * A client is attempting to publish content to a subscribed connections on a URI * @param \Ratchet\ConnectionInterface $conn * @param string|Topic $topic The topic the user has attempted to publish to * @param string $event Payload of the publish * @param array $exclude A list of session IDs the message should be excluded from (blacklist) * @param array $eligible A list of session Ids the message should be send to (whitelist) */ function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible); } ratchet/src/Ratchet/Wamp/Exception.php 0000664 00000000106 15177100702 0013731 0 ustar 00 <?php namespace Ratchet\Wamp; class Exception extends \Exception { } ratchet/src/Ratchet/Wamp/WampConnection.php 0000664 00000006660 15177100702 0014732 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\ConnectionInterface; use Ratchet\AbstractConnectionDecorator; use Ratchet\Wamp\ServerProtocol as WAMP; /** * A ConnectionInterface object wrapper that is passed to your WAMP application * representing a client. Methods on this Connection are therefore different. * @property \stdClass $WAMP */ class WampConnection extends AbstractConnectionDecorator { /** * {@inheritdoc} */ public function __construct(ConnectionInterface $conn) { parent::__construct($conn); $this->WAMP = new \StdClass; $this->WAMP->sessionId = str_replace('.', '', uniqid(mt_rand(), true)); $this->WAMP->prefixes = array(); $this->send(json_encode(array(WAMP::MSG_WELCOME, $this->WAMP->sessionId, 1, \Ratchet\VERSION))); } /** * Successfully respond to a call made by the client * @param string $id The unique ID given by the client to respond to * @param array $data an object or array * @return WampConnection */ public function callResult($id, $data = array()) { return $this->send(json_encode(array(WAMP::MSG_CALL_RESULT, $id, $data))); } /** * Respond with an error to a client call * @param string $id The unique ID given by the client to respond to * @param string $errorUri The URI given to identify the specific error * @param string $desc A developer-oriented description of the error * @param string $details An optional human readable detail message to send back * @return WampConnection */ public function callError($id, $errorUri, $desc = '', $details = null) { if ($errorUri instanceof Topic) { $errorUri = (string)$errorUri; } $data = array(WAMP::MSG_CALL_ERROR, $id, $errorUri, $desc); if (null !== $details) { $data[] = $details; } return $this->send(json_encode($data)); } /** * @param string $topic The topic to broadcast to * @param mixed $msg Data to send with the event. Anything that is json'able * @return WampConnection */ public function event($topic, $msg) { return $this->send(json_encode(array(WAMP::MSG_EVENT, (string)$topic, $msg))); } /** * @param string $curie * @param string $uri * @return WampConnection */ public function prefix($curie, $uri) { $this->WAMP->prefixes[$curie] = (string)$uri; return $this->send(json_encode(array(WAMP::MSG_PREFIX, $curie, (string)$uri))); } /** * Get the full request URI from the connection object if a prefix has been established for it * @param string $uri * @return string */ public function getUri($uri) { $curieSeperator = ':'; if (preg_match('/http(s*)\:\/\//', $uri) == false) { if (strpos($uri, $curieSeperator) !== false) { list($prefix, $action) = explode($curieSeperator, $uri); if(isset($this->WAMP->prefixes[$prefix]) === true){ return $this->WAMP->prefixes[$prefix] . '#' . $action; } } } return $uri; } /** * @internal */ public function send($data) { $this->getConnection()->send($data); return $this; } /** * {@inheritdoc} */ public function close($opt = null) { $this->getConnection()->close($opt); } } ratchet/src/Ratchet/Wamp/ServerProtocol.php 0000664 00000011235 15177100702 0014770 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\MessageComponentInterface; use Ratchet\WebSocket\WsServerInterface; use Ratchet\ConnectionInterface; /** * WebSocket Application Messaging Protocol * * @link http://wamp.ws/spec * @link https://github.com/oberstet/autobahn-js * * +--------------+----+------------------+ * | Message Type | ID | DIRECTION | * |--------------+----+------------------+ * | WELCOME | 0 | Server-to-Client | * | PREFIX | 1 | Bi-Directional | * | CALL | 2 | Client-to-Server | * | CALL RESULT | 3 | Server-to-Client | * | CALL ERROR | 4 | Server-to-Client | * | SUBSCRIBE | 5 | Client-to-Server | * | UNSUBSCRIBE | 6 | Client-to-Server | * | PUBLISH | 7 | Client-to-Server | * | EVENT | 8 | Server-to-Client | * +--------------+----+------------------+ */ class ServerProtocol implements MessageComponentInterface, WsServerInterface { const MSG_WELCOME = 0; const MSG_PREFIX = 1; const MSG_CALL = 2; const MSG_CALL_RESULT = 3; const MSG_CALL_ERROR = 4; const MSG_SUBSCRIBE = 5; const MSG_UNSUBSCRIBE = 6; const MSG_PUBLISH = 7; const MSG_EVENT = 8; /** * @var WampServerInterface */ protected $_decorating; /** * @var \SplObjectStorage */ protected $connections; /** * @param WampServerInterface $serverComponent An class to propagate calls through */ public function __construct(WampServerInterface $serverComponent) { $this->_decorating = $serverComponent; $this->connections = new \SplObjectStorage; } /** * {@inheritdoc} */ public function getSubProtocols() { if ($this->_decorating instanceof WsServerInterface) { $subs = $this->_decorating->getSubProtocols(); $subs[] = 'wamp'; return $subs; } return ['wamp']; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { $decor = new WampConnection($conn); $this->connections->attach($conn, $decor); $this->_decorating->onOpen($decor); } /** * {@inheritdoc} * @throws \Ratchet\Wamp\Exception * @throws \Ratchet\Wamp\JsonException */ public function onMessage(ConnectionInterface $from, $msg) { $from = $this->connections[$from]; if (null === ($json = @json_decode($msg, true))) { throw new JsonException; } if (!is_array($json) || $json !== array_values($json)) { throw new Exception("Invalid WAMP message format"); } if (isset($json[1]) && !(is_string($json[1]) || is_numeric($json[1]))) { throw new Exception('Invalid Topic, must be a string'); } switch ($json[0]) { case static::MSG_PREFIX: $from->WAMP->prefixes[$json[1]] = $json[2]; break; case static::MSG_CALL: array_shift($json); $callID = array_shift($json); $procURI = array_shift($json); if (count($json) == 1 && is_array($json[0])) { $json = $json[0]; } $this->_decorating->onCall($from, $callID, $from->getUri($procURI), $json); break; case static::MSG_SUBSCRIBE: $this->_decorating->onSubscribe($from, $from->getUri($json[1])); break; case static::MSG_UNSUBSCRIBE: $this->_decorating->onUnSubscribe($from, $from->getUri($json[1])); break; case static::MSG_PUBLISH: $exclude = (array_key_exists(3, $json) ? $json[3] : null); if (!is_array($exclude)) { if (true === (boolean)$exclude) { $exclude = [$from->WAMP->sessionId]; } else { $exclude = []; } } $eligible = (array_key_exists(4, $json) ? $json[4] : []); $this->_decorating->onPublish($from, $from->getUri($json[1]), $json[2], $exclude, $eligible); break; default: throw new Exception('Invalid WAMP message type'); } } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { $decor = $this->connections[$conn]; $this->connections->detach($conn); $this->_decorating->onClose($decor); } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { return $this->_decorating->onError($this->connections[$conn], $e); } } ratchet/src/Ratchet/Wamp/JsonException.php 0000664 00000001610 15177100702 0014564 0 ustar 00 <?php namespace Ratchet\Wamp; class JsonException extends Exception { public function __construct() { $code = json_last_error(); switch ($code) { case JSON_ERROR_DEPTH: $msg = 'Maximum stack depth exceeded'; break; case JSON_ERROR_STATE_MISMATCH: $msg = 'Underflow or the modes mismatch'; break; case JSON_ERROR_CTRL_CHAR: $msg = 'Unexpected control character found'; break; case JSON_ERROR_SYNTAX: $msg = 'Syntax error, malformed JSON'; break; case JSON_ERROR_UTF8: $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded'; break; default: $msg = 'Unknown error'; break; } parent::__construct($msg, $code); } } ratchet/src/Ratchet/Wamp/Topic.php 0000664 00000004604 15177100702 0013060 0 ustar 00 <?php namespace Ratchet\Wamp; use Ratchet\ConnectionInterface; /** * A topic/channel containing connections that have subscribed to it */ class Topic implements \IteratorAggregate, \Countable { private $id; private $subscribers; /** * @param string $topicId Unique ID for this object */ public function __construct($topicId) { $this->id = $topicId; $this->subscribers = new \SplObjectStorage; } /** * @return string */ public function getId() { return $this->id; } public function __toString() { return $this->getId(); } /** * Send a message to all the connections in this topic * @param string|array $msg Payload to publish * @param array $exclude A list of session IDs the message should be excluded from (blacklist) * @param array $eligible A list of session Ids the message should be send to (whitelist) * @return Topic The same Topic object to chain */ public function broadcast($msg, array $exclude = array(), array $eligible = array()) { $useEligible = (bool)count($eligible); foreach ($this->subscribers as $client) { if (in_array($client->WAMP->sessionId, $exclude)) { continue; } if ($useEligible && !in_array($client->WAMP->sessionId, $eligible)) { continue; } $client->event($this->id, $msg); } return $this; } /** * @param WampConnection $conn * @return boolean */ public function has(ConnectionInterface $conn) { return $this->subscribers->contains($conn); } /** * @param WampConnection $conn * @return Topic */ public function add(ConnectionInterface $conn) { $this->subscribers->attach($conn); return $this; } /** * @param WampConnection $conn * @return Topic */ public function remove(ConnectionInterface $conn) { if ($this->subscribers->contains($conn)) { $this->subscribers->detach($conn); } return $this; } /** * {@inheritdoc} */ #[\ReturnTypeWillChange] public function getIterator() { return $this->subscribers; } /** * {@inheritdoc} */ #[\ReturnTypeWillChange] public function count() { return $this->subscribers->count(); } } ratchet/src/Ratchet/Session/Serialize/PhpHandler.php 0000664 00000002700 15177100702 0016470 0 ustar 00 <?php namespace Ratchet\Session\Serialize; class PhpHandler implements HandlerInterface { /** * Simply reverse behaviour of unserialize method. * {@inheritdoc} */ function serialize(array $data) { $preSerialized = array(); $serialized = ''; if (count($data)) { foreach ($data as $bucket => $bucketData) { $preSerialized[] = $bucket . '|' . serialize($bucketData); } $serialized = implode('', $preSerialized); } return $serialized; } /** * {@inheritdoc} * @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net * @throws \UnexpectedValueException If there is a problem parsing the data */ public function unserialize($raw) { $returnData = array(); $offset = 0; while ($offset < strlen($raw)) { if (!strstr(substr($raw, $offset), "|")) { throw new \UnexpectedValueException("invalid data, remaining: " . substr($raw, $offset)); } $pos = strpos($raw, "|", $offset); $num = $pos - $offset; $varname = substr($raw, $offset, $num); $offset += $num + 1; $data = unserialize(substr($raw, $offset)); $returnData[$varname] = $data; $offset += strlen(serialize($data)); } return $returnData; } } ratchet/src/Ratchet/Session/Serialize/PhpBinaryHandler.php 0000664 00000001625 15177100702 0017642 0 ustar 00 <?php namespace Ratchet\Session\Serialize; class PhpBinaryHandler implements HandlerInterface { /** * {@inheritdoc} */ function serialize(array $data) { throw new \RuntimeException("Serialize PhpHandler:serialize code not written yet, write me!"); } /** * {@inheritdoc} * @link http://ca2.php.net/manual/en/function.session-decode.php#108037 Code from this comment on php.net */ public function unserialize($raw) { $returnData = array(); $offset = 0; while ($offset < strlen($raw)) { $num = ord($raw[$offset]); $offset += 1; $varname = substr($raw, $offset, $num); $offset += $num; $data = unserialize(substr($raw, $offset)); $returnData[$varname] = $data; $offset += strlen(serialize($data)); } return $returnData; } } ratchet/src/Ratchet/Session/Serialize/HandlerInterface.php 0000664 00000000405 15177100702 0017641 0 ustar 00 <?php namespace Ratchet\Session\Serialize; interface HandlerInterface { /** * @param array * @return string */ function serialize(array $data); /** * @param string * @return array */ function unserialize($raw); } ratchet/src/Ratchet/Session/Storage/Proxy/VirtualProxy.php 0000664 00000002070 15177100702 0017731 0 ustar 00 <?php namespace Ratchet\Session\Storage\Proxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; class VirtualProxy extends SessionHandlerProxy { /** * @var string */ protected $_sessionId; /** * @var string */ protected $_sessionName; /** * {@inheritdoc} */ public function __construct(\SessionHandlerInterface $handler) { parent::__construct($handler); $this->saveHandlerName = 'user'; $this->_sessionName = ini_get('session.name'); } /** * {@inheritdoc} */ public function getId() { return $this->_sessionId; } /** * {@inheritdoc} */ public function setId($id) { $this->_sessionId = $id; } /** * {@inheritdoc} */ public function getName() { return $this->_sessionName; } /** * DO NOT CALL THIS METHOD * @internal */ public function setName($name) { throw new \RuntimeException("Can not change session name in VirtualProxy"); } } ratchet/src/Ratchet/Session/Storage/VirtualSessionStorage.php 0000664 00000005645 15177100702 0020452 0 ustar 00 <?php namespace Ratchet\Session\Storage; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Ratchet\Session\Storage\Proxy\VirtualProxy; use Ratchet\Session\Serialize\HandlerInterface; class VirtualSessionStorage extends NativeSessionStorage { /** * @var \Ratchet\Session\Serialize\HandlerInterface */ protected $_serializer; /** * @param \SessionHandlerInterface $handler * @param string $sessionId The ID of the session to retrieve * @param \Ratchet\Session\Serialize\HandlerInterface $serializer */ public function __construct(\SessionHandlerInterface $handler, $sessionId, HandlerInterface $serializer) { $this->setSaveHandler($handler); $this->saveHandler->setId($sessionId); $this->_serializer = $serializer; $this->setMetadataBag(null); } /** * {@inheritdoc} */ public function start() { if ($this->started && !$this->closed) { return true; } // You have to call Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::open() to use // pdo_sqlite (and possible pdo_*) as session storage, if you are using a DSN string instead of a \PDO object // in the constructor. The method arguments are filled with the values, which are also used by the symfony // framework in this case. This must not be the best choice, but it works. $this->saveHandler->open(session_save_path(), session_name()); $rawData = $this->saveHandler->read($this->saveHandler->getId()); $sessionData = $this->_serializer->unserialize($rawData); $this->loadSession($sessionData); if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) { $this->saveHandler->setActive(false); } return true; } /** * {@inheritdoc} */ public function regenerate($destroy = false, $lifetime = null) { // .. ? } /** * {@inheritdoc} */ public function save() { // get the data from the bags? // serialize the data // save the data using the saveHandler // $this->saveHandler->write($this->saveHandler->getId(), if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) { $this->saveHandler->setActive(false); } $this->closed = true; } /** * {@inheritdoc} */ public function setSaveHandler($saveHandler = null) { if (!($saveHandler instanceof \SessionHandlerInterface)) { throw new \InvalidArgumentException('Handler must be instance of SessionHandlerInterface'); } if (!($saveHandler instanceof VirtualProxy)) { $saveHandler = new VirtualProxy($saveHandler); } $this->saveHandler = $saveHandler; } } ratchet/src/Ratchet/Session/SessionProvider.php 0000664 00000020063 15177100702 0015654 0 ustar 00 <?php namespace Ratchet\Session; use Ratchet\ConnectionInterface; use Ratchet\Http\HttpServerInterface; use Psr\Http\Message\RequestInterface; use Ratchet\Session\Storage\VirtualSessionStorage; use Ratchet\Session\Serialize\HandlerInterface; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; /** * This component will allow access to session data from your website for each user connected * Symfony HttpFoundation is required for this component to work * Your website must also use Symfony HttpFoundation Sessions to read your sites session data * If your are not using at least PHP 5.4 you must include a SessionHandlerInterface stub (is included in Symfony HttpFoundation, loaded w/ composer) */ class SessionProvider implements HttpServerInterface { /** * @var \Ratchet\MessageComponentInterface */ protected $_app; /** * Selected handler storage assigned by the developer * @var \SessionHandlerInterface */ protected $_handler; /** * Null storage handler if no previous session was found * @var \SessionHandlerInterface */ protected $_null; /** * @var \Ratchet\Session\Serialize\HandlerInterface */ protected $_serializer; /** * @param \Ratchet\Http\HttpServerInterface $app * @param \SessionHandlerInterface $handler * @param array $options * @param \Ratchet\Session\Serialize\HandlerInterface $serializer * @throws \RuntimeException */ public function __construct(HttpServerInterface $app, \SessionHandlerInterface $handler, array $options = array(), HandlerInterface $serializer = null) { $this->_app = $app; $this->_handler = $handler; $this->_null = new NullSessionHandler; ini_set('session.auto_start', 0); ini_set('session.cache_limiter', ''); ini_set('session.use_cookies', 0); $this->setOptions($options); if (null === $serializer) { $serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh? if (!class_exists($serialClass)) { throw new \RuntimeException('Unable to parse session serialize handler'); } $serializer = new $serialClass; } $this->_serializer = $serializer; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { $sessionName = ini_get('session.name'); $id = array_reduce($request->getHeader('Cookie'), function($accumulator, $cookie) use ($sessionName) { if ($accumulator) { return $accumulator; } $crumbs = $this->parseCookie($cookie); return isset($crumbs['cookies'][$sessionName]) ? $crumbs['cookies'][$sessionName] : false; }, false); if (null === $request || false === $id) { $saveHandler = $this->_null; $id = ''; } else { $saveHandler = $this->_handler; } $conn->Session = new Session(new VirtualSessionStorage($saveHandler, $id, $this->_serializer)); if (ini_get('session.auto_start')) { $conn->Session->start(); } return $this->_app->onOpen($conn, $request); } /** * {@inheritdoc} */ function onMessage(ConnectionInterface $from, $msg) { return $this->_app->onMessage($from, $msg); } /** * {@inheritdoc} */ function onClose(ConnectionInterface $conn) { // "close" session for Connection return $this->_app->onClose($conn); } /** * {@inheritdoc} */ function onError(ConnectionInterface $conn, \Exception $e) { return $this->_app->onError($conn, $e); } /** * Set all the php session. ini options * © Symfony * @param array $options * @return array */ protected function setOptions(array $options) { $all = array( 'auto_start', 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', 'hash_function', 'name', 'referer_check', 'serialize_handler', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags' ); foreach ($all as $key) { if (!array_key_exists($key, $options)) { $options[$key] = ini_get("session.{$key}"); } else { ini_set("session.{$key}", $options[$key]); } } return $options; } /** * @param string $langDef Input to convert * @return string */ protected function toClassCase($langDef) { return str_replace(' ', '', ucwords(str_replace('_', ' ', $langDef))); } /** * Taken from Guzzle3 */ private static $cookieParts = array( 'domain' => 'Domain', 'path' => 'Path', 'max_age' => 'Max-Age', 'expires' => 'Expires', 'version' => 'Version', 'secure' => 'Secure', 'port' => 'Port', 'discard' => 'Discard', 'comment' => 'Comment', 'comment_url' => 'Comment-Url', 'http_only' => 'HttpOnly' ); /** * Taken from Guzzle3 */ private function parseCookie($cookie, $host = null, $path = null, $decode = false) { // Explode the cookie string using a series of semicolons $pieces = array_filter(array_map('trim', explode(';', $cookie))); // The name of the cookie (first kvp) must include an equal sign. if (empty($pieces) || !strpos($pieces[0], '=')) { return false; } // Create the default return array $data = array_merge(array_fill_keys(array_keys(self::$cookieParts), null), array( 'cookies' => array(), 'data' => array(), 'path' => $path ?: '/', 'http_only' => false, 'discard' => false, 'domain' => $host )); $foundNonCookies = 0; // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { $cookieParts = explode('=', $part, 2); $key = trim($cookieParts[0]); if (count($cookieParts) == 1) { // Can be a single value (e.g. secure, httpOnly) $value = true; } else { // Be sure to strip wrapping quotes $value = trim($cookieParts[1], " \n\r\t\0\x0B\""); if ($decode) { $value = urldecode($value); } } // Only check for non-cookies when cookies have been found if (!empty($data['cookies'])) { foreach (self::$cookieParts as $mapValue => $search) { if (!strcasecmp($search, $key)) { $data[$mapValue] = $mapValue == 'port' ? array_map('trim', explode(',', $value)) : $value; $foundNonCookies++; continue 2; } } } // If cookies have not yet been retrieved, or this value was not found in the pieces array, treat it as a // cookie. IF non-cookies have been parsed, then this isn't a cookie, it's cookie data. Cookies then data. $data[$foundNonCookies ? 'data' : 'cookies'][$key] = $value; } // Calculate the expires date if (!$data['expires'] && $data['max_age']) { $data['expires'] = time() + (int) $data['max_age']; } return $data; } } ratchet/src/Ratchet/Server/IpBlackList.php 0000664 00000005312 15177100702 0014502 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; class IpBlackList implements MessageComponentInterface { /** * @var array */ protected $_blacklist = array(); /** * @var \Ratchet\MessageComponentInterface */ protected $_decorating; /** * @param \Ratchet\MessageComponentInterface $component */ public function __construct(MessageComponentInterface $component) { $this->_decorating = $component; } /** * Add an address to the blacklist that will not be allowed to connect to your application * @param string $ip IP address to block from connecting to your application * @return IpBlackList */ public function blockAddress($ip) { $this->_blacklist[$ip] = true; return $this; } /** * Unblock an address so they can access your application again * @param string $ip IP address to unblock from connecting to your application * @return IpBlackList */ public function unblockAddress($ip) { if (isset($this->_blacklist[$this->filterAddress($ip)])) { unset($this->_blacklist[$this->filterAddress($ip)]); } return $this; } /** * @param string $address * @return bool */ public function isBlocked($address) { return (isset($this->_blacklist[$this->filterAddress($address)])); } /** * Get an array of all the addresses blocked * @return array */ public function getBlockedAddresses() { return array_keys($this->_blacklist); } /** * @param string $address * @return string */ public function filterAddress($address) { if (strstr($address, ':') && substr_count($address, '.') == 3) { list($address, $port) = explode(':', $address); } return $address; } /** * {@inheritdoc} */ function onOpen(ConnectionInterface $conn) { if ($this->isBlocked($conn->remoteAddress)) { return $conn->close(); } return $this->_decorating->onOpen($conn); } /** * {@inheritdoc} */ function onMessage(ConnectionInterface $from, $msg) { return $this->_decorating->onMessage($from, $msg); } /** * {@inheritdoc} */ function onClose(ConnectionInterface $conn) { if (!$this->isBlocked($conn->remoteAddress)) { $this->_decorating->onClose($conn); } } /** * {@inheritdoc} */ function onError(ConnectionInterface $conn, \Exception $e) { if (!$this->isBlocked($conn->remoteAddress)) { $this->_decorating->onError($conn, $e); } } } ratchet/src/Ratchet/Server/FlashPolicy.php 0000664 00000014220 15177100702 0014554 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; /** * An app to go on a server stack to pass a policy file to a Flash socket * Useful if you're using Flash as a WebSocket polyfill on IE * Be sure to run your server instance on port 843 * By default this lets accepts everything, make sure you tighten the rules up for production * @final * @link http://www.adobe.com/devnet/articles/crossdomain_policy_file_spec.html * @link http://learn.adobe.com/wiki/download/attachments/64389123/CrossDomain_PolicyFile_Specification.pdf?version=1 * @link view-source:http://www.adobe.com/xml/schemas/PolicyFileSocket.xsd */ class FlashPolicy implements MessageComponentInterface { /** * Contains the root policy node * @var string */ protected $_policy = '<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy></cross-domain-policy>'; /** * Stores an array of allowed domains and their ports * @var array */ protected $_access = array(); /** * @var string */ protected $_siteControl = ''; /** * @var string */ protected $_cache = ''; /** * @var string */ protected $_cacheValid = false; /** * Add a domain to an allowed access list. * * @param string $domain Specifies a requesting domain to be granted access. Both named domains and IP * addresses are acceptable values. Subdomains are considered different domains. A wildcard (*) can * be used to match all domains when used alone, or multiple domains (subdomains) when used as a * prefix for an explicit, second-level domain name separated with a dot (.) * @param string $ports A comma-separated list of ports or range of ports that a socket connection * is allowed to connect to. A range of ports is specified through a dash (-) between two port numbers. * Ranges can be used with individual ports when separated with a comma. A single wildcard (*) can * be used to allow all ports. * @param bool $secure * @throws \UnexpectedValueException * @return FlashPolicy */ public function addAllowedAccess($domain, $ports = '*', $secure = false) { if (!$this->validateDomain($domain)) { throw new \UnexpectedValueException('Invalid domain'); } if (!$this->validatePorts($ports)) { throw new \UnexpectedValueException('Invalid Port'); } $this->_access[] = array($domain, $ports, (boolean)$secure); $this->_cacheValid = false; return $this; } /** * Removes all domains from the allowed access list. * * @return \Ratchet\Server\FlashPolicy */ public function clearAllowedAccess() { $this->_access = array(); $this->_cacheValid = false; return $this; } /** * site-control defines the meta-policy for the current domain. A meta-policy specifies acceptable * domain policy files other than the master policy file located in the target domain's root and named * crossdomain.xml. * * @param string $permittedCrossDomainPolicies * @throws \UnexpectedValueException * @return FlashPolicy */ public function setSiteControl($permittedCrossDomainPolicies = 'all') { if (!$this->validateSiteControl($permittedCrossDomainPolicies)) { throw new \UnexpectedValueException('Invalid site control set'); } $this->_siteControl = $permittedCrossDomainPolicies; $this->_cacheValid = false; return $this; } /** * {@inheritdoc} */ public function onOpen(ConnectionInterface $conn) { } /** * {@inheritdoc} */ public function onMessage(ConnectionInterface $from, $msg) { if (!$this->_cacheValid) { $this->_cache = $this->renderPolicy()->asXML(); $this->_cacheValid = true; } $from->send($this->_cache . "\0"); $from->close(); } /** * {@inheritdoc} */ public function onClose(ConnectionInterface $conn) { } /** * {@inheritdoc} */ public function onError(ConnectionInterface $conn, \Exception $e) { $conn->close(); } /** * Builds the crossdomain file based on the template policy * * @throws \UnexpectedValueException * @return \SimpleXMLElement */ public function renderPolicy() { $policy = new \SimpleXMLElement($this->_policy); $siteControl = $policy->addChild('site-control'); if ($this->_siteControl == '') { $this->setSiteControl(); } $siteControl->addAttribute('permitted-cross-domain-policies', $this->_siteControl); if (empty($this->_access)) { throw new \UnexpectedValueException('You must add a domain through addAllowedAccess()'); } foreach ($this->_access as $access) { $tmp = $policy->addChild('allow-access-from'); $tmp->addAttribute('domain', $access[0]); $tmp->addAttribute('to-ports', $access[1]); $tmp->addAttribute('secure', ($access[2] === true) ? 'true' : 'false'); } return $policy; } /** * Make sure the proper site control was passed * * @param string $permittedCrossDomainPolicies * @return bool */ public function validateSiteControl($permittedCrossDomainPolicies) { //'by-content-type' and 'by-ftp-filename' are not available for sockets return (bool)in_array($permittedCrossDomainPolicies, array('none', 'master-only', 'all')); } /** * Validate for proper domains (wildcards allowed) * * @param string $domain * @return bool */ public function validateDomain($domain) { return (bool)preg_match("/^((http(s)?:\/\/)?([a-z0-9-_]+\.|\*\.)*([a-z0-9-_\.]+)|\*)$/i", $domain); } /** * Make sure valid ports were passed * * @param string $port * @return bool */ public function validatePorts($port) { return (bool)preg_match('/^(\*|(\d+[,-]?)*\d+)$/', $port); } } ratchet/src/Ratchet/Server/IoConnection.php 0000664 00000001243 15177100702 0014727 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\ConnectionInterface; use React\Socket\ConnectionInterface as ReactConn; /** * {@inheritdoc} */ class IoConnection implements ConnectionInterface { /** * @var \React\Socket\ConnectionInterface */ protected $conn; /** * @param \React\Socket\ConnectionInterface $conn */ public function __construct(ReactConn $conn) { $this->conn = $conn; } /** * {@inheritdoc} */ public function send($data) { $this->conn->write($data); return $this; } /** * {@inheritdoc} */ public function close() { $this->conn->end(); } } ratchet/src/Ratchet/Server/EchoServer.php 0000664 00000001120 15177100702 0014377 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; /** * A simple Ratchet application that will reply to all messages with the message it received */ class EchoServer implements MessageComponentInterface { public function onOpen(ConnectionInterface $conn) { } public function onMessage(ConnectionInterface $from, $msg) { $from->send($msg); } public function onClose(ConnectionInterface $conn) { } public function onError(ConnectionInterface $conn, \Exception $e) { $conn->close(); } } ratchet/src/Ratchet/Server/IoServer.php 0000664 00000010612 15177100702 0014076 0 ustar 00 <?php namespace Ratchet\Server; use Ratchet\MessageComponentInterface; use React\EventLoop\LoopInterface; use React\Socket\ServerInterface; use React\EventLoop\Factory as LoopFactory; use React\Socket\Server as Reactor; use React\Socket\SecureServer as SecureReactor; /** * Creates an open-ended socket to listen on a port for incoming connections. * Events are delegated through this to attached applications */ class IoServer { /** * @var \React\EventLoop\LoopInterface */ public $loop; /** * @var \Ratchet\MessageComponentInterface */ public $app; /** * The socket server the Ratchet Application is run off of * @var \React\Socket\ServerInterface */ public $socket; /** * @param \Ratchet\MessageComponentInterface $app The Ratchet application stack to host * @param \React\Socket\ServerInterface $socket The React socket server to run the Ratchet application off of * @param \React\EventLoop\LoopInterface|null $loop The React looper to run the Ratchet application off of */ public function __construct(MessageComponentInterface $app, ServerInterface $socket, LoopInterface $loop = null) { if (false === strpos(PHP_VERSION, "hiphop")) { gc_enable(); } set_time_limit(0); ob_implicit_flush(); $this->loop = $loop; $this->app = $app; $this->socket = $socket; $socket->on('connection', array($this, 'handleConnect')); } /** * @param \Ratchet\MessageComponentInterface $component The application that I/O will call when events are received * @param int $port The port to server sockets on * @param string $address The address to receive sockets on (0.0.0.0 means receive connections from any) * @return IoServer */ public static function factory(MessageComponentInterface $component, $port = 80, $address = '0.0.0.0') { $loop = LoopFactory::create(); $socket = new Reactor($address . ':' . $port, $loop); return new static($component, $socket, $loop); } /** * Run the application by entering the event loop * @throws \RuntimeException If a loop was not previously specified */ public function run() { if (null === $this->loop) { throw new \RuntimeException("A React Loop was not provided during instantiation"); } // @codeCoverageIgnoreStart $this->loop->run(); // @codeCoverageIgnoreEnd } /** * Triggered when a new connection is received from React * @param \React\Socket\ConnectionInterface $conn */ public function handleConnect($conn) { $conn->decor = new IoConnection($conn); $conn->decor->resourceId = (int)$conn->stream; $uri = $conn->getRemoteAddress(); $conn->decor->remoteAddress = trim( parse_url((strpos($uri, '://') === false ? 'tcp://' : '') . $uri, PHP_URL_HOST), '[]' ); $this->app->onOpen($conn->decor); $conn->on('data', function ($data) use ($conn) { $this->handleData($data, $conn); }); $conn->on('close', function () use ($conn) { $this->handleEnd($conn); }); $conn->on('error', function (\Exception $e) use ($conn) { $this->handleError($e, $conn); }); } /** * Data has been received from React * @param string $data * @param \React\Socket\ConnectionInterface $conn */ public function handleData($data, $conn) { try { $this->app->onMessage($conn->decor, $data); } catch (\Exception $e) { $this->handleError($e, $conn); } } /** * A connection has been closed by React * @param \React\Socket\ConnectionInterface $conn */ public function handleEnd($conn) { try { $this->app->onClose($conn->decor); } catch (\Exception $e) { $this->handleError($e, $conn); } unset($conn->decor); } /** * An error has occurred, let the listening application know * @param \Exception $e * @param \React\Socket\ConnectionInterface $conn */ public function handleError(\Exception $e, $conn) { $this->app->onError($conn->decor, $e); } } ratchet/src/Ratchet/error_log 0000644 00000001241 15177100702 0012272 0 ustar 00 [06-May-2026 00:41:22 UTC] PHP Fatal error: Uncaught Error: Interface "Ratchet\ComponentInterface" not found in /home/toptrendingappst/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php:4 Stack trace: #0 {main} thrown in /home/toptrendingappst/vendor/cboden/ratchet/src/Ratchet/MessageComponentInterface.php on line 4 [06-May-2026 00:41:31 UTC] PHP Fatal error: Uncaught Error: Interface "Ratchet\ConnectionInterface" not found in /home/toptrendingappst/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php:9 Stack trace: #0 {main} thrown in /home/toptrendingappst/vendor/cboden/ratchet/src/Ratchet/AbstractConnectionDecorator.php on line 9 ratchet/src/Ratchet/ConnectionInterface.php 0000664 00000001004 15177100702 0015005 0 ustar 00 <?php namespace Ratchet; /** * The version of Ratchet being used * @var string */ const VERSION = 'Ratchet/0.4.4'; /** * A proxy object representing a connection to the application * This acts as a container to store data (in memory) about the connection */ interface ConnectionInterface { /** * Send data to the connection * @param string $data * @return \Ratchet\ConnectionInterface */ function send($data); /** * Close the connection */ function close(); } ratchet/src/Ratchet/AbstractConnectionDecorator.php 0000664 00000001723 15177100702 0016523 0 ustar 00 <?php namespace Ratchet; /** * Wraps ConnectionInterface objects via the decorator pattern but allows * parameters to bubble through with magic methods * @todo It sure would be nice if I could make most of this a trait... */ abstract class AbstractConnectionDecorator implements ConnectionInterface { /** * @var ConnectionInterface */ protected $wrappedConn; public function __construct(ConnectionInterface $conn) { $this->wrappedConn = $conn; } /** * @return ConnectionInterface */ protected function getConnection() { return $this->wrappedConn; } public function __set($name, $value) { $this->wrappedConn->$name = $value; } public function __get($name) { return $this->wrappedConn->$name; } public function __isset($name) { return isset($this->wrappedConn->$name); } public function __unset($name) { unset($this->wrappedConn->$name); } } ratchet/src/Ratchet/ComponentInterface.php 0000664 00000002326 15177100702 0014660 0 ustar 00 <?php namespace Ratchet; /** * This is the interface to build a Ratchet application with. * It implements the decorator pattern to build an application stack */ interface ComponentInterface { /** * When a new connection is opened it will be passed to this method * @param ConnectionInterface $conn The socket/connection that just connected to your application * @throws \Exception */ function onOpen(ConnectionInterface $conn); /** * This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed. * @param ConnectionInterface $conn The socket/connection that is closing/closed * @throws \Exception */ function onClose(ConnectionInterface $conn); /** * If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown, * the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method * @param ConnectionInterface $conn * @param \Exception $e * @throws \Exception */ function onError(ConnectionInterface $conn, \Exception $e); } ratchet/src/Ratchet/App.php 0000664 00000012621 15177100702 0011614 0 ustar 00 <?php namespace Ratchet; use React\EventLoop\LoopInterface; use React\EventLoop\Factory as LoopFactory; use React\Socket\Server as Reactor; use React\Socket\SecureServer as SecureReactor; use Ratchet\Http\HttpServerInterface; use Ratchet\Http\OriginCheck; use Ratchet\Wamp\WampServerInterface; use Ratchet\Server\IoServer; use Ratchet\Server\FlashPolicy; use Ratchet\Http\HttpServer; use Ratchet\Http\Router; use Ratchet\WebSocket\MessageComponentInterface as WsMessageComponentInterface; use Ratchet\WebSocket\WsServer; use Ratchet\Wamp\WampServer; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Matcher\UrlMatcher; /** * An opinionated facade class to quickly and easily create a WebSocket server. * A few configuration assumptions are made and some best-practice security conventions are applied by default. */ class App { /** * @var \Symfony\Component\Routing\RouteCollection */ public $routes; /** * @var \Ratchet\Server\IoServer */ public $flashServer; /** * @var \Ratchet\Server\IoServer */ protected $_server; /** * The Host passed in construct used for same origin policy * @var string */ protected $httpHost; /*** * The port the socket is listening * @var int */ protected $port; /** * @var int */ protected $_routeCounter = 0; /** * @param string $httpHost HTTP hostname clients intend to connect to. MUST match JS `new WebSocket('ws://$httpHost');` * @param int $port Port to listen on. If 80, assuming production, Flash on 843 otherwise expecting Flash to be proxied through 8843 * @param string $address IP address to bind to. Default is localhost/proxy only. '0.0.0.0' for any machine. * @param LoopInterface $loop Specific React\EventLoop to bind the application to. null will create one for you. * @param array $context */ public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null, $context = array()) { if (extension_loaded('xdebug') && getenv('RATCHET_DISABLE_XDEBUG_WARN') === false) { trigger_error('XDebug extension detected. Remember to disable this if performance testing or going live!', E_USER_WARNING); } if (null === $loop) { $loop = LoopFactory::create(); } $this->httpHost = $httpHost; $this->port = $port; $socket = new Reactor($address . ':' . $port, $loop, $context); $this->routes = new RouteCollection; $this->_server = new IoServer(new HttpServer(new Router(new UrlMatcher($this->routes, new RequestContext))), $socket, $loop); $policy = new FlashPolicy; $policy->addAllowedAccess($httpHost, 80); $policy->addAllowedAccess($httpHost, $port); if (80 == $port) { $flashUri = '0.0.0.0:843'; } else { $flashUri = 8843; } $flashSock = new Reactor($flashUri, $loop); $this->flashServer = new IoServer($policy, $flashSock); } /** * Add an endpoint/application to the server * @param string $path The URI the client will connect to * @param ComponentInterface $controller Your application to server for the route. If not specified, assumed to be for a WebSocket * @param array $allowedOrigins An array of hosts allowed to connect (same host by default), ['*'] for any * @param string $httpHost Override the $httpHost variable provided in the __construct * @return ComponentInterface|WsServer */ public function route($path, ComponentInterface $controller, array $allowedOrigins = array(), $httpHost = null) { if ($controller instanceof HttpServerInterface || $controller instanceof WsServer) { $decorated = $controller; } elseif ($controller instanceof WampServerInterface) { $decorated = new WsServer(new WampServer($controller)); $decorated->enableKeepAlive($this->_server->loop); } elseif ($controller instanceof MessageComponentInterface || $controller instanceof WsMessageComponentInterface) { $decorated = new WsServer($controller); $decorated->enableKeepAlive($this->_server->loop); } else { $decorated = $controller; } if ($httpHost === null) { $httpHost = $this->httpHost; } $allowedOrigins = array_values($allowedOrigins); if (0 === count($allowedOrigins)) { $allowedOrigins[] = $httpHost; } if ('*' !== $allowedOrigins[0]) { $decorated = new OriginCheck($decorated, $allowedOrigins); } //allow origins in flash policy server if(empty($this->flashServer) === false) { foreach($allowedOrigins as $allowedOrgin) { $this->flashServer->app->addAllowedAccess($allowedOrgin, $this->port); } } $this->routes->add('rr-' . ++$this->_routeCounter, new Route($path, array('_controller' => $decorated), array('Origin' => $this->httpHost), array(), $httpHost, array(), array('GET'))); return $decorated; } /** * Run the server by entering the event loop */ public function run() { $this->_server->run(); } } ratchet/src/Ratchet/MessageInterface.php 0000664 00000000622 15177100702 0014277 0 ustar 00 <?php namespace Ratchet; interface MessageInterface { /** * Triggered when a client sends data through the socket * @param \Ratchet\ConnectionInterface $from The socket/connection that sent the message to your application * @param string $msg The message received * @throws \Exception */ function onMessage(ConnectionInterface $from, $msg); } ratchet/src/Ratchet/MessageComponentInterface.php 0000664 00000000157 15177100702 0016165 0 ustar 00 <?php namespace Ratchet; interface MessageComponentInterface extends ComponentInterface, MessageInterface { } ratchet/CHANGELOG.md 0000664 00000013135 15177100702 0010014 0 ustar 00 CHANGELOG ========= ### Legend * "BC": Backwards compatibility break (from public component APIs) * "BF": Bug fix --- * 0.4.4 (2021-12-11) * Correct and update dependencies for forward compatibility * Added context for React Socket server to App * Use non-deprecated Guzzle API calls * 0.4.3 (2020-06-04) * BF: Fixed interface acceptable regression in `App` * Update RFC6455 library with latest fixes * 0.4.2 (2020-01-27) * Support Symfony 5 * BF: Use phpunit from vendor directory * Allow disabling of xdebug warning by defining `RATCHET_DISABLE_XDEBUG_WARN` * Stop using `LoopInterface::tick()` for testing * 0.4.1 (2017-12-11) * Only enableKeepAlive in App if no WsServer passed allowing user to set their own timeout duration * Support Symfony 4 * BF: Plug NOOP controller in connection from router in case of misbehaving client * BF: Raise error from invalid WAMP payload * 0.4 (2017-09-14) * BC: $conn->WebSocket->request replaced with $conn->httpRequest which is a PSR-7 object * Binary messages now supported via Ratchet\WebSocket\MessageComponentInterface * Added heartbeat support via ping/pong in WsServer * BC: No longer support old (and insecure) Hixie76 and Hybi protocols * BC: No longer support disabling UTF-8 checks * BC: The Session component implements HttpServerInterface instead of WsServerInterface * BC: PHP 5.3 no longer supported * BC: Update to newer version of react/socket dependency * BC: WAMP topics reduced to 0 subscriptions are deleted, new subs to same name will result in new Topic instance * Significant performance enhancements * 0.3.6 (2017-01-06) * BF: Keep host and scheme in HTTP request object attatched to connection * BF: Return correct HTTP response (405) when non-GET request made * 0.3.5 (2016-05-25) * BF: Unmask responding close frame * Added write handler for PHP session serializer * 0.3.4 (2015-12-23) * BF: Edge case where version check wasn't run on message coalesce * BF: Session didn't start when using pdo_sqlite * BF: WAMP currie prefix check when using '#' * Compatibility with Symfony 3 * 0.3.3 (2015-05-26) * BF: Framing bug on large messages upon TCP fragmentation * BF: Symfony Router query parameter defaults applied to Request * BF: WAMP CURIE on all URIs * OriginCheck rules applied to FlashPolicy * Switched from PSR-0 to PSR-4 * 0.3.2 (2014-06-08) * BF: No messages after closing handshake (fixed rare race condition causing 100% CPU) * BF: Fixed accidental BC break from v0.3.1 * Added autoDelete parameter to Topic to destroy when empty of connections * Exposed React Socket on IoServer (allowing FlashPolicy shutdown in App) * Normalized Exceptions in WAMP * 0.3.1 (2014-05-26) * Added query parameter support to Router, set in HTTP request (ws://server?hello=world) * HHVM compatibility * BF: React/0.4 support; CPU starvation bug fixes * BF: Allow App::route to ignore Host header * Added expected filters to WAMP Topic broadcast method * Resource cleanup in WAMP TopicManager * 0.3.0 (2013-10-14) * Added the `App` class to help making Ratchet so easy to use it's silly * BC: Require hostname to do HTTP Host header match and do Origin HTTP header check, verify same name by default, helping prevent CSRF attacks * Added Symfony/2.2 based HTTP Router component to allowing for a single Ratchet server to handle multiple apps -> Ratchet\Http\Router * BC: Decoupled HTTP from WebSocket component -> Ratchet\Http\HttpServer * BF: Single sub-protocol selection to conform with RFC6455 * BF: Sanity checks on WAMP protocol to prevent errors * 0.2.8 (2013-09-19) * React 0.3 support * 0.2.7 (2013-06-09) * BF: Sub-protocol negotation with Guzzle 3.6 * 0.2.6 (2013-06-01) * Guzzle 3.6 support * 0.2.5 (2013-04-01) * Fixed Hixie-76 handshake bug * 0.2.4 (2013-03-09) * Support for Symfony 2.2 and Guzzle 2.3 * Minor bug fixes when handling errors * 0.2.3 (2012-11-21) * Bumped dep: Guzzle to v3, React to v0.2.4 * More tests * 0.2.2 (2012-10-20) * Bumped deps to use React v0.2 * 0.2.1 (2012-10-13) * BF: No more UTF-8 warnings in browsers (no longer sending empty sub-protocol string) * Documentation corrections * Using new composer structure * 0.2 (2012-09-07) * Ratchet passes every non-binary-frame test from the Autobahn Testsuite * Major performance improvements * BC: Renamed "WampServer" to "ServerProtocol" * BC: New "WampServer" component passes Topic container objects of subscribed Connections * Option to turn off UTF-8 checks in order to increase performance * Switched dependency guzzle/guzzle to guzzle/http (no API changes) * mbstring no longer required * 0.1.5 (2012-07-12) * BF: Error where service wouldn't run on PHP <= 5.3.8 * Dependency library updates * 0.1.4 (2012-06-17) * Fixed dozens of failing AB tests * BF: Proper socket buffer handling * 0.1.3 (2012-06-15) * Major refactor inside WebSocket protocol handling, more loosley coupled * BF: Proper error handling on failed WebSocket connections * BF: Handle TCP message concatenation * Inclusion of the AutobahnTestSuite checking WebSocket protocol compliance * mb_string now a requirement * 0.1.2 (2012-05-19) * BC/BF: Updated WAMP API to coincide with the official spec * Tweaks to improve running as a long lived process * 0.1.1 (2012-05-14) * Separated interfaces allowing WebSockets to support multiple sub protocols * BF: remoteAddress variable on connections returns proper value * 0.1 (2012-05-11) * First release with components: IoServer, WsServer, SessionProvider, WampServer, FlashPolicy, IpBlackList * I/O now handled by React, making Ratchet fully asynchronous ratchet/phpunit.xml.dist 0000664 00000001277 15177100702 0011362 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <phpunit forceCoversAnnotation="true" mapTestClassNameToCoveredClassName="true" bootstrap="tests/bootstrap.php" colors="true" backupGlobals="false" backupStaticAttributes="false" syntaxCheck="false" stopOnError="false" > <testsuites> <testsuite name="unit"> <directory>./tests/unit/</directory> </testsuite> </testsuites> <testsuites> <testsuite name="integration"> <directory>./tests/integration/</directory> </testsuite> </testsuites> <filter> <whitelist> <directory>./src/</directory> </whitelist> </filter> </phpunit>