1<?php
2error_reporting(E_ALL);
3define('PHPT_ACL_READ',  1 << 1);
4define('PHPT_ACL_WRITE', 1 << 2);
5define('PHPT_ACL_EXEC',  1 << 3);
6define('PHPT_ACL_NONE',  1 << 4);
7define('PHPT_ACL_FULL',  1 << 5);
8
9define('PHPT_ACL_GRANT',  1);
10define('PHPT_ACL_DENY',  2);
11
12function skipif() {
13	if(substr(PHP_OS, 0, 3) != 'WIN' ) {
14		die('skip windows only test');
15	}
16	if(stripos(php_uname(), 'XP') !== FALSE) {
17		die('skip windows 2003 or newer only test');
18	}
19}
20
21function get_username(){
22	$user = getenv('USERNAME');
23
24	if (!$user) {
25		$user = get_current_user();
26	}
27
28	if (!$user) {
29		$user =  exec('echo %USERNAME%');
30	}
31
32	return $user;
33}
34
35function get_domainname()
36{
37	$domain = getenv('USERDOMAIN');
38
39	return $domain;
40}
41
42function get_icacls()
43{
44	$sysroot = exec('echo %SYSTEMROOT%');
45
46	return "$sysroot\\System32\\icacls.exe";
47}
48
49function fix_acls() {
50	$user = get_username();
51	/* Current user needs to be owner of the test files. As well
52	   all the other users having acls on the files must loose them.
53	   The following fixes this just partially, as dynamically reading
54	   all the users having acls on a file could be sophisticated. */
55	exec(get_icacls() . ' . /setowner $user /T /L /Q 2> nul');
56	exec(get_icacls() . ' . /remove:g Administrators /T /L /Q 2> nul');
57}
58
59function icacls_set($path, $mode, $perm) {
60	$icacls = get_icacls();
61	$user = get_username();
62	$path_escaped =  '"' . $path . '"';
63	$perm_entry = array();
64
65	if ($perm & PHPT_ACL_READ) $perm_entry[]  = 'R';
66	if ($perm & PHPT_ACL_WRITE) $perm_entry[] = 'W';
67	if ($perm & PHPT_ACL_EXEC) $perm_entry[]  = 'RX';
68	if ($perm & PHPT_ACL_FULL) $perm_entry[]  = 'F';
69
70	// Deny all
71	$cmd = $icacls . ' ' . $path_escaped . ' /inheritance:r /deny ' . $user . ':(F,M,R,RX,W)';
72	exec($cmd);
73
74	if ($perm & PHPT_ACL_NONE) {
75		/*
76		 This is required to remove all the previously denied
77		 permission for the USER. Just granting permission doesn't
78		 remove the previously denied permission.
79		*/
80		$cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user;
81		exec($cmd);
82		$cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user;
83		exec($cmd);
84		return;
85	}
86
87	if ($mode == PHPT_ACL_GRANT) {
88		$mode = 'grant';
89	} else {
90		$mode = 'deny';
91	}
92
93
94	// Deny all
95	$cmd = $icacls . ' ' . $path_escaped . ' /deny ' . $user . ':(F,M,R,RX,W)';
96	exec($cmd);
97
98	/*
99	 This is required to remove all the previously denied
100	 permission for the USER. Just granting permission doesn't
101	 remove the previously denied permission.
102	*/
103	$cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user;
104	exec($cmd);
105	$cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user;
106	exec($cmd);
107
108
109	/*
110	 Required to set no permission and check that is_readable()
111	 returns false. If the $perm_entry contains 'N' skip this step.
112	 This will make the file/dir with NO aceess.
113	*/
114	if (!in_array('N', $perm_entry)) {
115		/*
116		 This is required to remove all the previously denied
117		 permission for the USER. Just granting permission doesn't
118		 remove the previously denied permission.
119		*/
120		$cmd = $icacls . ' ' . $path_escaped . ' /remove:d ' . $user;
121		exec($cmd);
122		$cmd = $icacls . ' ' . $path_escaped . ' /remove:g ' . $user;
123		exec($cmd);
124
125		$cmd = $icacls . ' ' . $path_escaped . ' /' . $mode . ' ' . $user;
126		$cmd .= ':' . '(' . implode($perm_entry, ',') . ')';
127		exec($cmd);
128	}
129}
130
131function create_dir($name, $perms) {
132	if (empty($name)) {
133		echo "create_dir: Empty name is not allowed\n";
134		return;
135	}
136
137	mkdir($name);
138	$dst = realpath($name);
139	icacls_set($name, PHPT_ACL_GRANT, $perms);
140}
141
142function create_file($name, $perms) {
143	if (empty($name)) {
144		echo "create_file: Empty name is not allowed\n";
145		return;
146	}
147
148	touch($name);
149	icacls_set($name, PHPT_ACL_GRANT, $perms);
150}
151
152function delete_file($path) {
153	icacls_set($path, PHPT_ACL_GRANT, PHPT_ACL_FULL);
154	if (is_file($path)) {
155		unlink($path);
156	} else {
157		echo "delete_file: '$path' is not a file\n";
158		return;
159	}
160}
161
162function delete_dir($path) {
163	if (is_dir($path)) {
164		icacls_set($path, PHPT_ACL_GRANT, PHPT_ACL_FULL);
165		rmdir($path);
166	} else {
167		echo "delete_dir: '$path' is not a directory\n";
168		return;
169	}
170}
171if (0) {
172$path = __DIR__ . '/a.txt';
173create_file($path, PHPT_ACL_NONE);
174if (!is_writable($path)) {
175	echo "PHPT_ACL_NONE success!!\n";
176} else {
177	echo "PHPT_ACL_NONE failed!!\n";
178}
179delete_file($path);
180
181$path = __DIR__ . '/a.txt';
182create_file($path, PHPT_ACL_READ);
183if (!is_writable($path)) {
184	echo "PHPT_ACL_READ success!!\n";
185} else {
186	echo "PHPT_ACL_READ failed!!\n";
187}
188delete_file($path);
189
190$path = __DIR__ . '/adir';
191create_dir($path, PHPT_ACL_READ);
192if (!is_writable($path)) {
193	echo "PHPT_ACL_READ dir success!!\n";
194} else {
195	echo "PHPT_ACL_READ dir failed!!\n";
196}
197delete_dir($path);
198
199}
200