mirror of
https://github.com/bdnugget/php-src.git
synced 2026-11-11 03:00:49 +00:00
Compare commits
501
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
785b3d9bf1 | ||
|
|
882a4c4d2c | ||
|
|
dd5652e4c1 | ||
|
|
963200c74c | ||
|
|
4c4d9102e8 | ||
|
|
85a9b2283f | ||
|
|
85a36e2bc3 | ||
|
|
2f5990a5c4 | ||
|
|
338e3357ae | ||
|
|
efea880e6f | ||
|
|
91af7f394f | ||
|
|
945f7d68b9 | ||
|
|
9632e324b6 | ||
|
|
895b4a2825 | ||
|
|
d7422e3821 | ||
|
|
eb3900b77a | ||
|
|
bb6422a83f | ||
|
|
ef3e8fa852 | ||
|
|
d265cdffbf | ||
|
|
4d3894178d | ||
|
|
6ad651afbe | ||
|
|
69a4d841a9 | ||
|
|
57f3b2504e | ||
|
|
72000ecda9 | ||
|
|
94c4feef12 | ||
|
|
aab4ad1a8e | ||
|
|
dbc1cb5e92 | ||
|
|
00b9ace829 | ||
|
|
62ed6a0f2b | ||
|
|
197d65770a | ||
|
|
4369785d6d | ||
|
|
1cd7013517 | ||
|
|
819127b74b | ||
|
|
579575e430 | ||
|
|
0d3884fed1 | ||
|
|
fd6d9cbeac | ||
|
|
8b4929818f | ||
|
|
fdb578219b | ||
|
|
322ed7d092 | ||
|
|
142ac728dd | ||
|
|
a1cf684b55 | ||
|
|
8867010b22 | ||
|
|
a50166004d | ||
|
|
02fa5aa0dc | ||
|
|
d39cca1530 | ||
|
|
513c93b9ae | ||
|
|
4f68f3774c | ||
|
|
22f796e55f | ||
|
|
0eaa26fc31 | ||
|
|
9996b5f731 | ||
|
|
1901b9d90e | ||
|
|
1e708a5aeb | ||
|
|
d402f6fab3 | ||
|
|
505144b844 | ||
|
|
1d1d20ced2 | ||
|
|
fdb29f9fa5 | ||
|
|
b799e6cbaf | ||
|
|
2f4ca9a2d4 | ||
|
|
52d6a64efa | ||
|
|
48335493eb | ||
|
|
eeb4e150e7 | ||
|
|
ec3aac1e86 | ||
|
|
dae2423d11 | ||
|
|
7280d303f4 | ||
|
|
ee8a0fc8f8 | ||
|
|
ec4f576cb3 | ||
|
|
b1d43bac61 | ||
|
|
dcd10fb714 | ||
|
|
08c344c293 | ||
|
|
690b45afaa | ||
|
|
5960786cc6 | ||
|
|
74259c9124 | ||
|
|
518145133f | ||
|
|
855f3591a6 | ||
|
|
0384e2ae27 | ||
|
|
dedab09c32 | ||
|
|
0835c34572 | ||
|
|
6078001f12 | ||
|
|
b8ed424ed3 | ||
|
|
fe73e4d851 | ||
|
|
ace6ff598c | ||
|
|
616d49aaf6 | ||
|
|
c8572b0bba | ||
|
|
b96ebb376f | ||
|
|
7ec9245c74 | ||
|
|
ea5d8fcf1d | ||
|
|
69aa60a947 | ||
|
|
99cae17cd0 | ||
|
|
709c5bd2d5 | ||
|
|
d800816f94 | ||
|
|
b8b1b35904 | ||
|
|
1d913a9c0b | ||
|
|
965783b7c1 | ||
|
|
f30355a7df | ||
|
|
87187da066 | ||
|
|
381d3f8e62 | ||
|
|
f95c1df583 | ||
|
|
53d0c7a753 | ||
|
|
bbd6dec20c | ||
|
|
0bfb0fad92 | ||
|
|
5ed8e63591 | ||
|
|
ce65982ec1 | ||
|
|
e762b69ccb | ||
|
|
ce84626a7f | ||
|
|
efbfaec0a3 | ||
|
|
b7a8297bc1 | ||
|
|
88b9c69cb2 | ||
|
|
4c5fd67f7c | ||
|
|
51501e8de0 | ||
|
|
4ca88997f7 | ||
|
|
8eacea8b48 | ||
|
|
6ffc1c291a | ||
|
|
05bf7d9c65 | ||
|
|
51b7d3a1c0 | ||
|
|
c84bd49fb5 | ||
|
|
d6dd2c26fa | ||
|
|
7035a224b5 | ||
|
|
dd5538566e | ||
|
|
e398e6b7d6 | ||
|
|
20db6b2dcb | ||
|
|
b5547442e5 | ||
|
|
5a81efa31f | ||
|
|
3849411fa2 | ||
|
|
823e4029f7 | ||
|
|
420a8cd50a | ||
|
|
998f5221b5 | ||
|
|
67e3288a5d | ||
|
|
9b09af54d9 | ||
|
|
a36e7b0ab1 | ||
|
|
57ba9b8ccf | ||
|
|
2f97097e0f | ||
|
|
edb7c7d4f5 | ||
|
|
4319872812 | ||
|
|
5d7d4a55aa | ||
|
|
ca28e37be1 | ||
|
|
e156ed7433 | ||
|
|
5950725144 | ||
|
|
ba75dd7877 | ||
|
|
f97066dc17 | ||
|
|
308081cd11 | ||
|
|
5e1a0f4c0c | ||
|
|
77319b779a | ||
|
|
35fec42377 | ||
|
|
5520636b17 | ||
|
|
f60dc4699f | ||
|
|
fe5c131a0d | ||
|
|
ad503c814b | ||
|
|
97360bacd5 | ||
|
|
48b766d500 | ||
|
|
b3da1422bb | ||
|
|
d3cf46ca1d | ||
|
|
4d360ead0c | ||
|
|
b9310261d7 | ||
|
|
041d23d7b6 | ||
|
|
60fc9c050a | ||
|
|
be00addf85 | ||
|
|
44a9c3188e | ||
|
|
d16571328f | ||
|
|
ce8331f9a5 | ||
|
|
295ae448b1 | ||
|
|
1c6f49006b | ||
|
|
8840250fa0 | ||
|
|
e45270dd2f | ||
|
|
7ccbed42c8 | ||
|
|
206c05dc47 | ||
|
|
1593aa0e5e | ||
|
|
e511b57e2a | ||
|
|
f370d0290f | ||
|
|
98dd7282be | ||
|
|
e99c375606 | ||
|
|
566230a01b | ||
|
|
e5cb1fa4e4 | ||
|
|
8ff9528138 | ||
|
|
6639ab8469 | ||
|
|
5b58b9af6b | ||
|
|
0bf1525bc8 | ||
|
|
1dda0f263a | ||
|
|
0286913937 | ||
|
|
993f70c1d2 | ||
|
|
de25255b6d | ||
|
|
5310de975c | ||
|
|
fb9b63de23 | ||
|
|
61d60153b2 | ||
|
|
bf8a6a07d8 | ||
|
|
3bca709fbc | ||
|
|
364c2fe5a2 | ||
|
|
af77fdb9bf | ||
|
|
e8f10e2694 | ||
|
|
be022a813f | ||
|
|
318be175a4 | ||
|
|
786ffab310 | ||
|
|
3166314d89 | ||
|
|
4894978500 | ||
|
|
883e096ce6 | ||
|
|
74de8bdb02 | ||
|
|
a13424db00 | ||
|
|
60b6ac053e | ||
|
|
cad60c3760 | ||
|
|
426443cc18 | ||
|
|
fa6079ea25 | ||
|
|
de46ba2ea5 | ||
|
|
bcdab8f7e6 | ||
|
|
b21a7357fc | ||
|
|
db855e2c74 | ||
|
|
32613f510c | ||
|
|
51505045e6 | ||
|
|
51fc7b8ea5 | ||
|
|
b4faef2fe3 | ||
|
|
636eb109ad | ||
|
|
96209e6cad | ||
|
|
92df5e9af9 | ||
|
|
2454194424 | ||
|
|
7374258dc1 | ||
|
|
f268ada2f3 | ||
|
|
93b21c6ed4 | ||
|
|
264fd866a1 | ||
|
|
79187b1360 | ||
|
|
8c4b687769 | ||
|
|
37b8c079d6 | ||
|
|
592b17d4d1 | ||
|
|
75f4ec8879 | ||
|
|
f3d6620f00 | ||
|
|
b86a6d448a | ||
|
|
d1341b1c15 | ||
|
|
b48af415cd | ||
|
|
d0ce6368b1 | ||
|
|
b7b1440330 | ||
|
|
ee656c4b32 | ||
|
|
15e14aeca5 | ||
|
|
5a10841059 | ||
|
|
22bbf75b5f | ||
|
|
e63a7d893b | ||
|
|
a60a6c5209 | ||
|
|
b1c45f61ad | ||
|
|
91e6402230 | ||
|
|
90e4fd0a0a | ||
|
|
5c412842d9 | ||
|
|
3944483cac | ||
|
|
99e343d250 | ||
|
|
58f9ed3a8e | ||
|
|
84e6f8f075 | ||
|
|
40defd5f2c | ||
|
|
b6da3465bc | ||
|
|
5caeacc9c3 | ||
|
|
161b37ffbc | ||
|
|
46baa28aaf | ||
|
|
e7b73ddce7 | ||
|
|
a0a046ca09 | ||
|
|
ae2d914580 | ||
|
|
8ff8c8cc49 | ||
|
|
c4508c377e | ||
|
|
7bfc91c3a9 | ||
|
|
546b9b97ca | ||
|
|
4d39a171ee | ||
|
|
f765acea59 | ||
|
|
cc39d06e4e | ||
|
|
addc7161b9 | ||
|
|
c0fd859688 | ||
|
|
2acc314e6f | ||
|
|
93cdab8b96 | ||
|
|
bfbd57905e | ||
|
|
bb099765a3 | ||
|
|
99639f79b6 | ||
|
|
a27afba6ff | ||
|
|
e7aeb7a4c8 | ||
|
|
70268f05ef | ||
|
|
84b90d6803 | ||
|
|
2803965525 | ||
|
|
ef9e7e5d9e | ||
|
|
cd7dafab7c | ||
|
|
a0ff48dbd3 | ||
|
|
30cad86a8d | ||
|
|
d38f944d1c | ||
|
|
07979b3ce4 | ||
|
|
78306b2d1d | ||
|
|
57d57237cf | ||
|
|
dc7cb19993 | ||
|
|
1e6c12c919 | ||
|
|
5f0433db83 | ||
|
|
5890197024 | ||
|
|
26cb5355e0 | ||
|
|
d746343928 | ||
|
|
dc2552a3ac | ||
|
|
d898a7418b | ||
|
|
f93193ccff | ||
|
|
2a90ba3642 | ||
|
|
2bf08d7d7d | ||
|
|
8085f48575 | ||
|
|
2c9d87c2f6 | ||
|
|
d45d690164 | ||
|
|
c8c9add3be | ||
|
|
83472de48e | ||
|
|
47e7fef08e | ||
|
|
d4ad4ac370 | ||
|
|
d0be029908 | ||
|
|
ae7285d658 | ||
|
|
05a3fabacb | ||
|
|
71078de71a | ||
|
|
a701436da6 | ||
|
|
79279dce97 | ||
|
|
62cd02c5a7 | ||
|
|
d7c839d54f | ||
|
|
138ef9a43e | ||
|
|
18896d510d | ||
|
|
60a2ea476b | ||
|
|
6b8544ace5 | ||
|
|
bef5858483 | ||
|
|
972940509f | ||
|
|
381adeadff | ||
|
|
5ec7c94a95 | ||
|
|
8a582fa707 | ||
|
|
7941b599fc | ||
|
|
a75203a278 | ||
|
|
dcf007c6da | ||
|
|
d96e7a170c | ||
|
|
37acb31c1a | ||
|
|
8c844fdde3 | ||
|
|
5865b3680a | ||
|
|
7b1d95adba | ||
|
|
ff531cca4d | ||
|
|
274dbb1b75 | ||
|
|
4da80ed1de | ||
|
|
dafda8936b | ||
|
|
cde7423cde | ||
|
|
c7f22e5aca | ||
|
|
739696d2d7 | ||
|
|
65ae35729d | ||
|
|
45ddc6a5cd | ||
|
|
f1072c2ae9 | ||
|
|
445daac3ab | ||
|
|
637c424d64 | ||
|
|
b1667b579b | ||
|
|
b1326c1c24 | ||
|
|
171d01dfcf | ||
|
|
7d80f82e70 | ||
|
|
5f888422d9 | ||
|
|
3d9eeb4538 | ||
|
|
9a19f065af | ||
|
|
89989f4e62 | ||
|
|
0b40c1d82b | ||
|
|
7557b388de | ||
|
|
8059173ad3 | ||
|
|
d5923d9121 | ||
|
|
d6bfe18b20 | ||
|
|
23475d4147 | ||
|
|
af900cb1d0 | ||
|
|
7d788aeba4 | ||
|
|
20eac88e58 | ||
|
|
a783891e76 | ||
|
|
aa74430ee0 | ||
|
|
4897bbe125 | ||
|
|
fe50278d0a | ||
|
|
e9549a4f9c | ||
|
|
47bf193c53 | ||
|
|
ac87800760 | ||
|
|
3e327b6e21 | ||
|
|
530d41732d | ||
|
|
20534bc445 | ||
|
|
03e298ec47 | ||
|
|
f5ddb60764 | ||
|
|
69a5253284 | ||
|
|
46455027fc | ||
|
|
c7b7791029 | ||
|
|
485f862b35 | ||
|
|
e64af9a898 | ||
|
|
dede51adf6 | ||
|
|
7223a1bc88 | ||
|
|
806245e185 | ||
|
|
03c19c2b8f | ||
|
|
fd83c1ea41 | ||
|
|
86efab2cc4 | ||
|
|
aae7a83df4 | ||
|
|
7e914380c9 | ||
|
|
f5cf052225 | ||
|
|
ba55871325 | ||
|
|
0936bfa42c | ||
|
|
a1c33af793 | ||
|
|
0b244def73 | ||
|
|
a497e9bf75 | ||
|
|
6bd845e365 | ||
|
|
0cd2da0309 | ||
|
|
40bf10319b | ||
|
|
2b9c90efd3 | ||
|
|
b9638a4a50 | ||
|
|
6b0cc4b54d | ||
|
|
e67ad79599 | ||
|
|
d77a3f92e6 | ||
|
|
b0f344e493 | ||
|
|
93f795bb9e | ||
|
|
49e31e4b0f | ||
|
|
d1b29ad4c2 | ||
|
|
8c6ab178e4 | ||
|
|
5ff2111a59 | ||
|
|
67c42a4a9b | ||
|
|
70d78cf7dd | ||
|
|
b5a926f78d | ||
|
|
da3d9f8e25 | ||
|
|
e58e6efd4d | ||
|
|
170c92dfbe | ||
|
|
950f950ecd | ||
|
|
bb23e0d7cc | ||
|
|
17adf438a2 | ||
|
|
34b00ca22a | ||
|
|
2682bbd2b0 | ||
|
|
96c002e07c | ||
|
|
f064a2c8b9 | ||
|
|
6789bcfed2 | ||
|
|
4162f81c88 | ||
|
|
728b849529 | ||
|
|
d42361630f | ||
|
|
1c2a22025d | ||
|
|
5e5d2640fb | ||
|
|
08fa8849b2 | ||
|
|
7b292e2fba | ||
|
|
dee534efba | ||
|
|
e5ed53b00a | ||
|
|
f502f56613 | ||
|
|
ee93ed0aaa | ||
|
|
a03447092d | ||
|
|
633ce3039f | ||
|
|
182e93ab6e | ||
|
|
23d202bd36 | ||
|
|
fbfd50bd1f | ||
|
|
e87fe59e96 | ||
|
|
e25a206e87 | ||
|
|
514dfbfbed | ||
|
|
f89486a3a0 | ||
|
|
446cc107b8 | ||
|
|
c210c68add | ||
|
|
3e026f08ae | ||
|
|
180306cf88 | ||
|
|
8a153add90 | ||
|
|
7601484612 | ||
|
|
7bdc6d4bf4 | ||
|
|
31757a6aa8 | ||
|
|
f92797f4e0 | ||
|
|
fc7197322c | ||
|
|
f3f7b6242d | ||
|
|
6b2e7f941a | ||
|
|
0d085b253f | ||
|
|
15b6714595 | ||
|
|
1f57188741 | ||
|
|
d889a123db | ||
|
|
fb3c30574e | ||
|
|
045d395d4a | ||
|
|
32e125e2b8 | ||
|
|
5ff410efdf | ||
|
|
fae637021d | ||
|
|
46bc2c5ae2 | ||
|
|
d84702836a | ||
|
|
96fc48b606 | ||
|
|
86b0967775 | ||
|
|
e000da960b | ||
|
|
f17aba3062 | ||
|
|
71b7a54377 | ||
|
|
8a8b20877c | ||
|
|
e0f33c589f | ||
|
|
e35bc2e2b4 | ||
|
|
0d002664fb | ||
|
|
967c72865f | ||
|
|
cbd5396cbb | ||
|
|
56f8195fe5 | ||
|
|
599ae4b1b5 | ||
|
|
83d2cbd36e | ||
|
|
fa958958c3 | ||
|
|
8840191d91 | ||
|
|
1ea073fb7a | ||
|
|
8860787ad9 | ||
|
|
5c17925a7c | ||
|
|
a7f36a5825 | ||
|
|
a5b697826b | ||
|
|
42ade33fa6 | ||
|
|
8925d6573e | ||
|
|
d19914a2aa | ||
|
|
ed682e570a | ||
|
|
22b70fcb31 | ||
|
|
96f5c697dd | ||
|
|
29ba20eea0 | ||
|
|
07a17df386 | ||
|
|
a0191f0505 | ||
|
|
af9c0b84cd | ||
|
|
9f50e40643 | ||
|
|
2af6d0e1ab | ||
|
|
15ef63b39a | ||
|
|
394a0aea16 | ||
|
|
b63393dea0 | ||
|
|
5289adbe99 | ||
|
|
d40e78ad6f | ||
|
|
d725f3af91 | ||
|
|
d1106bb4dc | ||
|
|
5c0cd5c47e | ||
|
|
53697aeb0d | ||
|
|
86d46f7cc1 | ||
|
|
381a3b234f | ||
|
|
6dd2613d7b | ||
|
|
10d903343f | ||
|
|
eb2e53be99 | ||
|
|
ce6717965e | ||
|
|
7722837517 | ||
|
|
1cdf7e66f4 | ||
|
|
32bdaae133 |
No files matched your search
@@ -1,359 +0,0 @@
|
||||
set $zts = 0
|
||||
|
||||
define ____executor_globals
|
||||
if $zts
|
||||
set $eg = ((zend_executor_globals) (*((void ***) tsrm_ls))[executor_globals_id-1])
|
||||
else
|
||||
set $eg = executor_globals
|
||||
end
|
||||
end
|
||||
|
||||
document ____executor_globals
|
||||
portable way of accessing executor_globals
|
||||
type "set $zts = 1" if you use --enable-maintainer-zts on your configure line
|
||||
end
|
||||
|
||||
define dump_bt
|
||||
set $t = $arg0
|
||||
while $t
|
||||
printf "[0x%08x] ", $t
|
||||
if $t->function_state.function->common.function_name
|
||||
printf "%s() ", $t->function_state.function->common.function_name
|
||||
else
|
||||
printf "??? "
|
||||
end
|
||||
if $t->op_array != 0
|
||||
printf "%s:%d ", $t->op_array->filename, $t->opline->lineno
|
||||
end
|
||||
set $t = $t->prev_execute_data
|
||||
printf "\n"
|
||||
end
|
||||
end
|
||||
|
||||
document dump_bt
|
||||
dumps the current execution stack. usage: dump_bt executor_globals.current_execute_data
|
||||
end
|
||||
|
||||
define printzv
|
||||
set $ind = 1
|
||||
____printzv $arg0 0
|
||||
end
|
||||
|
||||
document printzv
|
||||
prints content of zval
|
||||
end
|
||||
|
||||
define ____printzv_contents
|
||||
____executor_globals
|
||||
set $zvalue = $arg0
|
||||
|
||||
if $zvalue.type == 0
|
||||
set $typename = "NULL"
|
||||
end
|
||||
if $zvalue.type == 1
|
||||
set $typename = "long"
|
||||
end
|
||||
if $zvalue.type == 2
|
||||
set $typename = "double"
|
||||
end
|
||||
if $zvalue.type == 3
|
||||
set $typename = "string"
|
||||
end
|
||||
if $zvalue.type == 4
|
||||
set $typename = "array"
|
||||
end
|
||||
if $zvalue.type == 5
|
||||
set $typename = "object"
|
||||
end
|
||||
if $zvalue.type == 6
|
||||
set $typename = "bool"
|
||||
end
|
||||
if $zvalue.type == 7
|
||||
set $typename = "resource"
|
||||
end
|
||||
if $zvalue.type == 8
|
||||
set $typename = "constant"
|
||||
end
|
||||
if $zvalue.type == 9
|
||||
set $typename = "const_array"
|
||||
end
|
||||
|
||||
printf "(refcount=%d) %s: ", $zvalue.refcount, $typename
|
||||
if $zvalue.type == 1
|
||||
printf "%ld", $zvalue.value.lval
|
||||
end
|
||||
if $zvalue->type == 2
|
||||
printf "%lf", $zvalue.value.dval
|
||||
end
|
||||
if $zvalue.type == 3
|
||||
printf "\"%s\"(%d)", $zvalue.value.str.val, $zvalue.value.str.len
|
||||
end
|
||||
if $zvalue.type == 4
|
||||
if ! $arg1
|
||||
printf "{\n"
|
||||
set $ind = $ind + 1
|
||||
____print_ht $zvalue.value.ht
|
||||
set $ind = $ind - 1
|
||||
set $i = $ind
|
||||
while $i > 0
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
printf "}"
|
||||
end
|
||||
end
|
||||
if $zvalue.type == 5
|
||||
if ! $arg1
|
||||
printf "(prop examination disabled due to a gdb bug)"
|
||||
if $zvalue.value.obj.handlers->get_properties
|
||||
# set $ht = $zvalue->value.obj.handlers->get_properties($zvalue)
|
||||
# printf "{\n"
|
||||
# set $ind = $ind + 1
|
||||
# ____print_ht $ht
|
||||
# set $ind = $ind - 1
|
||||
# set $i = $ind
|
||||
# while $i > 0
|
||||
# printf " "
|
||||
# set $i = $i - 1
|
||||
# end
|
||||
# printf "}"
|
||||
end
|
||||
end
|
||||
end
|
||||
if $zvalue.type == 6
|
||||
if $zvalue.value.lval
|
||||
printf "true"
|
||||
else
|
||||
printf "false"
|
||||
end
|
||||
end
|
||||
if $zvalue.type == 7
|
||||
printf "#%d", $zvalue.value.lval
|
||||
end
|
||||
printf "\n"
|
||||
end
|
||||
|
||||
define ____printzv
|
||||
____executor_globals
|
||||
set $zvalue = $arg0
|
||||
|
||||
printf "[0x%08x] ", $zvalue
|
||||
|
||||
if $zvalue == $eg.uninitialized_zval_ptr
|
||||
printf "*uninitialized* "
|
||||
end
|
||||
|
||||
set $zcontents = *(struct _zval_struct *) $zvalue
|
||||
if $arg1
|
||||
____printzv_contents $zcontents $arg1
|
||||
else
|
||||
____printzv_contents $zcontents 0
|
||||
end
|
||||
end
|
||||
|
||||
define ____print_const_table
|
||||
set $ht = $arg0
|
||||
set $p = $ht->pListHead
|
||||
|
||||
while $p != 0
|
||||
set $const = *(zend_constant *) $p->pData
|
||||
|
||||
set $i = $ind
|
||||
while $i > 0
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
|
||||
if $p->nKeyLength > 0
|
||||
printf "\"%s\" => ", $p->arKey
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
____printzv_contents $const.value 0
|
||||
set $p = $p->pListNext
|
||||
end
|
||||
end
|
||||
|
||||
define print_const_table
|
||||
set $ind = 1
|
||||
printf "[0x%08x] {\n", $arg0
|
||||
____print_const_table $arg0
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
define ____print_ht
|
||||
set $ht = $arg0
|
||||
set $p = $ht->pListHead
|
||||
|
||||
while $p != 0
|
||||
set $zval = *(struct _zval_struct **)$p->pData
|
||||
|
||||
set $i = $ind
|
||||
while $i > 0
|
||||
printf " "
|
||||
set $i = $i - 1
|
||||
end
|
||||
|
||||
if $p->nKeyLength > 0
|
||||
printf "\"%s\" => ", $p->arKey
|
||||
else
|
||||
printf "%d => ", $p->h
|
||||
end
|
||||
|
||||
____printzv $zval 1
|
||||
set $p = $p->pListNext
|
||||
end
|
||||
end
|
||||
|
||||
define print_ht
|
||||
set $ind = 1
|
||||
printf "[0x%08x] {\n", $arg0
|
||||
____print_ht $arg0
|
||||
printf "}\n"
|
||||
end
|
||||
|
||||
document print_ht
|
||||
dumps elements of HashTable made of zval
|
||||
end
|
||||
|
||||
define printzn
|
||||
____executor_globals
|
||||
set $ind = 0
|
||||
set $znode = $arg0
|
||||
if $znode->op_type == 1
|
||||
set $optype = "IS_CONST"
|
||||
end
|
||||
if $znode->op_type == 2
|
||||
set $optype = "IS_TMP_VAR"
|
||||
end
|
||||
if $znode->op_type == 4
|
||||
set $optype = "IS_VAR"
|
||||
end
|
||||
if $znode->op_type == 8
|
||||
set $optype = "IS_UNUSED"
|
||||
end
|
||||
|
||||
printf "[0x%08x] %s", $znode, $optype
|
||||
|
||||
if $znode->op_type == 1
|
||||
printf ": "
|
||||
____printzv &$znode->u.constant 0
|
||||
end
|
||||
if $znode->op_type == 2
|
||||
printf ": "
|
||||
set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
|
||||
____printzv ((union _temp_variable *)$tvar)->tmp_var 0
|
||||
end
|
||||
if $znode->op_type == 4
|
||||
printf ": "
|
||||
set $tvar = (union _temp_variable *)((char *)$eg.current_execute_data->Ts + $znode->u.var)
|
||||
____printzv *$tvar->var.ptr_ptr 0
|
||||
end
|
||||
if $znode->op_type == 8
|
||||
printf "\n"
|
||||
end
|
||||
end
|
||||
|
||||
document printzn
|
||||
print type and content of znode.
|
||||
usage: printzn &opline->op1
|
||||
end
|
||||
|
||||
define printzops
|
||||
printf "op1 => "
|
||||
printzn &execute_data->opline.op1
|
||||
printf "op2 => "
|
||||
printzn &execute_data->opline.op2
|
||||
printf "result => "
|
||||
printzn &execute_data->opline.result
|
||||
end
|
||||
|
||||
document printzops
|
||||
dump operands of the current opline
|
||||
end
|
||||
|
||||
define zbacktrace
|
||||
____executor_globals
|
||||
dump_bt $eg.current_execute_data
|
||||
end
|
||||
|
||||
document zbacktrace
|
||||
prints backtrace.
|
||||
This command is almost a short cut for
|
||||
> (gdb) ____executor_globals
|
||||
> (gdb) dump_bt $eg.current_execute_data
|
||||
end
|
||||
|
||||
define zmemcheck
|
||||
set $p = alloc_globals.head
|
||||
set $stat = "?"
|
||||
set $total_size = 0
|
||||
if $arg0 != 0
|
||||
set $not_found = 1
|
||||
else
|
||||
set $not_found = 0
|
||||
end
|
||||
printf " block size status file:line\n"
|
||||
printf "-------------------------------------------------------------------------------\n"
|
||||
while $p
|
||||
set $aptr = $p + sizeof(struct _zend_mem_header) + sizeof(align_test)
|
||||
if $arg0 == 0 || (void *)$aptr == (void *)$arg0
|
||||
if $p->magic == 0x7312f8dc
|
||||
set $stat = "OK"
|
||||
end
|
||||
if $p->magic == 0x99954317
|
||||
set $stat = "FREED"
|
||||
end
|
||||
if $p->magic == 0xfb8277dc
|
||||
set $stat = "CACHED"
|
||||
end
|
||||
set $filename = strrchr($p->filename, '/')
|
||||
if !$filename
|
||||
set $filename = $p->filename
|
||||
else
|
||||
set $filename = $filename + 1
|
||||
end
|
||||
printf " 0x%08x ", $aptr
|
||||
if $p->size == sizeof(struct _zval_struct) && ((struct _zval_struct *)$aptr)->type >= 0 && ((struct _zval_struct *)$aptr)->type < 10
|
||||
printf "ZVAL?(%-2d) ", $p->size
|
||||
else
|
||||
printf "%-9d ", $p->size
|
||||
end
|
||||
set $total_size = $total_size + $p->size
|
||||
printf "%-06s %s:%d", $stat, $filename, $p->lineno
|
||||
if $p->orig_filename
|
||||
set $orig_filename = strrchr($p->orig_filename, '/')
|
||||
if !$orig_filename
|
||||
set $orig_filename = $p->orig_filename
|
||||
else
|
||||
set $orig_filename = $orig_filename + 1
|
||||
end
|
||||
printf " <= %s:%d\n", $orig_filename, $p->orig_lineno
|
||||
else
|
||||
printf "\n"
|
||||
end
|
||||
if $arg0 != 0
|
||||
set $p = 0
|
||||
set $not_found = 0
|
||||
else
|
||||
set $p = $p->pNext
|
||||
end
|
||||
else
|
||||
set $p = $p->pNext
|
||||
end
|
||||
end
|
||||
if $not_found
|
||||
printf "no such block that begins at 0x%08x.\n", $aptr
|
||||
end
|
||||
if $arg0 == 0
|
||||
printf "-------------------------------------------------------------------------------\n"
|
||||
printf " total: %d bytes\n", $total_size
|
||||
end
|
||||
end
|
||||
|
||||
document zmemcheck
|
||||
show status of a memory block.
|
||||
usage: zmemcheck [ptr].
|
||||
if ptr is 0, all blocks will be listed.
|
||||
end
|
||||
@@ -1,272 +0,0 @@
|
||||
PHP Coding Standards
|
||||
====================
|
||||
|
||||
|
||||
This file lists several standards that any programmer, adding or changing
|
||||
code in PHP, should follow. Since this file was added at a very late
|
||||
stage of the development of PHP v3.0, the code base does not (yet) fully
|
||||
follow it, but it's going in that general direction. Since we are now
|
||||
well into the version 4 releases, many sections have been recoded to use
|
||||
these rules.
|
||||
|
||||
|
||||
Code Implementation
|
||||
-------------------
|
||||
|
||||
[0] Document your code in source files and the manual. [tm]
|
||||
|
||||
[1] Functions that are given pointers to resources should not free them
|
||||
|
||||
For instance, function int mail(char *to, char *from) should NOT free
|
||||
to and/or from.
|
||||
Exceptions:
|
||||
|
||||
- The function's designated behavior is freeing that resource. E.g. efree()
|
||||
- The function is given a boolean argument, that controls whether or not
|
||||
the function may free its arguments (if true - the function must free its
|
||||
arguments, if false - it must not)
|
||||
- Low-level parser routines, that are tightly integrated with the token
|
||||
cache and the bison code for minimum memory copying overhead.
|
||||
|
||||
[2] Functions that are tightly integrated with other functions within the
|
||||
same module, and rely on each other non-trivial behavior, should be
|
||||
documented as such and declared 'static'. They should be avoided if
|
||||
possible.
|
||||
|
||||
[3] Use definitions and macros whenever possible, so that constants have
|
||||
meaningful names and can be easily manipulated. The only exceptions
|
||||
to this rule are 0 and 1, when used as false and true (respectively).
|
||||
Any other use of a numeric constant to specify different behavior
|
||||
or actions should be done through a #define.
|
||||
|
||||
[4] When writing functions that deal with strings, be sure to remember
|
||||
that PHP holds the length property of each string, and that it
|
||||
shouldn't be calculated with strlen(). Write your functions in a such
|
||||
a way so that they'll take advantage of the length property, both
|
||||
for efficiency and in order for them to be binary-safe.
|
||||
Functions that change strings and obtain their new lengths while
|
||||
doing so, should return that new length, so it doesn't have to be
|
||||
recalculated with strlen() (e.g. php_addslashes())
|
||||
|
||||
[5] NEVER USE strncat(). If you're absolutely sure you know what you're doing,
|
||||
check its man page again, and only then, consider using it, and even then,
|
||||
try avoiding it.
|
||||
|
||||
[6] Use PHP_* macros in the PHP source, and ZEND_* macros in the Zend
|
||||
part of the source. Although the PHP_* macro's are mostly aliased to the
|
||||
ZEND_* macros it gives a better understanding on what kind of macro you're
|
||||
calling.
|
||||
|
||||
[7] When commenting out code using a #if statement, do NOT use 0 only. Instead
|
||||
use "<cvs username here>_0". For example, #if FOO_0, where FOO is your
|
||||
cvs user foo. This allows easier tracking of why code was commented out,
|
||||
especially in bundled libraries.
|
||||
|
||||
[8] Do not define functions that are not available. For instance, if a
|
||||
library is missing a function, do not define the PHP version of the
|
||||
function, and do not raise a run-time error about the function not
|
||||
existing. End users should use function_exists() to test for the
|
||||
existence of a function
|
||||
|
||||
[9] Prefer emalloc(), efree(), estrdup(), etc. to their standard C library
|
||||
counterparts. These functions implement an internal "safety-net"
|
||||
mechanism that ensures the deallocation of any unfreed memory at the
|
||||
end of a request. They also provide useful allocation and overflow
|
||||
information while running in debug mode.
|
||||
|
||||
In almost all cases, memory returned to the engine must be allocated
|
||||
using emalloc().
|
||||
|
||||
The use of malloc() should be limited to cases where a third-party
|
||||
library may need to control or free the memory, or when the memory in
|
||||
question needs to survive between multiple requests.
|
||||
|
||||
Naming Conventions
|
||||
------------------
|
||||
|
||||
[1] Function names for user-level functions should be enclosed with in
|
||||
the PHP_FUNCTION() macro. They should be in lowercase, with words
|
||||
underscore delimited, with care taken to minimize the letter count.
|
||||
Abbreviations should not be used when they greatly decrease the
|
||||
readability of the function name itself.
|
||||
|
||||
Good:
|
||||
'mcrypt_enc_self_test'
|
||||
'mysql_list_fields'
|
||||
|
||||
Ok:
|
||||
'mcrypt_module_get_algo_supported_key_sizes'
|
||||
(could be 'mcrypt_mod_get_algo_sup_key_sizes'?)
|
||||
'get_html_translation_table'
|
||||
(could be 'html_get_trans_table'?)
|
||||
|
||||
Bad:
|
||||
'hw_GetObjectByQueryCollObj'
|
||||
'pg_setclientencoding'
|
||||
'jf_n_s_i'
|
||||
|
||||
[2] If they are part of a "parent set" of functions, that parent should
|
||||
be included in the user function name, and should be clearly related
|
||||
to the parent program or function family. This should be in the form
|
||||
of parent_*.
|
||||
|
||||
A family of 'foo' functions, for example:
|
||||
Good:
|
||||
'foo_select_bar'
|
||||
'foo_insert_baz'
|
||||
'foo_delete_baz'
|
||||
|
||||
Bad:
|
||||
'fooselect_bar'
|
||||
'fooinsertbaz'
|
||||
'delete_foo_baz'
|
||||
|
||||
[3] Function names used by user functions should be prefixed
|
||||
with "_php_", and followed by a word or an underscore-delimited list of
|
||||
words, in lowercase letters, that describes the function. If applicable,
|
||||
they should be declared 'static'.
|
||||
|
||||
[4] Variable names must be meaningful. One letter variable names must be
|
||||
avoided, except for places where the variable has no real meaning or
|
||||
a trivial meaning (e.g. for (i=0; i<100; i++) ...).
|
||||
|
||||
[5] Variable names should be in lowercase. Use underscores to separate
|
||||
between words.
|
||||
|
||||
[6] Method names follow the 'studlyCaps' (also referred to as 'bumpy case'
|
||||
or 'camel caps') naming convention, with care taken to minimize the
|
||||
letter count. The initial letter of the name is lowercase, and each
|
||||
letter that starts a new 'word' is capitalized.
|
||||
|
||||
Good:
|
||||
'connect()'
|
||||
'getData()'
|
||||
'buildSomeWidget()'
|
||||
|
||||
Bad:
|
||||
'get_Data()'
|
||||
'buildsomewidget'
|
||||
'getI()'
|
||||
|
||||
[7] Classes should be given descriptive names. Avoid using abbreviations
|
||||
where possible. Each word in the class name should start with a capital
|
||||
letter, with words underscore delimited. The class name should be prefixed
|
||||
with the name of the 'parent set'.
|
||||
|
||||
Good:
|
||||
'Curl'
|
||||
'Foo_Bar'
|
||||
|
||||
Bad:
|
||||
'foobar'
|
||||
'foo_bar'
|
||||
'FooBar'
|
||||
|
||||
|
||||
Syntax and indentation
|
||||
----------------------
|
||||
|
||||
[1] Never use C++ style comments (i.e. // comment). Always use C-style
|
||||
comments instead. PHP is written in C, and is aimed at compiling
|
||||
under any ANSI-C compliant compiler. Even though many compilers
|
||||
accept C++-style comments in C code, you have to ensure that your
|
||||
code would compile with other compilers as well.
|
||||
The only exception to this rule is code that is Win32-specific,
|
||||
because the Win32 port is MS-Visual C++ specific, and this compiler
|
||||
is known to accept C++-style comments in C code.
|
||||
|
||||
[2] Use K&R-style. Of course, we can't and don't want to
|
||||
force anybody to use a style he or she is not used to, but,
|
||||
at the very least, when you write code that goes into the core
|
||||
of PHP or one of its standard modules, please maintain the K&R
|
||||
style. This applies to just about everything, starting with
|
||||
indentation and comment styles and up to function declaration
|
||||
syntax.
|
||||
|
||||
(see also http://www.catb.org/~esr/jargon/html/I/indent-style.html)
|
||||
|
||||
[3] Be generous with whitespace and braces. Always prefer:
|
||||
|
||||
if (foo) {
|
||||
bar;
|
||||
}
|
||||
|
||||
to:
|
||||
|
||||
if(foo)bar;
|
||||
|
||||
Keep one empty line between the variable declaration section and
|
||||
the statements in a block, as well as between logical statement
|
||||
groups in a block. Maintain at least one empty line between
|
||||
two functions, preferably two.
|
||||
|
||||
[4] When indenting, use the tab character. A tab is expected to represent
|
||||
four spaces. It is important to maintain consistency in indenture so
|
||||
that definitions, comments, and control structures line up correctly.
|
||||
|
||||
[5] Preprocessor statements (#if and such) MUST start at column one. To
|
||||
indent preprocessor directives you should put the # at the beginning
|
||||
of a line, followed by any number of whitespace.
|
||||
|
||||
Documentation and Folding Hooks
|
||||
-------------------------------
|
||||
|
||||
In order to make sure that the online documentation stays in line with
|
||||
the code, each user-level function should have its user-level function
|
||||
prototype before it along with a brief one-line description of what the
|
||||
function does. It would look like this:
|
||||
|
||||
/* {{{ proto int abs(int number)
|
||||
Returns the absolute value of the number */
|
||||
PHP_FUNCTION(abs)
|
||||
{
|
||||
...
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
The {{{ symbols are the default folding symbols for the folding mode in
|
||||
Emacs and vim (set fdm=marker). Folding is very useful when dealing with
|
||||
large files because you can scroll through the file quickly and just unfold
|
||||
the function you wish to work on. The }}} at the end of each function marks
|
||||
the end of the fold, and should be on a separate line.
|
||||
|
||||
The "proto" keyword there is just a helper for the doc/genfuncsummary script
|
||||
which generates a full function summary. Having this keyword in front of the
|
||||
function prototypes allows us to put folds elsewhere in the code without
|
||||
messing up the function summary.
|
||||
|
||||
Optional arguments are written like this:
|
||||
|
||||
/* {{{ proto object imap_header(int stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
|
||||
Returns a header object with the defined parameters */
|
||||
|
||||
And yes, please keep the prototype on a single line, even if that line
|
||||
is massive.
|
||||
|
||||
New and Experimental Functions
|
||||
-----------------------------------
|
||||
To reduce the problems normally associated with the first public
|
||||
implementation of a new set of functions, it has been suggested
|
||||
that the first implementation include a file labeled 'EXPERIMENTAL'
|
||||
in the function directory, and that the functions follow the
|
||||
standard prefixing conventions during their initial implementation.
|
||||
|
||||
The file labelled 'EXPERIMENTAL' should include the following
|
||||
information:
|
||||
Any authoring information (known bugs, future directions of the module).
|
||||
Ongoing status notes which may not be appropriate for CVS comments.
|
||||
|
||||
Aliases & Legacy Documentation
|
||||
-----------------------------------
|
||||
You may also have some deprecated aliases with close to duplicate
|
||||
names, for example, somedb_select_result and somedb_selectresult. For
|
||||
documentation purposes, these will only be documented by the most
|
||||
current name, with the aliases listed in the documentation for
|
||||
the parent function. For ease of reference, user-functions with
|
||||
completely different names, that alias to the same function (such as
|
||||
highlight_file and show_source), will be separately documented. The
|
||||
proto should still be included, describing which function is aliased.
|
||||
|
||||
Backwards compatible functions and names should be maintained as long
|
||||
as the code can be reasonably be kept as part of the codebase. See
|
||||
/phpdoc/README for more information on documentation.
|
||||
@@ -1,2 +0,0 @@
|
||||
For the list of people who've put work into PHP, please see
|
||||
http://www.php.net/credits.php
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-456
@@ -1,456 +0,0 @@
|
||||
List of PHP maintainers
|
||||
=======================
|
||||
|
||||
Maintenance legend
|
||||
------------------
|
||||
Supported: Someone is actually paid to look after this.
|
||||
Maintained: Someone actually looks after it.
|
||||
Odd Fixes: It has a maintainer but they don't have time to do
|
||||
much other than throw the odd patch in. See below.
|
||||
Orphan: No current maintainer [but maybe you could take the
|
||||
role as you write your new code].
|
||||
Obsolete: Old code. Something tagged obsolete generally means
|
||||
it has been replaced by a better system and you
|
||||
should be using that.
|
||||
Unknown: Not known at this time.
|
||||
|
||||
Status legend
|
||||
-------------
|
||||
Working: Working under both Windows and Unix.
|
||||
Windows: Working only under Windows.
|
||||
Unix: Working only under Unix.
|
||||
Experimental: Under development or initial release.
|
||||
Not Working: Not working.
|
||||
Unknown: Status unknown.
|
||||
|
||||
|
||||
== Server APIs ==
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: activescript
|
||||
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>
|
||||
MAINTENANCE: Odd Fixes
|
||||
STATUS: Experimental
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: aolserver
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: apache
|
||||
PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: apache2handler / apache2filter
|
||||
PRIMARY MAINTAINER: Aaron Bannert <aaron@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: apache_hooks
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: caudium
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: cgi
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: cli
|
||||
MAINTENANCE: Marcus Boerger <helly@php.net>, Edin Kadribasic <edink@php.net>
|
||||
STATUS: Working
|
||||
SINCE: 4.3.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: embed
|
||||
PRIMARY MAINTAINER: Edin Kadribasic <edink@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: isapi
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: milter
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: nsapi
|
||||
PRIMARY MAINTAINER: Uwe Schindler <thetaphi@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: phttpd
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pi3web
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: roxen
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: thttpd
|
||||
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>
|
||||
MAINTENANCE: Odd fixes
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: tux
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: webjames
|
||||
PRIMARY MAINTAINER: Alex Waugh <alex@alexwaugh.com>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
== Database extensions ==
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: dba
|
||||
PRIMARY MAINTAINER: Marcus Börger <helly@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
COMMENT: DBM abstraction for db2, db3, db4, dbm, ndbm, gdbm, ini
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: dbase
|
||||
MAINTENANCE: Orphaned
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: dbx
|
||||
PRIMARY MAINTAINER: Marc Boeren <M.Boeren@guidance.nl>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.0.6
|
||||
COMMENT: DB abstraction for odbc, mysql, pgsql, mssql, fbsql and more, see documentation
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: filepro
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: hwapi
|
||||
PRIMARY MAINTAINER: Uwe Steinmann <steinm@php.net>
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: informix
|
||||
PRIMARY MAINTAINER: Danny Heijl <Danny.Heijl@cevi.be>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: ingres_ii
|
||||
PRIMARY MAINTAINER: David Hénot <henot@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: interbase
|
||||
PRIMARY MAINTAINER: Ard Biesheuvel <ard@ard.nu>, Jouni Ahto <jouni.ahto@exdec.fi>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: msql
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mssql
|
||||
PRIMARY MAINTAINER: Frank M. Kromann <fmk@swwwing.com>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
COMMENT: Tested on phpts and isapi versions
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mysql
|
||||
PRIMARY MAINTAINER: Zak Greant <zak@mysql.com>, Georg Richter <georg@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mysqli
|
||||
PRIMARY MAINTAINER: Georg Richter <georg@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 5.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pgsql
|
||||
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Yasuo Ohgaki <yohgaki@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
COMMENT: Use PostgreSQL 7.0.x or later. PostgreSQL 6.5.3 or less have fatal bug.
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sqlite
|
||||
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>, Wez Furlong <wez@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 5.0 (Since 4.3.2 in PECL)
|
||||
COMMENT: Integrates SQLite embeddable SQL database engine.
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sybase
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Not Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sybase_ct
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: oci8
|
||||
PRIMARY MAINTAINER: Antony Dovgal <tony2001@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: odbc
|
||||
PRIMARY MAINTAINER: Daniel R. Kalowsky <kalowsky@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
COMMENT: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: oracle
|
||||
MAINTENANCE: Orphaned
|
||||
STATUS: Working
|
||||
COMMENT: Using the new OCI8 driver is encouraged where possible.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
== XML extensions ==
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: dom
|
||||
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net>, Rob Richards <rrichards@php.net>, Marcus Boerger <helly@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 5.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: simplexml
|
||||
PRIMARY MAINTAINER: Sterling Hughes <sterling@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 5.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: wddx
|
||||
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xml
|
||||
PRIMARY MAINTAINER: Thies C. Arntzen <thies@thieso.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xmlrpc
|
||||
PRIMARY MAINTAINER: Dan Libby
|
||||
MAINTENANCE: UNKNOWN
|
||||
STATUS: Experimental
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: xsl
|
||||
PRIMARY MAINTAINER: Christian Stocker <chregu@php.net>, Rob Richards <rrichards@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 5.0
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
|
||||
== Other extensions ==
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: bcmath
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: bz2
|
||||
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
|
||||
MAINTENANCE: Odd Fixes
|
||||
STATUS: Working
|
||||
SINCE: 4.0.3
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: dio
|
||||
MAINTENANCE: Orphaned
|
||||
STATUS: Working
|
||||
SINCE: 4.0.6
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: calendar
|
||||
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
|
||||
MAINTENANCE: Odd Fixes
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: com_dotnet
|
||||
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Windows
|
||||
SINCE: 5.0
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: cpdf
|
||||
PRIMARY MAINTAINER: Uwe Steinmann <steinm@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: ctype
|
||||
PRIMARY MAINTAINER: Hartmut Holzgraefe <hholzgra@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: curl
|
||||
PRIMARY MAINTAINER: Sterling Hughes <sterling@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: exif
|
||||
PRIMARY MAINTAINER: Marcus Boerger <helly@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: fdf
|
||||
PRIMARY MAINTAINER: Uwe Steinmann <steinm@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: ftp
|
||||
PRIMARY MAINTAINER: Stefan Esser (sesser@php.net)
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gd
|
||||
PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gettext
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: gmp
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
SINCE: 4.0.4
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: iconv
|
||||
PRIMARY MAINTAINER: Moriyoshi Koizumi <moriyoshi@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: imap
|
||||
PRIMARY MAINTAINER: Chuck Hagenbuch <chuck@horde.org>
|
||||
MAINTENANCE: Odd Fixes
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: ldap
|
||||
PRIMARY MAINTAINER: Stig Venaas <venaas@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mbstring
|
||||
PRIMARY MAINTAINER: Rui Hirokawa <hirokawa@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mcrypt
|
||||
PRIMARY MAINTAINER: Derick Rethans <derick@derickrethans.nl>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: mhash
|
||||
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: msession
|
||||
PRIMARY MAINTAINER Mark L. Woodward mlwmohawk@mohawksoft.com
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working/Experimental
|
||||
COMMENT: Tested on Linux, should work on other UNIX platforms. Backend server code can compile under Windows.
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: openssl
|
||||
PRIMARY MAINTAINER: Wez Furlong <wez@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 4.0.4
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pcre
|
||||
PRIMARY MAINTAINER: Andrei Zmievski <andrei@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pdf
|
||||
PRIMARY MAINTAINER: Uwe Steinmann <steinm@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pfpro
|
||||
PRIMARY MAINTAINER: David Croft <david@infotrek.co.uk>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: posix
|
||||
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: pspell
|
||||
PRIMARY MAINTAINER: Vlad Krupin <phpdevel@echospace.com>
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: readline
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: recode
|
||||
PRIMARY MAINTAINER: Kristian Köhntopp <kris@koehntopp.de>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: session
|
||||
PRIMARY MAINTAINER: Sascha Schumann <sascha@schumann.cx>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: shmop
|
||||
PRIMARY MAINTAINER: Ilia Alshanetsky <iliaa@php.net>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 4.0.3
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: snmp
|
||||
PRIMARY MAINTAINER: Rasmus Lerdorf <rasmus@php.net>
|
||||
MAINTENANCE: Odd Fixes
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sockets
|
||||
PRIMARY MAINTAINER: Chris Vandomelen <chrisv@b0rked.dhs.org>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Experimental
|
||||
SINCE: 4.0.2
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvmsg
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvsem
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: sysvshm
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: yaz
|
||||
PRIMARY MAINTAINER: Adam Dickmeiss <adam@indexdata.dk>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Unknown
|
||||
SINCE: 4.0.1
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: yp
|
||||
MAINTENANCE: Unknown
|
||||
STATUS: Unknown
|
||||
-------------------------------------------------------------------------------
|
||||
EXTENSION: zlib
|
||||
PRIMARY MAINTAINER: Stefan Roehrich <sr@linux.de>
|
||||
MAINTENANCE: Maintained
|
||||
STATUS: Working
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1,422 +0,0 @@
|
||||
Installation Instructions for PHP 5
|
||||
-----------------------------------
|
||||
|
||||
STOP!
|
||||
|
||||
Before going any further, please remember you are going to find more
|
||||
up to date instructions in the online manual, located here:
|
||||
|
||||
http://www.php.net/manual/en/install.apache.php
|
||||
|
||||
For Apache 2, instructions and up-to-date information regarding its
|
||||
support status, is available here:
|
||||
|
||||
http://www.php.net/manual/en/install.apache2.php
|
||||
|
||||
It is strongly recommended that you read the manual page before going
|
||||
further. However, for the impatient, here is a quick set of steps that
|
||||
will build PHP as (first) a dynamic Apache module (DSO) for Apache 1.3.x
|
||||
with MySQL support and then a static module. A more verbose explanation follows.
|
||||
|
||||
For installing PHP on other web servers, refer to one of the following
|
||||
files:
|
||||
|
||||
sapi/aolserver/README
|
||||
sapi/pi3web/README
|
||||
sapi/servlet/README
|
||||
sapi/thttpd/README
|
||||
README.Zeus
|
||||
|
||||
Some notes:
|
||||
|
||||
1: Only install either the static module or the dynamic one. Do not
|
||||
install both.
|
||||
|
||||
2: If you are recompiling PHP to add new extensions or upgrading
|
||||
something like GD, remove the config.cache file before you re-run
|
||||
configure.
|
||||
|
||||
3: If you are on Linux and have installed shared libraries, make
|
||||
sure the location of these shared libraries are listed in your
|
||||
/etc/ld.so.conf file. For example, if you have:
|
||||
|
||||
/usr/local/lib/mysql/libmysqlclient.so
|
||||
|
||||
Make sure /etc/ld.so.conf contains:
|
||||
|
||||
/usr/local/lib/mysql
|
||||
|
||||
Then run ldconfig.
|
||||
|
||||
If you want both PHP 3 and 4 modules in the same Apache server, check the
|
||||
bottom of this file for instructions.
|
||||
|
||||
INSTALLATION WITH THE ZEUS WEB SERVER:
|
||||
--Please see the 'README.Zeus' file included in this distribution
|
||||
|
||||
|
||||
QUICK INSTALL (DSO)
|
||||
|
||||
For this to work your Apache httpd must have mod_so enabled.
|
||||
Check using httpd -l. You should see something like:
|
||||
|
||||
Compiled-in modules:
|
||||
http_core.c
|
||||
mod_so.c
|
||||
|
||||
Chances are you will see a lot more modules than these two. That's ok,
|
||||
as long as mod_so.c shows up you can proceed with the following steps:
|
||||
|
||||
$ gunzip -c php-4.x.y.tar.gz | tar xf -
|
||||
$ cd php-4.x.y
|
||||
$ ./configure --with-mysql --with-apxs
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
If you get an error telling you that the apxs script could not be found,
|
||||
look for it on your system and if you find it, provide the full path to it
|
||||
as: --with-apxs=/path/to/apxs
|
||||
|
||||
Make sure you specify the version of apxs that is actually installed on
|
||||
your system and NOT the one that is in the apache source tarball.
|
||||
|
||||
Next you must copy php.ini-dist to the appropriate place (normally
|
||||
/usr/local/lib/php.ini) and edit it as necessary to set PHP options.
|
||||
|
||||
The only thing left to do is to edit your httpd.conf file and make sure the
|
||||
PHP 4 mime type is there and uncommented. You need a line that looks like
|
||||
this:
|
||||
|
||||
AddType application/x-httpd-php .php
|
||||
|
||||
Then restart your server (apachectl restart) and you should be able to
|
||||
serve up PHP files now. Make a test file called test.php and put some
|
||||
PHP tags in it. Like <?phpinfo()?>, for example.
|
||||
|
||||
|
||||
QUICK INSTALL (Static)
|
||||
|
||||
$ gunzip -c apache_1.3.x.tar.gz | tar xf -
|
||||
$ cd apache_1.3.x
|
||||
$ ./configure
|
||||
$ cd ..
|
||||
|
||||
$ gunzip -c php-4.x.y.tar.gz | tar xf -
|
||||
$ cd php-4.x.y
|
||||
$ ./configure --with-mysql --with-apache=../apache_1.3.x
|
||||
$ make
|
||||
$ make install
|
||||
|
||||
$ cd ../apache_1.3.x
|
||||
$ ./configure --prefix=/www --activate-module=src/modules/php5/libphp5.a
|
||||
(The above line is correct! Yes, we know libphp5.a does not exist at this
|
||||
stage. It isn't supposed to. It will be created.)
|
||||
$ make
|
||||
(you should now have an httpd binary which you can copy to your Apache bin dir if
|
||||
is is your first install then you need to "make install" as well)
|
||||
$ cd ../php-4.x.y
|
||||
$ cp php.ini-dist /usr/local/lib/php.ini
|
||||
You can edit /usr/local/lib/php.ini file to set PHP options.
|
||||
Edit your httpd.conf or srm.conf file and add:
|
||||
AddType application/x-httpd-php .php
|
||||
|
||||
|
||||
VERBOSE INSTALL
|
||||
|
||||
Chances are you are reading this because the quick install steps above
|
||||
did not work for you. If this is the case, congratulations, you are
|
||||
among the elite few that actually reads documentation. It really is
|
||||
not a difficult install and once you have done it once you will fly
|
||||
through it.
|
||||
|
||||
Installing PHP can be done in four simple steps:
|
||||
|
||||
1. Unpack your distribution file.
|
||||
|
||||
You will have downloaded a file named something like php-4.x.y.tar.gz.
|
||||
Unzip this file with a command like: gunzip php-4.x.y.tar.gz
|
||||
|
||||
Next you have to untar it with: tar -xvf php-4.x.y.tar
|
||||
|
||||
This will create a php-4.x.y directory. cd into this new directory.
|
||||
|
||||
2a. Configure PHP (Dynamic Module) - Skip to 2b if you wish to build
|
||||
a static module
|
||||
|
||||
You now have to choose the options you would like. There are quite
|
||||
a few of them. To see a list, type: ./configure --help
|
||||
|
||||
The only options that you are likely to want to use are the ones in
|
||||
the last section entitled, "--enable and --with options recognized:"
|
||||
|
||||
A popular choice is to build the Apache module version. In order to
|
||||
build PHP as a dynamic module for Apache-1.3.x you have to first have
|
||||
Apache installed. Assuming Apache is already installed, make sure
|
||||
the shared object module is enabled. To check this, type: httpd -l
|
||||
You should see something like:
|
||||
|
||||
Compiled-in modules:
|
||||
http_core.c
|
||||
mod_so.c
|
||||
|
||||
You will most likely have a lot more modules than what is shown here.
|
||||
As long as mod_so.c shows up in the list, PHP should be happy.
|
||||
|
||||
Now, type: ./configure --with-mysql --with-apxs
|
||||
|
||||
If you get an error telling you that the apxs script could not be found,
|
||||
look for it on your system and if you find it, provide the full path to it
|
||||
as: --with-apxs=/path/to/apxs
|
||||
|
||||
Make sure you specify the version of apxs that is actually installed on
|
||||
your system and NOT the one that is in the apache source tarball.
|
||||
|
||||
You might also want other flags on this configure line. --with-mysql
|
||||
is just an example.
|
||||
|
||||
There are a few things that can go wrong during this configure step.
|
||||
The most common is that you have asked for an option and that the
|
||||
configure script can not find the files required to enable this
|
||||
option in PHP. Chances are you can provide the full path to the
|
||||
base directory under which the related files were installed. For
|
||||
example, if you have installed the GD library in /opt/gd which means
|
||||
that /opt/gd/include has your GD header files and /opt/gd/lib contains
|
||||
your GD library files, you would use --with-gd=/opt/gd
|
||||
|
||||
Skip to step 3 for compilation and installation instructions.
|
||||
|
||||
2b. Configure PHP (Static Module) - Skip if you performed 2a
|
||||
|
||||
You now have to choose the options you would like. There are quite
|
||||
a few of them. To see a list, type: ./configure --help
|
||||
|
||||
The only options that you are likely to want to use are the ones in
|
||||
the last section entitled, "--enable and --with options recognized:"
|
||||
|
||||
A popular choice is to build the Apache module version. You need
|
||||
to know where the source code directory for your Apache server is
|
||||
located. Then use an option like: --with-apache=/usr/local/src/apache
|
||||
if that is your Apache source code directory. If you only specify
|
||||
--with-apache, then it will default to look for your Apache source
|
||||
in /usr/local/etc/httpd.
|
||||
|
||||
NOTE: The directory you specify should be the top-level of the
|
||||
unpacked Apache (or Stronghold) distribution. The configure program
|
||||
will automatically look for httpd.h in different directories under that
|
||||
location depending on which version of Apache, including Stronghold,
|
||||
you are running.
|
||||
|
||||
For MySQL support, since newer versions of MySQL installs its various
|
||||
components under /usr/local, this is the default. If you have
|
||||
changed the location you can specify it with: --with-mysql=/opt/local
|
||||
for example. Otherwise just use: --with-mysql
|
||||
|
||||
*NOTE* If you are using Apache 1.3b6 or later, you should run the
|
||||
Apache Configure script at least once before compiling PHP. It
|
||||
doesn't matter how you have Apache configured at this point.
|
||||
|
||||
Skip to step 3b at this point.
|
||||
|
||||
3. Compile and install the files. Simply type: make install
|
||||
|
||||
3a. Dynamic Module Installation
|
||||
|
||||
Nothing else is needed here. Proceed to step 4a.
|
||||
|
||||
3b. Static Module Installation
|
||||
|
||||
For the Apache module version this will copy the appropriate files
|
||||
to the src/modules/php5 directory in your Apache distribution if
|
||||
you are using Apache 1.3.x. If you are still running Apache 1.2.x
|
||||
these files will be copied directly to the main src directory.
|
||||
|
||||
For Apache 1.3b6 and later, you can use the new APACI configuration
|
||||
mechanism. To automatically build Apache with PHP support, use:
|
||||
|
||||
cd apache_1.3.x
|
||||
./configure --prefix=/<path>/apache \
|
||||
--activate-module=src/modules/php5/libphp5.a
|
||||
make
|
||||
make install
|
||||
|
||||
If you do not wish to use this new configuration tool, the old
|
||||
install procedure (src/Configure) will work fine.
|
||||
|
||||
If you are using the old Apache ./Configure script, you will have to
|
||||
edit the Apache src/Configuration file manually. If you do not have
|
||||
this file, copy Configuration.tmpl to Configuration.
|
||||
|
||||
For Apache 1.3.x add:
|
||||
|
||||
AddModule modules/php5/libphp5.a
|
||||
|
||||
For Apache 1.3.x don't do anything else. Just add this line and then
|
||||
run "./Configure" followed by "make".
|
||||
|
||||
For Apache 1.2.x add:
|
||||
|
||||
Module php5_module mod_php5.o
|
||||
|
||||
For Apache 1.2.x you will also have to look in the libphp5.module file,
|
||||
which was copied to the src directory. The EXTRA_LIBS line in the Apache
|
||||
Configuration file needs to be set to use the same libs as specified on
|
||||
the LIBS line in libphp5.module. You also need to make sure to add
|
||||
"-L." to the beginning of the EXTRA_LIBS line.
|
||||
|
||||
So, as an example, your EXTRA_LIBS line might look like:
|
||||
|
||||
EXTRA_LIBS=-L. -lphp5 -lgdbm -ldb -L/usr/local/mysql/lib -lmysqlclient
|
||||
|
||||
NOTE: You should not enclose the EXTRA_LIBS line in double-quotes, as it
|
||||
is in the libphp5.module file.
|
||||
|
||||
Also, look at the RULE_WANTHSREGEX setting in the libphp5.module file
|
||||
and set the WANTHSREGEX directive accordingly in your Configuration file.
|
||||
This last step applies to versions of Apache prior to 1.3b3.
|
||||
|
||||
This is a bit of a hassle, but should serve as incentive to move to
|
||||
Apache 1.3.x where this step has been eliminated.
|
||||
|
||||
Once you are satisfied with your Configuration settings, type: ./Configure
|
||||
If you get errors, chances are that you forgot a library or made a typo
|
||||
somewhere. Re-edit Configuration and try again. If it goes well,
|
||||
type: make
|
||||
|
||||
Assuming it compiles without errors, proceed to step 4b.
|
||||
|
||||
4a. Setting up the server. (Dynamic Module)
|
||||
|
||||
The make install command in step 3 should have done most of your
|
||||
work for you. It actually edits your httpd.conf file and tries to
|
||||
enable the dynamic PHP module. To verify this, look for a line that
|
||||
looks like this:
|
||||
|
||||
LoadModule php5_module libexec/libphp5.so
|
||||
|
||||
The actual path before the libphp5.so part might differ slightly. This
|
||||
is likely fine. If you are paranoid you can examine the output from the
|
||||
make install step to see where the libphp5.so file was actually put and
|
||||
place the full path to this file on this LoadModule line.
|
||||
|
||||
If somewhere in your httpd.conf file you have a ClearModuleList line
|
||||
then you also need this line:
|
||||
|
||||
AddModule mod_php5.c
|
||||
|
||||
And finally you need to tell Apache which file extension should trigger
|
||||
PHP. You do this by creating a special mime type and associating it
|
||||
with an extension. We suggest using:
|
||||
|
||||
AddType application/x-httpd-php .php
|
||||
|
||||
You are however free to use any extension you wish, including .html.
|
||||
|
||||
Note! If a line has a # at the beginning, then it is commented out
|
||||
and you need to remove the # for that line to take effect.
|
||||
|
||||
Finally you need to copy php.ini-dist to the appropriate place
|
||||
(normally /usr/local/lib/php.ini) and edit if necessary.
|
||||
|
||||
Once you have made these changes you should be ready to restart your
|
||||
server and try it out. Type: apachectl restart
|
||||
|
||||
4b. Setting up the server. (Static Module)
|
||||
|
||||
You should now have a new httpd binary. Shut down your existing server,
|
||||
if you have one, and copy this new binary overtop of it. Perhaps make
|
||||
a backup of your previous one first. Then edit your conf/httpd.conf file
|
||||
and add the line:
|
||||
|
||||
AddType application/x-httpd-php .php
|
||||
|
||||
There is also an interesting feature which can be quite instructive and
|
||||
helpful while debugging. That is the option of having colour syntax
|
||||
highlighting. To enable this, add the following line:
|
||||
|
||||
AddType application/x-httpd-php-source .phps
|
||||
|
||||
Any file ending in .phps will now be displayed with full colour syntax
|
||||
highlighting instead of being executed.
|
||||
|
||||
Note that on some older server setups, the AddType lines are in the
|
||||
conf/srm.conf file instead of conf/httpd.conf.
|
||||
|
||||
Note! If a line has a # at the beginning, then it is commented out
|
||||
and you need to remove the # for that line to take effect.
|
||||
|
||||
When you are finished making changes to your httpd.conf file, you need
|
||||
to copy php.ini-dist to the appropriate place (normally
|
||||
/usr/local/lib/php.ini) and edit if necessary. You can then
|
||||
start up your server.
|
||||
|
||||
5. Testing it all worked
|
||||
|
||||
Create a test file named test.php in your web tree somewhere and
|
||||
put some test PHP tags in it. <?phpinfo()?> is a good first test.
|
||||
This tag tells PHP to do a braindump and tells you all sorts of things
|
||||
about itself.
|
||||
|
||||
|
||||
WHY DISABLING -fPIC WORKS ON LINUX
|
||||
|
||||
From: Martin v. Loewis <martin@loewis.home.cs.tu-berlin.de>
|
||||
To: glibc-linux@ricardo.ecn.wfu.edu
|
||||
Subject: Re: Shared library -shared vs. -fpic
|
||||
|
||||
[In reply to Kaz Kylheku <kaz@ashi.footprints.net>]
|
||||
|
||||
> PIC stands for Position-Independent Code.
|
||||
|
||||
Correct.
|
||||
|
||||
> Code isn't position-independent (or ``relocatable'') cannot be
|
||||
> loaded at an arbitrary address;
|
||||
|
||||
Wrong.
|
||||
|
||||
> it requires some references to be patched at load time.
|
||||
|
||||
Correct.
|
||||
|
||||
> Shared libraries need to be relocatable because it's not known
|
||||
> beforehand what address they will be loaded at
|
||||
|
||||
Correct, depending on the meaning of "relocatable". PIC code typically
|
||||
does not contain relocations; that's why its position-independent.
|
||||
|
||||
> Just because you don't specify -fPIC doesn't mean that the compiler
|
||||
> won't emit position-independent code; the option prevents it from
|
||||
> emitting position-dependent code in situations where it otherwise
|
||||
> would.
|
||||
|
||||
Correct. However, a non-trivial shared library typically won't be
|
||||
position-independent unless explicitly compiled with
|
||||
-fPIC. Linux/glibc indeed does not require a shared library to be
|
||||
position-independent; instead, it will perform the relocations in the
|
||||
binary, even if they refer to code pages. As a result, those relocated
|
||||
pages won't be shared across processes, anymore.
|
||||
|
||||
Regards,
|
||||
Martin
|
||||
|
||||
USING PHP 3 AND PHP 4 AS CONCURRENT APACHE MODULES
|
||||
|
||||
With some (newer) installations of Apache, it's possible to compile both
|
||||
PHP 3 and PHP 4, and run them concurrently.
|
||||
|
||||
Note, it's only really wise to do this if you need to use the PHP 3 engine
|
||||
to maintain backwards compatibility.
|
||||
|
||||
To enable it, configure PHP 3 and PHP 4 to use APXS (--with-apxs) and the
|
||||
necessary link extensions (--enable-versioning). Otherwise, all standard
|
||||
installations instructions apply. For example:
|
||||
|
||||
$ ./configure \
|
||||
--with-apxs=/apache/bin/apxs \
|
||||
--enable-versioning \
|
||||
--with-mysql \
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
--------------------------------------------------------------------
|
||||
The PHP License, Version 3.0
|
||||
Copyright (c) 1999 - 2003 The PHP Group. All rights reserved.
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, is permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
3. The name "PHP" must not be used to endorse or promote products
|
||||
derived from this software without prior written permission. For
|
||||
written permission, please contact group@php.net.
|
||||
|
||||
4. Products derived from this software may not be called "PHP", nor
|
||||
may "PHP" appear in their name, without prior written permission
|
||||
from group@php.net. You may indicate that your software works in
|
||||
conjunction with PHP by saying "Foo for PHP" instead of calling
|
||||
it "PHP Foo" or "phpfoo"
|
||||
|
||||
5. The PHP Group may publish revised and/or new versions of the
|
||||
license from time to time. Each version will be given a
|
||||
distinguishing version number.
|
||||
Once covered code has been published under a particular version
|
||||
of the license, you may always continue to use it under the terms
|
||||
of that version. You may also choose to use such covered code
|
||||
under the terms of any subsequent version of the license
|
||||
published by the PHP Group. No one other than the PHP Group has
|
||||
the right to modify the terms applicable to covered code created
|
||||
under this License.
|
||||
|
||||
6. Redistributions of any form whatsoever must retain the following
|
||||
acknowledgment:
|
||||
"This product includes PHP, freely available from
|
||||
<http://www.php.net/>".
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
|
||||
ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
|
||||
DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
--------------------------------------------------------------------
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals on behalf of the PHP Group.
|
||||
|
||||
The PHP Group can be contacted via Email at group@php.net.
|
||||
|
||||
For more information on the PHP Group and the PHP project,
|
||||
please see <http://www.php.net>.
|
||||
|
||||
This product includes the Zend Engine, freely available at
|
||||
<http://www.zend.com>.
|
||||
@@ -1,23 +0,0 @@
|
||||
|
||||
#
|
||||
# Zend
|
||||
#
|
||||
|
||||
$(builddir)/zend_language_scanner.lo: $(builddir)/zend_language_parser.h
|
||||
$(builddir)/zend_ini_scanner.lo: $(builddir)/zend_ini_parser.h
|
||||
|
||||
$(builddir)/zend_language_scanner.c: $(srcdir)/zend_language_scanner.l
|
||||
$(LEX) -Pzend -S$(srcdir)/flex.skl -o$@ -i $(srcdir)/zend_language_scanner.l
|
||||
|
||||
$(builddir)/zend_language_parser.h: $(builddir)/zend_language_parser.c
|
||||
$(builddir)/zend_language_parser.c: $(srcdir)/zend_language_parser.y
|
||||
$(YACC) -p zend -v -d $(srcdir)/zend_language_parser.y -o $@
|
||||
|
||||
$(builddir)/zend_ini_parser.h: $(builddir)/zend_ini_parser.c
|
||||
$(builddir)/zend_ini_parser.c: $(srcdir)/zend_ini_parser.y
|
||||
$(YACC) -p ini_ -v -d $(srcdir)/zend_ini_parser.y -o $@
|
||||
|
||||
$(builddir)/zend_ini_scanner.c: $(srcdir)/zend_ini_scanner.l
|
||||
$(LEX) -Pini_ -S$(srcdir)/flex.skl -o$@ -i $(srcdir)/zend_ini_scanner.l
|
||||
|
||||
$(builddir)/zend_indent.lo $(builddir)/zend_highlight.lo $(builddir)/zend_compile.lo: $(builddir)/zend_language_parser.h
|
||||
@@ -1,76 +0,0 @@
|
||||
mkinstalldirs = $(top_srcdir)/build/shtool mkdir -p
|
||||
INSTALL = $(top_srcdir)/build/shtool install -c
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
|
||||
DEFS = -DPHP_ATOM_INC -I$(top_builddir)/include -I$(top_builddir)/main -I$(top_srcdir)
|
||||
COMMON_FLAGS = $(DEFS) $(INCLUDES) $(EXTRA_INCLUDES) $(CPPFLAGS) $(PHP_FRAMEWORKPATH)
|
||||
|
||||
|
||||
all: $(all_targets)
|
||||
@echo
|
||||
@echo "Build complete."
|
||||
@echo "(It is safe to ignore warnings about tempnam and tmpnam)."
|
||||
@echo
|
||||
|
||||
build-modules: $(PHP_MODULES)
|
||||
|
||||
libphp5.la: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -rpath $(phptempdir) $(EXTRA_LDFLAGS) $(LDFLAGS) $(PHP_RPATHS) $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@
|
||||
-@$(LIBTOOL) --silent --mode=install cp libphp5.la $(phptempdir)/libphp5.la >/dev/null 2>&1
|
||||
|
||||
libs/libphp5.bundle: $(PHP_GLOBAL_OBJS) $(PHP_SAPI_OBJS)
|
||||
$(CC) $(MH_BUNDLE_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(PHP_GLOBAL_OBJS:.lo=.o) $(PHP_SAPI_OBJS:.lo=.o) $(PHP_FRAMEWORKS) $(EXTRA_LIBS) $(ZEND_EXTRA_LIBS) -o $@ && cp $@ libs/libphp5.so
|
||||
|
||||
install: $(all_targets) $(install_targets)
|
||||
|
||||
install-sapi: $(OVERALL_TARGET)
|
||||
@echo "Installing PHP SAPI module: $(PHP_SAPI)"
|
||||
-@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
|
||||
-@if test ! -r $(phptempdir)/libphp5.$(SHLIB_SUFFIX_NAME); then \
|
||||
for i in 0.0.0 0.0 0; do \
|
||||
if test -r $(phptempdir)/libphp5.$(SHLIB_SUFFIX_NAME).$$i; then \
|
||||
$(LN_S) $(phptempdir)/libphp5.$(SHLIB_SUFFIX_NAME).$$i $(phptempdir)/libphp5.$(SHLIB_SUFFIX_NAME); \
|
||||
break; \
|
||||
fi; \
|
||||
done; \
|
||||
fi
|
||||
@$(INSTALL_IT)
|
||||
|
||||
install-modules: build-modules
|
||||
@test -d modules && \
|
||||
$(mkinstalldirs) $(INSTALL_ROOT)$(EXTENSION_DIR)
|
||||
@echo "Installing shared extensions: $(INSTALL_ROOT)$(EXTENSION_DIR)/"
|
||||
@rm -f modules/*.la >/dev/null 2>&1
|
||||
@$(INSTALL) modules/* $(INSTALL_ROOT)$(EXTENSION_DIR)
|
||||
|
||||
install-tester:
|
||||
@echo "Installing regression tester: $(INSTALL_ROOT)$(PEAR_INSTALLDIR)/"
|
||||
@$(mkinstalldirs) $(INSTALL_ROOT)$(PEAR_INSTALLDIR)
|
||||
@$(INSTALL) -m 755 $(top_srcdir)/run-tests.php $(INSTALL_ROOT)$(PEAR_INSTALLDIR)
|
||||
|
||||
install-su: install-pear install-tester
|
||||
|
||||
test:
|
||||
-@if test -x $(SAPI_CLI_PATH) && test ! -z $(SAPI_CLI_PATH); then \
|
||||
TEST_PHP_EXECUTABLE=$(top_builddir)/$(SAPI_CLI_PATH) \
|
||||
TEST_PHP_SRCDIR=$(top_srcdir) \
|
||||
CC="$(CC)" \
|
||||
$(top_builddir)/$(SAPI_CLI_PATH) -d 'open_basedir=' -d 'safe_mode=0' -d 'output_buffering=0' $(top_srcdir)/run-tests.php $(TESTS); \
|
||||
else \
|
||||
echo "ERROR: Cannot run tests without CLI sapi."; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
find . -name \*.lo -o -name \*.o | xargs rm -f
|
||||
find . -name \*.la -o -name \*.a | xargs rm -f
|
||||
find . -name \*.so | xargs rm -f
|
||||
find . -name .libs -a -type d|xargs rm -rf
|
||||
rm -f libphp5.la $(SAPI_CLI_PATH) $(OVERALL_TARGET) modules/* libs/*
|
||||
|
||||
distclean: clean
|
||||
rm -f config.cache config.log config.status Makefile.objects Makefile.fragments libtool main/php_config.h stamp-h php5.spec sapi/apache/libphp5.module buildmk.stamp
|
||||
egrep define'.*include/php' configure|sed 's/.*>//'|xargs rm -f
|
||||
find . -name Makefile | xargs rm -f
|
||||
|
||||
.PHONY: all clean install distclean test
|
||||
.NOEXPORT:
|
||||
@@ -1,537 +0,0 @@
|
||||
PHP NEWS
|
||||
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||
?? ??? 2004, PHP 5.0.1
|
||||
- Fixed bug #28829 (Thread-unsafety in bcmath elementary values). (Sara)
|
||||
|
||||
13 Jul 2004, PHP 5.0.0
|
||||
- Updated PCRE to provide better error handling in certain cases. (Andrei)
|
||||
- Changed doc comments to require a single white space after '/**'. (Marcus)
|
||||
- Fixed bug #29019 (Database not closing). (Marcus)
|
||||
- Fixed bug #29008 (array_combine() does not handle non-numeric/string keys).
|
||||
(Ilia)
|
||||
- Fixed bug #28999 (fixed behaviour of exec() to work as it did in 4.X). (Ilia)
|
||||
- Fixed bug #28895 (ReflectionClass::isAbstract always returns false). (Marcus)
|
||||
- Fixed bug #28868 (Internal filter registry not thread safe). (Sara)
|
||||
- Fixed bug #28851 (call_user_func_array has typo in error message). (Marcus)
|
||||
- Fixed bug #28831 (ArrayObject::offsetGet() does the work of offsetUnset()).
|
||||
(Marcus)
|
||||
- Fixed bug #28822 (ArrayObject::offsetExists() works inverted). (Marcus)
|
||||
- Fixed bug #28789 (ReflectionProperty getValue() fails on public static
|
||||
members). (Marcus)
|
||||
- Fixed bug #28771 (Segfault when using xslt and clone). (Rob)
|
||||
- Fixed bug #28751 (SoapServer does not call _autoload()). (Dmitry)
|
||||
- Fixed bug #28739 (array_*diff() and array_*intersect() not clearing the fci
|
||||
cache before work). (Andrey)
|
||||
- Fixed bug #28721 (appendChild() and insertBefore() unset DOMText).(Rob)
|
||||
- Fixed bug #28702 (SOAP does not parse WSDL service address correctly). (Dmitry)
|
||||
- Fixed bug #28699 (Reflection api bugs). (Marcus)
|
||||
- Fixed bug #28694 (ReflectionExtension::getFunctions() crashes PHP). (Marcus)
|
||||
- Fixed bug #28512 (Allocate enough space to store MSSQL data). (Frank)
|
||||
- Fixed bug #28325 (Circular references not properly serialised). (Moriyoshi)
|
||||
- Fixed strip_tags() to correctly handle '\0' characters. (Stefan)
|
||||
|
||||
7 Jun 2004, PHP 5 Release Candidate 3
|
||||
- Moved the PDFLib extension to PECL. (Wez)
|
||||
- Added MySQL 4.1.2-alpha and 4.1.3-beta support to MySQLI extension. (Georg)
|
||||
- Added support for dumping private/protected properties to var_dump().
|
||||
(Andrey)
|
||||
- Added count() support for COM arrays. (Wez)
|
||||
- Added Firebird/InterBase UDF source that allows PHP functions to be called
|
||||
from SQL (Ard)
|
||||
- Removed Firebird/Interbase function ibase_timefmt() (Ard)
|
||||
- Changed user error handler mechanism to relay to built-in error handler if it
|
||||
returns false. (Andrei)
|
||||
- Changed class type hints for function parameters to not allow the passing of
|
||||
NULL values. (Andi)
|
||||
- Changed tidy_node to tidyNode and removed tidy_exception. (John)
|
||||
- Fixed ip2long() to return FALSE if an IP address passed to this function
|
||||
is not valid. (Derick)
|
||||
- Fixed memory leak in memory manager. (Andi)
|
||||
- Fixed problem with exceptions returning from include(). (Dmitry)
|
||||
- Fixed bug #28641 (Instance of Interface). (Marcus)
|
||||
- Fixed bug #28430 (Extending mysqli class). (Georg)
|
||||
- Fixed bug #28311 (Transparency detection code is off by 1).
|
||||
(Ilia, pikeman at pikeman dot sytes dot net)
|
||||
- Fixed bug #28304 (Missing bounds check inside imagefilter()). (Ilia)
|
||||
- Fixed bug #28300 (Userspace stream/filter names forced to lowercase). (Sara)
|
||||
- Fixed bug #28287 (stream_*_register() not calling __autoload()). (Sara)
|
||||
- Fixed bug #28267 (php_image_filter_contrast calls gdImageBrightness). (Ilia)
|
||||
- Fixed bug #28239 (No results returned on SOAP call, no error given). (Dmitry)
|
||||
- Fixed bug #28205 (num_rows property for statement object). (Georg)
|
||||
- Fixed bug #28161 (COM: Array style properties could not be accessed). (Wez)
|
||||
- Fixed bug #28125 (ArrayObject leaks when accessing elements). (Marcus)
|
||||
- Fixed bug #28100 (NULL parameter support for mysqli_ssl_set). (Georg)
|
||||
- Fixed bug #28099 (ArrayObject doesn't implement ArrayAccess). (Marcus)
|
||||
- Fixed bug #27929 (SPL: change visibility of ArrayIterator::__construct).
|
||||
(Marcus)
|
||||
- Fixed bug #27640 (memory leak of registered_zend_ini_directives). (Dmitry)
|
||||
- Fixed bug #27063 (SPL: ArrayObject does not handle PPP correctly). (Marcus)
|
||||
|
||||
25 Apr 2004, PHP 5 Release Candidate 2
|
||||
- Implementing an interface/abstract method with the wrong prototype is now
|
||||
a fatal error. (Zeev)
|
||||
- Reimplemented zend.ze1_compatibility_mode to have better PHP 4 compliance.
|
||||
(Dmitry, Andi)
|
||||
- Under CLI, fclose() on php://stdin, php://stdout and php://stderr will now
|
||||
close the real stream. Please update your CLI scripts to use STDIN, STDOUT
|
||||
and STDERR constants instead of fopen()/fclose(). (Wez)
|
||||
- Moved yaz extension to PECL. (Wez)
|
||||
- Added pty support to proc_open(). (Wez)
|
||||
- Added possibility to check in which extension an internal class was defined
|
||||
in using reflection API. (Marcus)
|
||||
- Changed tidy error handling to no longer use exceptions and
|
||||
renamed the "error_buf" property to errorBuffer. (John)
|
||||
- Changed class and method names to use studlyCaps convention. (Marcus)
|
||||
- Changed language parser to throw errors when a non-empty signature is used in
|
||||
a destructor definition. (Marcus)
|
||||
- Changed HTTP file uploads not to throw E_WARNINGs and E_NOTICEs. The error
|
||||
value in the $_FILES global should be used for error handling. (Derick)
|
||||
- Changed __construct() to always take precedence over old style constructor.
|
||||
(Dmitry)
|
||||
- Fixed handling of return values from storred procedures in mssql_execute()
|
||||
with multiple result sets returned. (Frank)
|
||||
- Fixed bug #28096 (stream_socket_accept() doesn't work with ssl). (Wez)
|
||||
- Fixed bug #28007 (compile mssql extension with old versions of FreeTDS
|
||||
fails). (Frank)
|
||||
- Fixed bug #27997 (SPL: Crash with getInnerIterator()). (Marcus)
|
||||
- Fixed bug #27974 (COM doesn't pass array parameters). (Wez)
|
||||
- Fixed bug #27928 (sqlite incorrectly handles invalid filenames). (Ilia)
|
||||
- Fixed bug $27923 (in some cases using foreach() to iterate over values
|
||||
led to a false error message about the key being a reference). (Adam)
|
||||
- Fixed bug #27865 (STDIN, STDOUT, STDERR are dup()d under CLI). (Wez)
|
||||
- Fixed bug #27821 (xml_parse() segfaults when xml_set_object() is called from
|
||||
class method). (Andi, Rob)
|
||||
- Fixed bug #27742 (WDSL SOAP Parsing Schema bug). (Dmitry)
|
||||
- Fixed bug #27722 (Segfault on schema without targetNamespace). (Dmitry)
|
||||
- Fixed bug #27719 (mktime issues on and around DST changeover). (Rasmus)
|
||||
- Fixed bug #27681 (soap extension fails without HAVE_TM_GMTOFF). (Dmitry)
|
||||
- Fixed bug #27641 (Object cloning in ze1_compatibility_mode was reimplemented)
|
||||
(Dmitry, Andi)
|
||||
- Fixed bug #27628 (Simplify the process of making a POST request via stream
|
||||
context). (Ilia)
|
||||
- Fixed bug #27619 (filters not applied to pre-buffered stream data). (Sara)
|
||||
- Fixed bug #27519 (Reflection_Function constructor crashes with non-existant
|
||||
function's name). (Marcus)
|
||||
- Fixed bug #27469 (serialize() objects of incomplete class). (Dmitry)
|
||||
- Fixed bug #27457 (handling of numeric indexes in strtr()). (Dmitry)
|
||||
- Fixed bug #27397 (debug_backtrace() not showing function arguments). (Zeev)
|
||||
- Fixed bug #27283 (The last catch statement was sometimes skipped). (Andi)
|
||||
- Fixed bug #26441 (When __set() returned a value it corrupted it). (Andi)
|
||||
- Fixed bug #19749 (shouldn't mmap() files larger than memory_limit). (Wez)
|
||||
|
||||
18 March 2004, PHP 5 Release Candidate 1
|
||||
- Fixed numerous bugs with the just-in-time auto-global initialization, that
|
||||
could cause $_SERVER, $argv/$argc and other variables not to work properly.
|
||||
(Zeev)
|
||||
- Fixed data corruption with constant assignments to object properties. (Zeev)
|
||||
- Changed __toString() to be called automatically only with print and echo
|
||||
statements. (Andi)
|
||||
- Replaced the exec_finished hook by the zend_post_deactive hook for
|
||||
extensions. The new hook will be run after the symbol table and destructors
|
||||
are run. (Derick)
|
||||
- Fixed possible crash when internal get_method() is not defined. (Andi)
|
||||
- Fixed calling methods using call_user_func() in conjunction with
|
||||
the array("Class","Method") syntax to use the scope of the PHP user function.
|
||||
(Dmitry)
|
||||
- Fixed php-cgi to not ignore command-line switches when run in a web context.
|
||||
This fixes our test cases allowing INI with GET sections to work. (Rasmus)
|
||||
- Fixed getopt() so it works without $_SERVER. (Rasmus, bfrance)
|
||||
- Added support for PHP 4 style object comparisons which is enabled in
|
||||
ze1_compatiblity_mode. (Andi)
|
||||
- Added support for PHP 4 style object conversion to long, double, and boolean
|
||||
values which is enabled in ze1_compatibility_mode. (Andi, Stas)
|
||||
- Allow object oriented extensions to overload comparison functions and other
|
||||
operations. Solves problems using SimpleXML values. (Andi, Zeev)
|
||||
- Fixed crash when accessing a class constant with a value which in turn is
|
||||
also a constant. (Dmitry)
|
||||
- Fixed object's truth value conversion. It is always true unless
|
||||
ze1_compatibility_mode is on in which it behaves like in PHP 4. (Stas)
|
||||
- Improved out of memory handling in new memory manager. (Stas)
|
||||
- Fixed crash when an object references itself during destructor call. (Andi)
|
||||
- Fixed crash in foreach() when iterating over object properties or a method's
|
||||
return values. (Andi)
|
||||
- Fixed crash when an exception is thrown in a destructor. Such exceptions are
|
||||
now ignored as destruction happens out of context at no definite time. (Andi)
|
||||
- Fixed crashes in exception handling. (Dmitry, Andi)
|
||||
- Changed prototype checks so that they aren't done on constructors. (Andi)
|
||||
- Changed prototype checks to output an E_STRICT message instead of
|
||||
an E_COMPILE_ERROR. (Andi)
|
||||
- Changed Iterator::has_more() to Iterator::valid(). (Marcus)
|
||||
- Upgraded bundled oniguruma library to version 2.2.2. (Rui, Moriyoshi)
|
||||
- Added mb_list_encoding() to return an array with all mbstring supported
|
||||
encodings. (Derick)
|
||||
- Added support for more ISO8601 datetime formats in strtotime(). (Moriyoshi)
|
||||
. Timezone specifier (ex. "20040301T02:00:00+19:00")
|
||||
. Week specifier (ex. "1997W021")
|
||||
- Renamed php.ini option "zend2.implicit_clone" to
|
||||
"zend.ze1_compatibility_mode" as it doesn't only affect implicit cloning.
|
||||
(Andi, Zeev)
|
||||
- Methods that override parent methods are now subject to prototype checking,
|
||||
and have to be compatible with the method they're overriding - this check is
|
||||
disabled in compatibility mode. (Andi, Zeev)
|
||||
- Fixed crash in php_ini_scanned_files() when no additional INI files were
|
||||
actually parsed. (Jon)
|
||||
- Fixed bug in gdImageFilledRectangle in the bundled GD library, that required
|
||||
x1 < x2 and y1 < y2 for coordinates. (Derick)
|
||||
- Fixed crash with foreach() and temporary objects($obj->method()->a ...) where
|
||||
method returns a non-referenced object. (Andi, Zeev)
|
||||
- Fixed problem preventing startup errors from being displayed. (Marcus)
|
||||
- Fixed start-up problem if both SPL and SimpleXML were enabled. The double
|
||||
initialization of apache 1.3 was causing problems here. (Marcus, Derick)
|
||||
- Fixed bug #27606 (Expression must be a modifiable lvalue compiler error).
|
||||
(Derick)
|
||||
- Fixed bug #27597 (pg_fetch_array not returning false). (Marcus)
|
||||
- Fixed bug #27586 (ArrayObject::getIterator crashes with [] assignment).
|
||||
(Marcus)
|
||||
- Fixed bug #27537 (Objects pointing to each other segfaults). (Dmitry)
|
||||
- Fixed bug #27535 (Problem with object freeing mechanism). (Dmitry)
|
||||
- Fixed bug #27504 (Visibility bugs in call_user_function()). (Dmitry)
|
||||
- Fixed bug #27338 (memory leak inside tsrm_virtual_cwd.c on win32). (Ilia)
|
||||
- Fixed bug #27291 (get_browser matches browscap.ini patterns incorrectly).
|
||||
(Jay)
|
||||
- Fixed bug #27287 (wddx segfaults during deserialization). (Moriyoshi)
|
||||
- Fixed bug #27263 (session extension crashes when unserializing referenced
|
||||
values / objects). (Moriyoshi)
|
||||
- Fixed bug #27237 (Working with simplexml crashes apache2). (Rob)
|
||||
- Fixed bug #27227 (Mixed case class names causes Fatal Error in Constructor
|
||||
call). (Marcus)
|
||||
- Fixed bug #27125 (strval() doesn't work for objects with __toString()).
|
||||
(Marcus)
|
||||
- Fixed bug #27123 (Fix crash caused by bug in get_object_vars()). (Andi)
|
||||
- Fixed bug #26677 (mbstring compile errors with IRIX compiler).
|
||||
(K.Kosako <kosako at sofnec dot co dot jp>, Rui, Moriyoshi)
|
||||
- Fixed bug #26206 (register_long_arrays breaks superglobals). (Zeev)
|
||||
- Fixed bug #25724 (argv and argc not defined). (Zeev)
|
||||
|
||||
12 Feb 2004, PHP 5 Beta 4
|
||||
- Changed exceptions so that they must now inherit from the built-in Exception
|
||||
class. This allows for a general catch(Exception $e) statement to catch all
|
||||
exceptions. (Andi, Zeev)
|
||||
- Added SPL extension. (Marcus, Derick)
|
||||
- Added checks for invalid characters in a cookie name and cookie data
|
||||
into set[raw]cookie(). (Brian)
|
||||
- Added support for ++ and += (and similar) to SimpleXML. (Andi, Zeev)
|
||||
- Added infrastructure for ++ and += (and similar) to object overloading
|
||||
modules. (Andi, Zeev)
|
||||
- Added error message when trying to re-assign to $this variable. (Zeev, Andi)
|
||||
- Added support for an interface to extend another interface. (Zeev)
|
||||
- Added new pspell functions: (Brian)
|
||||
. pspell_config_dict_dir()
|
||||
. pspell_config_data_dir()
|
||||
- Added new Interbase functions: (Ard)
|
||||
. ibase_service_attach() and ibase_service_detach().
|
||||
. ibase_backup() and ibase_restore().
|
||||
. ibase_maintain_db(), ibase_db_info() and ibase_server_info().
|
||||
- Added context option "http"/"request_fulluri" to send entire URI in request
|
||||
which is required format for some proxies. (Sara)
|
||||
- Added optional third parameter 'strict' to array_keys(). (Andrey)
|
||||
- Added stream_lock() method to userspace streams interface. (Hartmut, Wez)
|
||||
- Added xsltprocessor->registerPHPFunctions(). (Christian)
|
||||
- Readded support for using classes before they are declared according to
|
||||
the behavior in PHP 4. This won't work with classes who are using PHP 5
|
||||
features such as interfaces. (Zeev, Andi)
|
||||
- Completely overhauled SimpleXML extension. (Marcus, Rob, Sterling)
|
||||
- Upgraded bundled SQLite library to version 2.8.11. (Ilia, Wez)
|
||||
- Improved destructor implementation to always call destructors on clean
|
||||
shutdown. An order of destruction is not guaranteed. (Zeev, Andi)
|
||||
- Redesigned exception support. This fixes many bugs in the previous design
|
||||
such as nested try's and problems with overloaded extensions. (Zeev, Andi)
|
||||
- Redesigned clone by adding a clone keyword (clone $obj) and copying all
|
||||
properties before __clone() is called. Also allows calling parent __clone
|
||||
function by using parent::__clone(). (Zeev, Andi)
|
||||
- Fixed interfaces to check for function return-by-reference equality when
|
||||
inheriting and implementing interfaces. (Andi, Zeev)
|
||||
- Fixed foreach() to respect property visibility. (Marcus)
|
||||
- Fixed problem with parse error in include() file not stopping PHP's
|
||||
execution. (Ilia)
|
||||
- Fixed var_export() to show public, protected and private modifiers properly.
|
||||
(Derick)
|
||||
- Fixed problems with longlong values in mysqli. (Georg)
|
||||
- Fixed class name case preserving of user defined classes. (Marcus)
|
||||
- Fixed bug #27145 (Unmangle private/protected property names before printing
|
||||
them inside error messages). (Ilia)
|
||||
- Fixed bug #27103 (preg_split('//u') incorrectly splits UTF-8 strings into
|
||||
octets). (Moriyoshi)
|
||||
- Fixed bug #27042 (SPL: SeekableIterator seek() broken). (Marcus)
|
||||
- Fixed bug #27008 (Every class method can be called as static). (Marcus)
|
||||
- Fixed bug #26938 (exec() has problems reading long lines).
|
||||
(Ilia, runekl[at]opoint[dot]com
|
||||
- Fixed bug #26947 (ext/dom: Crash when using DomDocument::getElementById()).
|
||||
(Christian)
|
||||
- Fixed bug #26911 (crash in sqlite extension when fetching data from empty
|
||||
queries). (Ilia)
|
||||
- Fixed bug #26844 (ext/mime_magic: magic file validation broken). (Jani)
|
||||
- Fixed bug #26819 (http_build_query() crashes on NULL output). (Ilia)
|
||||
- Fixed bug #26817 (http_build_query() does not handle private & protected
|
||||
object properties correctly). (Ilia)
|
||||
- Fixed bug #26815 (foreach of (DOM) childnodes crashes when Xinclude is used).
|
||||
(Rob)
|
||||
- Fixed bug #26796 (SQLite causes crashes with other extensions *connect()
|
||||
calls). (Marcus)
|
||||
- Fixed bug #26762 (unserialize() produces lowercase classnames). (Marcus)
|
||||
- Fixed bug #26743 (getElementsByTagName doesn't work properly). (Rob)
|
||||
- Fixed bug #26736 (__autoload not invoked for parent classes). (Marcus)
|
||||
- Fixed bug #26723 (domNode::appendChild() changes child node namespace). (Rob)
|
||||
- Fixed bug #26697 (calling class_exists() on a nonexistent class in __autoload
|
||||
results in segfault). (Marcus)
|
||||
- Fixed bug #26696 (string index in a switch() crashes with multiple matches).
|
||||
(Andi)
|
||||
- Fixed bug #26695 (Reflection API does not recognize mixed-case class hints).
|
||||
(Marcus)
|
||||
- Fixed bug #26690 (make xsltProcessor->transformToUri use streams wrappers).
|
||||
(Ilia)
|
||||
- Fixed bug #26680 (Added version check in mysqli_report_index). (Georg)
|
||||
- Fixed bug #26675 (Segfault on ArrayAccess use). (Marcus)
|
||||
- Fixed bug #26640 (__autoload() not invoked by Reflection classes). (Jani)
|
||||
- Fixed bug #26543 (call_user_func() broken for self, parent). (Stanislav)
|
||||
- Fixed bug #26077 (memory leak when new() result is not assigned and no
|
||||
constructor is defined). (Stanislav)
|
||||
- Fixed bug #26065 (Crash when nesting classes). (Marcus)
|
||||
- Fixed bug #25816 (disallow arrays in class constants). (Stanislav)
|
||||
- Fixed bug #25329 (sqlite_create_function with method and reference to $this).
|
||||
(Marcus)
|
||||
- Fixed bug #25038 (call_user_func() issues a warning if function throws an
|
||||
exception). (Marcus)
|
||||
- Fixed bug #24608 (__set not triggered when overloading with array).
|
||||
(Stanislav)
|
||||
- Fixed bug #24243 (enabling browscap causes segfault). (Wez)
|
||||
|
||||
21 Dec 2003, PHP 5 Beta 3
|
||||
- Bundled new tidy extension (John, Wez)
|
||||
- Upgraded PCRE library to version 4.5. (Andrei)
|
||||
- Dropped Windows 95 support. (Andi)
|
||||
- Moved extensions to PECL:
|
||||
. ext/crack (Jani, Derick)
|
||||
. ext/db (Jani, Derick)
|
||||
. ext/mcal (Jani, Derick)
|
||||
. ext/qtdom (Jani, Derick)
|
||||
. ext/notes (Wez)
|
||||
- Added 'c' modifier to date() which returns the date in the ISO 8601 format.
|
||||
(Derick, Manuzhai)
|
||||
- Added an optional parameter to microtime() to get the time as float. (Andrey)
|
||||
- Added MacRoman encoding support to htmlentities(). (Derick, Marcus Bointon)
|
||||
- Added possibility to call PHP functions as XSLT-functions. (Christian)
|
||||
- Added possibility to prevent PHP from registering variables when input filter
|
||||
support is used. (Derick)
|
||||
- Added iconv stream filter (convert.iconv.*). (Moriyoshi)
|
||||
- Added EXSLT support in ext/xsl. (Christian)
|
||||
- Added qdbm handler for dba extension. (mg at iceni dot pl, Marcus)
|
||||
- Added new functions:
|
||||
. dba_key_split() to split inifile keys in an array. (Marcus)
|
||||
. time_nanosleep() signal safe sleep (Magnus, Ilia)
|
||||
. headers_list(). (Sara)
|
||||
. php_strip_whitespace(). strip whitespace & comments from a script. (Ilia)
|
||||
. php_check_syntax(). check php script for parse errors. (Ilia)
|
||||
. image_type_to_extension(). return extension based on image type. (Ilia)
|
||||
. stream_socket_sendto() and stream_socket_recvfrom(). (Wez)
|
||||
. iconv_mime_decode_headers(). (Moriyoshi)
|
||||
. get_declared_interfaces(). (Andrey, Marcus)
|
||||
. sqlite_fetch_column_types(). (Ilia)
|
||||
- Added proxy support to http:// wrapper. (Sara)
|
||||
- Added rename(), rmdir() and mkdir() support to userstreams. (Sara)
|
||||
- Added rename(), rmdir() and mkdir() support to ftp:// wrapper. (Sara)
|
||||
- Changed rename(), rmdir() and mkdir() to be routed via streams API. (Sara)
|
||||
- Changed stat() and family to be routed via streams API. (Sara)
|
||||
- Fixed include_once() / require_once() on Windows to honor case-insensitivity
|
||||
of files. (Andi)
|
||||
- Fixed get_declared_classes() to return only classes. (Andrey, Marcus)
|
||||
- Fixed __autoload() to preserve case of the passed class name. (Andi)
|
||||
- Fixed bug #26615 () (runekl at opoint dot com, Derick)
|
||||
- Fixed bug #26591 ("__autoload threw an exception" during an uncaught).
|
||||
(Marcus)
|
||||
- Fixed bug #26534 (stream_get_meta_data() -> Access Violation). (Wez)
|
||||
- Fixed bug #26528 (HTML entities are not being decoded by
|
||||
xml_parse()/xml_parse_into_struct()). (Ilia)
|
||||
- Fixed bug #26182 (Object properties created redundantly). (Andi)
|
||||
- Fixed bug #26156 (REPLACE_ZVAL_VALUE works on uninit stack-based zvals).
|
||||
(Moriyoshi)
|
||||
- Fixed bug #26083 (Non-working write support in ext/dom). (Ilia)
|
||||
- Fixed bug #26072 (--disable-libxml does not work). (Jani)
|
||||
- Fixed bug #26001 (serialize crashes when accessing an overloaded object that
|
||||
has no properties (NULL hashtable)). (Wez)
|
||||
- Fixed bug #25664 (COM crashes when calling a Delphi implementations of
|
||||
ITypeInfo). (Wez)
|
||||
- Fixed bug #24837 (Incorrect behaviour of PPP using foreach). (Marcus)
|
||||
- Fixed bug #24693 (Allow session.use_trans_sid to be enabled/disabled from
|
||||
inside the script). (Ilia)
|
||||
- Fixed bug #24394 (Serializing cross-referenced objects causes segfault).
|
||||
(Moriyoshi)
|
||||
|
||||
30 Oct 2003, PHP 5 Beta 2
|
||||
- Lots and lots of changes in the Zend Engine 2 since beta 1:
|
||||
. Added Iterators
|
||||
. Improved memory manager
|
||||
. Added Reflection API
|
||||
. Removed the not so working namespaces support
|
||||
. Removed support for expressions within constant declarations.
|
||||
. You can read about most changes in ZEND_CHANGES under the Zend directory.
|
||||
- Improved the DBX extension: (Marc)
|
||||
. Added DBX_RESULT_UNBUFFERED flag for dbx_query().
|
||||
. Added dbx_fetch_row()
|
||||
. Added SQLite support.
|
||||
- Improved the Interbase extension: (Ard Biesheuvel)
|
||||
. Added support for multiple databases into ibase_trans()
|
||||
. Added support for CREATE DATABASE, SET TRANSACTION and EXECUTE PROCEDURE
|
||||
statements into ibase_query()
|
||||
. Added ability to bind PHP arrays to native Interbase arrays
|
||||
. Added ibase_commit_ret() and ibase_rollback_ret()
|
||||
. Added ibase_drop_db()
|
||||
. Added ibase_gen_id()
|
||||
. Added ibase_name_result()
|
||||
. Added ibase_errcode()
|
||||
. Added ibase_affected_rows() and ibase_num_params()
|
||||
. Added ibase_param_info()
|
||||
. Added ibase_wait_event()
|
||||
. Added ibase_set_event_handler() and ibase_free_event_handler()
|
||||
- Added new COM extension with integrated .Net support. (Wez)
|
||||
- Added new functions:
|
||||
. setrawcookie(). (Brian)
|
||||
. pg_version(). (Marcus)
|
||||
. dbase_get_header_info(). (Zak)
|
||||
. snmp_read_mib(). (Jani)
|
||||
. http_build_query(). (Sara)
|
||||
. ftp_alloc(). (Sara)
|
||||
. array_udiff(). (Andrey)
|
||||
. array_udiff_assoc(). (Andrey)
|
||||
. array_udiff_uassoc(). (Andrey)
|
||||
. array_diff_uassoc(). (Andrey)
|
||||
. convert_uuencode(). (Ilia)
|
||||
. convert_uudecode(). (Ilia)
|
||||
. substr_compare(). (Ilia)
|
||||
. pcntl_wait(). (GeorgeS)
|
||||
- Added "resume_pos" context option to "ftp://" wrapper. (Sara)
|
||||
- Added optional parameter to OCIWriteTemporaryLob() to specify the type of LOB
|
||||
(Patch by Novicky Marek <novicky@aarongroup.cz>). (Thies)
|
||||
- Added reflection API. (Andrei, George, Timm)
|
||||
- Changed length parameter in fgetcsv() to be optional. (Moriyoshi)
|
||||
- Fixed IPv6 support in MacOSX Panther. (Dan, Marko)
|
||||
- Fixed fgetcsv() to correctly handle international (non-ascii) characters.
|
||||
(Moriyoshi)
|
||||
- Fixed support for <![CDATA[]]> fields within XML documents in ext/xml.
|
||||
(Sterling)
|
||||
- Fixed visibility of __construct and __clone. (Marcus)
|
||||
- Fixed bug #25756 (SimpleXML's validate_schema_file() broken). (Moriyoshi)
|
||||
- Fixed bug #25581 (getimagesize() returns incorrect values on bitmap (os2)
|
||||
files). (Marcus)
|
||||
- Fixed bug #25494 (array_merge*() allows non-arrays as argument). (Jay)
|
||||
- Fixed bug #24766 (strange result array from unpack()). (Moriyoshi)
|
||||
- Fixed bug #24729 ($obj = new $className; causes crash when $className is not
|
||||
set). (Marcus)
|
||||
- Fixed bug #24565 (cannot read array elements received via $_REQUEST). (Zeev)
|
||||
- Fixed bug #24445 (get_parent_class() returns different values).
|
||||
(Sterling, Stanislav)
|
||||
- Fixed bug #24403 (preg_replace() problem: Using $this when not in object
|
||||
context). (Zeev)
|
||||
- Fixed bug #24399 (PEAR DB isError crash [instanceof_function fault?]).
|
||||
(Sterling, Marcus)
|
||||
- Fixed bug #24396 (foreach ($k=>$v), the key $k is missing). (Zeev)
|
||||
- Fixed bug #24279 (__get() crash when no value is returned). (Ilia)
|
||||
- Fixed bug #22367 (undefined variable has a value). (Zeev)
|
||||
- Fixed bug #19859 (allow fast_call_user_function to support __call).
|
||||
(Stanislav)
|
||||
- Fixed bug #17997 (Warning when switch() and reference are combined). (Zeev)
|
||||
- Fixed bug #17988 (strtotime failed to parse postgresql timestamp). (Derick)
|
||||
|
||||
29 Jun 2003, PHP 5 Beta 1
|
||||
- Removed the bundled MySQL client library. (Sterling)
|
||||
- Switched to Zend Engine 2, which includes numerous engine level improvements.
|
||||
A full list is available at http://www.php.net/zend-engine-2.php.
|
||||
- Added SQLite (http://www.hwaci.com/sw/sqlite/) extension: (Wez, Marcus, Tal)
|
||||
. Includes bundled SQLite library
|
||||
. Enabled by default
|
||||
- Completely Overhauled XML support:
|
||||
. New simplexml extension. (Sterling)
|
||||
. New DOM extension. (Rob, Chregu, Marcus)
|
||||
. New XSL extension. (Chregu, Rob)
|
||||
. Moved the old DOM-XML and XSLT extensions to PECL. (James, Sterling)
|
||||
. ext/xml can now use either libxml2 or expat to parse XML. (Sterling)
|
||||
. Removed bundled expat library. (Jani)
|
||||
- New php.ini options:
|
||||
. "session.hash_function" and "session.hash_bits_per_character". (Sascha)
|
||||
. "mail.force_extra_paramaters". (Derick)
|
||||
. "register_long_arrays". (Zeev)
|
||||
- Improved the speed of internal functions that use callbacks by 40% due to a
|
||||
new internal fast_call_user_function() function. (Sterling)
|
||||
- Improved the streams support: (Wez)
|
||||
. Improved performance of readfile(), fpassthru() and some internal streams
|
||||
operations under Win32.
|
||||
. stream_socket_client() - similar to fsockopen(), but more powerful.
|
||||
. stream_socket_server() - Creates a server socket.
|
||||
. stream_socket_accept() - Accept a client connection.
|
||||
. stream_socket_get_name() - Get local or remote name of socket.
|
||||
. stream_copy_to_stream()
|
||||
. stream_get_line() - Reads either the specified number of bytes or until
|
||||
the ending string is found. (Ilia)
|
||||
. Added context property to userspace streams object. (Sara)
|
||||
. Added generic crypto interface for streams.
|
||||
(supports dynamic loading of OpenSSL)
|
||||
. Added lightweight streaming input abstraction to the Zend Engine scanners
|
||||
to provide uniform support for include()'ing data from PHP streams across
|
||||
all platforms.
|
||||
. Added 'string.base64' stream filter. (Moriyoshi)
|
||||
. Renamed stream_register_wrapper() to stream_wrapper_register(). (Derick)
|
||||
- Improved the GD extension: (Pierre-Alain Joye, Ilia)
|
||||
. imagefilter() - Apply different filters to image.
|
||||
(Only available with bundled GD library)
|
||||
. Antialiased drawing support:
|
||||
o imageantialias() - (de)active antialias
|
||||
o imageline() and imagepolygon() antialias support
|
||||
- Changed the length parameter in fgetss() to be optional. (Moriyoshi)
|
||||
- Changed ini parser to allow for handling of quoted multi-line values. (Ilia)
|
||||
- Changed get_extension_funcs() to return list of the built-in Zend Engine
|
||||
functions if "zend" is specified as the module name. (Ilia)
|
||||
- Changed array_search() to accept also objects as a needle. (Moriyoshi)
|
||||
- Changed ext/mcrypt to require libmcrypt version 2.5.6 or greater. (Derick)
|
||||
- Changed uniqid() parameters to be optional and allow any prefix length.
|
||||
(Marcus)
|
||||
- Added new iconv functions. (Moriyoshi)
|
||||
. iconv_strlen()
|
||||
. iconv_substr()
|
||||
. iconv_strpos()
|
||||
. iconv_strrpos()
|
||||
. iconv_mime_decode()
|
||||
. iconv_mime_encode()
|
||||
- Added misc. new functions:
|
||||
. ldap_sasl_bind(). (peter_c60@hotmail.com, Jani)
|
||||
. imap_getacl(). (Dan, Holger Burbach)
|
||||
. file_put_contents(). (Sterling)
|
||||
. proc_nice() - Changes priority of the current process. (Ilia)
|
||||
. pcntl_getpriority() and pcntl_setpriority(). (Ilia)
|
||||
. idate(), date_sunrise() and date_sunset(). (Moshe Doron)
|
||||
. strpbrk() - Searches a string for a list of characters. (Ilia)
|
||||
. get_headers() - Returns headers sent by the server of the specified URL.
|
||||
(Ilia)
|
||||
. str_split() - Breaks down a string into an array of elements based on
|
||||
length. (Ilia)
|
||||
. array_walk_recursive(). (Ilia)
|
||||
. array_combine(). (Andrey)
|
||||
- Added optional parameter to get_browser() to make it return an array. (Jay)
|
||||
- Added optional parameter to openssl_sign() to specify the hashing algorithm.
|
||||
(scott@planetscott.ca, Derick)
|
||||
- Added optional parameter to sha1(), sha1_file(), md5() and md5_file() which
|
||||
makes them return the digest as binary data. (Michael Bretterklieber, Derick)
|
||||
- Added optional parameter to mkdir() to make directory creation recursive.
|
||||
(Ilia)
|
||||
- Added optional parameter to file() which makes the result array not contain
|
||||
the line endings and to skip empty lines. (Ilia)
|
||||
- Added new range() functionality:
|
||||
. Support for float modifier. (Ilia)
|
||||
. Detection of numeric values inside strings passed as high & low. (Ilia)
|
||||
. Proper handle the situations where high == low. (Ilia)
|
||||
. Added an optional step parameter. (Jon)
|
||||
- Added encoding detection feature for expat XML parser.
|
||||
(Adam Dickmeiss, Moriyoshi)
|
||||
- Added missing multibyte (unicode) support and numeric entity support to
|
||||
html_entity_decode(). (Moriyoshi)
|
||||
- Added IPv6 support to ext/sockets. (Sara)
|
||||
- Added "ftp://" wrapper support to opendir(), stat() and unlink(). (Sara)
|
||||
- Added context options 'method', 'header' and 'content' for "http://" fopen
|
||||
wrapper. (Sara)
|
||||
- Added input filter support. See README.input_filter for more info. (Rasmus)
|
||||
- Added a replace count for str_[i]replace(), see bug #8218. (Sara)
|
||||
- Fixed is_executable() to be available also on Windows. (Shane)
|
||||
- Fixed dirname() and strip_tags() to be binary-safe. (Moriyoshi)
|
||||
- Fixed bug #24098 (crash in pathinfo()). (Ilia)
|
||||
- Fixed bug #21985 and #22064 (various mb_send_mail() issues). (Moriyoshi)
|
||||
- Fixed bug #21600 (Assign by reference function call changes variable
|
||||
contents). (Zeev)
|
||||
@@ -1,115 +0,0 @@
|
||||
This is the first file you should be reading after you get your CVS account.
|
||||
We'll assume you're basically familiar with CVS, but feel free to post
|
||||
your questions on the mailing list. Please have a look at
|
||||
http://cvsbook.red-bean.com/ for more detailed information on CVS.
|
||||
|
||||
PHP is developed through the efforts of a large number of people.
|
||||
Collaboration is a Good Thing(tm), and CVS lets us do this. Thus, following
|
||||
some basic rules with regards to CVS usage will:
|
||||
|
||||
a. Make everybody happier, especially those responsible for maintaining
|
||||
the CVS itself.
|
||||
b. Keep the changes consistently well documented and easily trackable.
|
||||
c. Prevent some of those 'Oops' moments.
|
||||
d. Increase the general level of good will on planet Earth.
|
||||
|
||||
|
||||
Having said that, here are the organizational rules:
|
||||
|
||||
1. Respect other people working on the project.
|
||||
|
||||
2. Discuss any significant changes on the list before committing.
|
||||
|
||||
3. Look at EXTENSIONS file to see who is the primary maintainer of
|
||||
the code you want to contribute to.
|
||||
|
||||
4. If you "strongly disagree" about something another person did, don't
|
||||
start fighting publicly - take it up in private email.
|
||||
|
||||
5. If you don't know how to do something, ask first!
|
||||
|
||||
6. Test your changes before committing them. We mean it. Really.
|
||||
|
||||
|
||||
The next few rules are more of a technical nature.
|
||||
|
||||
1. DO NOT TOUCH ChangeLog! It is automagically updated from the commit
|
||||
messages every day. Woe be to those who attempt to mess with it.
|
||||
|
||||
2. All news updates intended for public viewing, such as new features,
|
||||
bug fixes, improvements, etc., should go into the NEWS file. Also see
|
||||
the note below about automatically updating NEWS in your commit message.
|
||||
|
||||
3. Do not commit multiple file and dump all messages in one commit. If you
|
||||
modified several unrelated files, commit each group separately and
|
||||
provide a nice commit message for each one. See example below.
|
||||
|
||||
4. Do write your commit message in such a way that it makes sense even
|
||||
without the corresponding diff. One should be able to look at it, and
|
||||
immediately know what was modified. Definitely include the function name
|
||||
in the message as shown below.
|
||||
|
||||
5. In your commit messages, keep each line shorter than 80 characters. And
|
||||
try to align your lines vertically, if they wrap. It looks bad otherwise.
|
||||
|
||||
6. If you modified a function that is callable from PHP, prepend PHP to
|
||||
the function name as shown below.
|
||||
|
||||
|
||||
The format of the commit messages is pretty simple.
|
||||
|
||||
If a line begins with #, it is taken to be a comment and will not appear
|
||||
in the ChangeLog. If the line begins with @, it will be redirected to the
|
||||
NEWS file. Everything else goes into the ChangeLog.
|
||||
|
||||
It is important to note that if your comment or news logline spans multiple
|
||||
lines, you have to put # or @ at the beginning of _every_ such line. Every
|
||||
entry in NEWS has to have a name after it, so if you did it with someone's
|
||||
help, put both your names there. Your name WILL NOT be automatically put
|
||||
at the end of the NEWS entry - so, please provide it yourself.
|
||||
|
||||
Example. Say you modified two files, datetime.c and string.c. In datetime.c
|
||||
you added a new format option for date() function, and in string.c you fixed
|
||||
a memory leak in php_trim(). Don't commit both of these at once. Commit them
|
||||
separately and try to make sure your commit messages look something like the
|
||||
following.
|
||||
|
||||
For datetime.c:
|
||||
|
||||
(PHP date) Added new 'K' format modifier for printing out number of
|
||||
days until New Year's Eve.
|
||||
@- Added new 'K' format modifier that will output the number of days
|
||||
@ until New Year's Eve. (Bob)
|
||||
|
||||
For string.c:
|
||||
(php_trim) Fixed a memory leak resulting from improper use of zval_dtor().
|
||||
# Man, that thing was leaking all over the place!
|
||||
@- Fixed memory leak in trim(). (Bob)
|
||||
|
||||
The lines above marked with @ will go into NEWS file automagically, and the
|
||||
# lines will be omitted from the ChangeLog. Alternatively, you might want
|
||||
to modify NEWS file directly and not use the @ lines.
|
||||
|
||||
If you fix some bugs, you should note the bug ID numbers in your
|
||||
commit message. Bug ID should be prefixed by "#" for easier access to
|
||||
bug report when developers are browsing CVS via. LXR or Bonsai.
|
||||
|
||||
Example:
|
||||
|
||||
Fixed pgsql notice handler double free crash bug. Bug #14016
|
||||
@ Fixed pgsql notice handler double free crash bug. Bug #14016
|
||||
|
||||
If you don't see your messages in ChangeLog and NEWS right away, don't worry!
|
||||
These files are updated once a day, so your stuff will not show up until
|
||||
somewhat later. Don't go adding stuff to NEWS by hand if you already put @
|
||||
lines in the commit message.
|
||||
|
||||
You can use LXR (http://lxr.php.net/) and Bonsai (http://bonsai.php.net/)
|
||||
to look at PHP CVS repository in various ways.
|
||||
|
||||
To receive daily updates to ChangeLog and NEWS, send an empty message to
|
||||
php-cvs-daily-subscribe@lists.php.net.
|
||||
|
||||
Happy hacking,
|
||||
|
||||
PHP Team
|
||||
@@ -1,39 +0,0 @@
|
||||
Between PHP 4.0.6 and 4.1.0, the Zend module struct changed in a way
|
||||
that broke both source and binary compatibility. If you are
|
||||
maintaining a third party extension, here's how to update it:
|
||||
|
||||
If this was your old module entry:
|
||||
|
||||
zend_module_entry foo_module_entry = {
|
||||
"foo", /* extension name */
|
||||
foo_functions, /* extension function list */
|
||||
NULL, /* extension-wide startup function */
|
||||
NULL, /* extension-wide shutdown function */
|
||||
PHP_RINIT(foo), /* per-request startup function */
|
||||
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
|
||||
PHP_MINFO(foo), /* information function */
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
Here's how it should look if you want your code to build with PHP
|
||||
4.1.0 and up:
|
||||
|
||||
zend_module_entry foo_module_entry = {
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
STANDARD_MODULE_HEADER,
|
||||
#endif
|
||||
"foo", /* extension name */
|
||||
foo_functions, /* extension function list */
|
||||
NULL, /* extension-wide startup function */
|
||||
NULL, /* extension-wide shutdown function */
|
||||
PHP_RINIT(foo), /* per-request startup function */
|
||||
PHP_RSHUTDOWN(foo), /* per-request shutdown function */
|
||||
PHP_MINFO(foo), /* information function */
|
||||
#if ZEND_MODULE_API_NO >= 20010901
|
||||
FOO_VERSION, /* extension version number (string) */
|
||||
#endif
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
If you don't care about source compatibility with earlier PHP releases
|
||||
than 4.1.0, you can drop the #if/#endif lines.
|
||||
-194
@@ -1,194 +0,0 @@
|
||||
(NOTE: you may also want to take a look at the pear package
|
||||
PECL_Gen, a PHP-only alternative for this script that
|
||||
supports way more extension writing tasks and is
|
||||
supposed to replace ext_skel completely in the long run ...)
|
||||
|
||||
WHAT IT IS
|
||||
|
||||
It's a tool for automatically creating the basic framework for a PHP module
|
||||
and writing C code handling arguments passed to your functions from a simple
|
||||
configuration file. See an example at the end of this file.
|
||||
|
||||
HOW TO USE IT
|
||||
|
||||
Very simple. First, change to the ext/ directory of the PHP 4 sources. If
|
||||
you just need the basic framework and will be writing all the code in your
|
||||
functions yourself, you can now do
|
||||
|
||||
./ext_skel --extname=module_name
|
||||
|
||||
and everything you need is placed in directory module_name.
|
||||
|
||||
[ Note that GNU awk is likely required for this script to work. Debian
|
||||
systems seem to default to using mawk, so you may need to change the
|
||||
#! line in skeleton/create_stubs and the cat $proto | awk line in
|
||||
ext_skel to use gawk explicitly. ]
|
||||
|
||||
If you don't need to test the existence of any external header files,
|
||||
libraries or functions in them, the module is already almost ready to be
|
||||
compiled in PHP. Just remove 3 comments in your_module_name/config.m4,
|
||||
change back up to PHP sources top directory, and do
|
||||
|
||||
./buildconf; ./configure --enable-module_name; make
|
||||
|
||||
But if you already have planned the overall scheme of your module, what
|
||||
functions it will contain, their return types and the arguments they take
|
||||
(a very good idea) and don't want to bother yourself with creating function
|
||||
definitions and handling arguments passed yourself, it's time to create a
|
||||
function definitions file, which you will give as an argument to ext_skel
|
||||
with option
|
||||
|
||||
--proto=filename.
|
||||
|
||||
FORMAT OF FUNCTION DEFINITIONS FILE
|
||||
|
||||
All the definitions must be on one line. In it's simplest form, it's just
|
||||
the function name, e.g.
|
||||
|
||||
my_function
|
||||
|
||||
but then you'll be left with an almost empty function body without any
|
||||
argument handling.
|
||||
|
||||
Arguments are given in parenthesis after the function name, and are of
|
||||
the form 'argument_type argument_name'. Arguments are separated from each
|
||||
other with a comma and optional space. Argument_type can be one of int,
|
||||
bool, double, float, string, array, object or mixed.
|
||||
|
||||
An optional argument is separated from the previous by an optional space,
|
||||
then '[' and of course comma and optional space, like all the other
|
||||
arguments. You should close a row of optional arguments with same amount of
|
||||
']'s as there where '['s. Currently, it does not harm if you forget to do it
|
||||
or there is a wrong amount of ']'s, but this may change in the future.
|
||||
|
||||
An additional short description may be added after the parameters.
|
||||
If present it will be filled into the 'proto' header comments in the stubs
|
||||
code and the <refpurpose> tag in the XML documentation.
|
||||
|
||||
An example:
|
||||
|
||||
my_function(int arg1, int arg2 [, int arg3 [, int arg4]]) this is my 1st
|
||||
|
||||
Arguments arg3 and arg4 are optional.
|
||||
|
||||
If possible, the function definition should also contain it's return type
|
||||
in front of the definition. It's not actually used for any C code generating
|
||||
purposes but PHP in-source documentation instead, and as such, very useful.
|
||||
It can be any of int, double, string, bool, array, object, resource, mixed
|
||||
or void.
|
||||
|
||||
The file must contain nothing else but function definitions, no comments or
|
||||
empty lines.
|
||||
|
||||
OTHER OPTIONS
|
||||
|
||||
--no-help
|
||||
|
||||
By default, ext_skel creates both comments in the source code and a test
|
||||
function to help first time module writers to get started and testing
|
||||
configuring and compiling their module. This option turns off all such things
|
||||
which may just annoy experienced PHP module coders. Especially useful with
|
||||
|
||||
--stubs=file
|
||||
|
||||
which will leave out also all module specific stuff and write just function
|
||||
stubs with function value declarations and passed argument handling, and
|
||||
function entries and definitions at the end of the file, for copying and
|
||||
pasting into an already existing module.
|
||||
|
||||
--assign-params
|
||||
--string-lens
|
||||
|
||||
By default, function proto 'void foo(string bar)' creates the following:
|
||||
...
|
||||
zval **bar;
|
||||
... (zend_get_parameters_ex() called in the middle...)
|
||||
convert_to_string_ex(bar);
|
||||
|
||||
Specifying both of these options changes the generated code to:
|
||||
...
|
||||
zval **bar_arg;
|
||||
int bar_len;
|
||||
char *bar = NULL;
|
||||
... (zend_get_parameters_ex() called in the middle...)
|
||||
convert_to_string_ex(bar_arg);
|
||||
bar = Z_STRVAL_PP(bar_arg);
|
||||
bar_len = Z_STRLEN_PP(bar_arg);
|
||||
|
||||
You shouldn't have to ask what happens if you leave --string-lens out. If you
|
||||
have to, it's questionable whether you should be reading this document.
|
||||
|
||||
--with-xml[=file]
|
||||
|
||||
Creates the basics for phpdoc .xml file.
|
||||
|
||||
--full-xml
|
||||
|
||||
Not implemented yet. When or if there will ever be created a framework for
|
||||
self-contained extensions to use phpdoc system for their documentation, this
|
||||
option enables it on the created xml file.
|
||||
|
||||
CURRENT LIMITATIONS, BUGS AND OTHER ODDITIES
|
||||
|
||||
Only arguments of types int, bool, double, float, string and array are
|
||||
handled. For other types you must write the code yourself. And for type
|
||||
mixed, it wouldn't even be possible to write anything, because only you
|
||||
know what to expect.
|
||||
|
||||
It can't handle correctly, and probably never will, variable list of
|
||||
of arguments. (void foo(int bar [, ...])
|
||||
|
||||
Don't trust the generated code too much. It tries to be useful in most of
|
||||
the situations you might encounter, but automatic code generation will never
|
||||
beat a programmer who knows the real situation at hand. ext_skel is generally
|
||||
best suited for quickly generating a wrapper for c-library functions you
|
||||
might want to have available in PHP too.
|
||||
|
||||
This program doesn't have a --help option. It has --no-help instead.
|
||||
|
||||
EXAMPLE
|
||||
|
||||
The following _one_ line
|
||||
|
||||
bool my_drawtext(resource image, string text, resource font, int x, int y [, int color])
|
||||
|
||||
will create this function definition for you (note that there are a few
|
||||
question marks to be replaced by you, and you must of course add your own
|
||||
value definitions too):
|
||||
|
||||
/* {{{ proto bool my_drawtext(resource image, string text, resource font, int x, int y[, int color])
|
||||
*/
|
||||
PHP_FUNCTION(my_drawtext)
|
||||
{
|
||||
zval **image, **text, **font, **x, **y, **color;
|
||||
int argc;
|
||||
int image_id = -1;
|
||||
int font_id = -1;
|
||||
|
||||
argc = ZEND_NUM_ARGS();
|
||||
if (argc < 5 || argc > 6 || zend_get_parameters_ex(argc, &image, &text, &font, &x, &y, &color) == FAILURE) {
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(???, ???, image, image_id, "???", ???_rsrc_id);
|
||||
ZEND_FETCH_RESOURCE(???, ???, font, font_id, "???", ???_rsrc_id);
|
||||
|
||||
switch (argc) {
|
||||
case 6:
|
||||
convert_to_long_ex(color);
|
||||
/* Fall-through. */
|
||||
case 5:
|
||||
convert_to_long_ex(y);
|
||||
convert_to_long_ex(x);
|
||||
/* font: fetching resources already handled. */
|
||||
convert_to_string_ex(text);
|
||||
/* image: fetching resources already handled. */
|
||||
break;
|
||||
default:
|
||||
WRONG_PARAM_COUNT;
|
||||
}
|
||||
|
||||
php_error(E_WARNING, "my_drawtext: not yet implemented");
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
New parameter parsing functions
|
||||
===============================
|
||||
|
||||
It should be easier to parse input parameters to an extension function.
|
||||
Hence, borrowing from Python's example, there are now a set of functions
|
||||
that given the string of type specifiers, can parse the input parameters
|
||||
and store the results in the user specified variables. This avoids most
|
||||
of the IS_* checks and convert_to_* conversions. The functions also
|
||||
check for the appropriate number of parameters, and try to output
|
||||
meaningful error messages.
|
||||
|
||||
|
||||
Prototypes
|
||||
----------
|
||||
/* Implemented. */
|
||||
int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
|
||||
int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);
|
||||
|
||||
The zend_parse_parameters() function takes the number of parameters
|
||||
passed to the extension function, the type specifier string, and the
|
||||
list of pointers to variables to store the results in. The _ex() version
|
||||
also takes 'flags' argument -- current only ZEND_PARSE_PARAMS_QUIET can
|
||||
be used as 'flags' to specify that the function should operate quietly
|
||||
and not output any error messages.
|
||||
|
||||
Both functions return SUCCESS or FAILURE depending on the result.
|
||||
|
||||
The auto-conversions are performed as necessary. Arrays, objects, and
|
||||
resources cannot be auto-converted.
|
||||
|
||||
|
||||
Type specifiers
|
||||
---------------
|
||||
l - long
|
||||
d - double
|
||||
s - string (with possible null bytes) and its length
|
||||
b - boolean, stored in zend_bool
|
||||
r - resource (stored in zval)
|
||||
a - array
|
||||
o - object (of any type)
|
||||
O - object (of specific type, specified by class entry)
|
||||
z - the actual zval
|
||||
|
||||
The following characters also have a meaning in the specifier string:
|
||||
| - indicates that the remaining parameters are optional, they
|
||||
should be initialized to default values by the extension since they
|
||||
will not be touched by the parsing function if they are not
|
||||
passed to it.
|
||||
/ - use SEPARATE_ZVAL_IF_NOT_REF() on the parameter it follows
|
||||
! - the parameter it follows can be of specified type or NULL (only applies
|
||||
to 'a', 'o', 'O', 'r', and 'z'). If NULL is passed, the results
|
||||
pointer is set to NULL as well.
|
||||
|
||||
Examples
|
||||
--------
|
||||
/* Gets a long, a string and its length, and a zval */
|
||||
long l;
|
||||
char *s;
|
||||
int s_len;
|
||||
zval *param;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
|
||||
&l, &s, &s_len, ¶m) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets an object of class specified by my_ce, and an optional double. */
|
||||
zval *obj;
|
||||
double d = 0.5;
|
||||
zend_class_entry my_ce;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
|
||||
&obj, my_ce, &d) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets an object or null, and an array.
|
||||
If null is passed for object, obj will be set to NULL. */
|
||||
zval *obj;
|
||||
zval *arr;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
|
||||
&obj, &arr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Gets a separated array which can also be null. */
|
||||
zval *arr;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
|
||||
&arr) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Get only the first three parameters (useful for varargs functions). */
|
||||
zval *z;
|
||||
zend_bool b;
|
||||
zval *r;
|
||||
if (zend_parse_parameters(3 TSRMLS_CC, "zbr!",
|
||||
&z, &b, &r) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Get either a set of 3 longs or a string. */
|
||||
long l1, l2, l3;
|
||||
char *s;
|
||||
/*
|
||||
* The function expects a pointer to a integer in this case, not a long
|
||||
* or any other type. If you specify a type which is larger
|
||||
* than a 'int', the upper bits might not be initialized
|
||||
* properly, leading to random crashes on platforms like
|
||||
* Tru64 or Linux/Alpha.
|
||||
*/
|
||||
int length;
|
||||
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
|
||||
"lll", &l1, &l2, &l3) == SUCCESS) {
|
||||
/* manipulate longs */
|
||||
} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
|
||||
"s", &s, &length) == SUCCESS) {
|
||||
/* manipulate string */
|
||||
} else {
|
||||
/* output error */
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
1. strrpos() and strripos() now use the entire string as a needle. Be aware
|
||||
that the existing scripts may no longer work as you expect.
|
||||
|
||||
EX :
|
||||
<?php
|
||||
var_dump(strrpos("ABCDEF","DEF"));
|
||||
var_dump(strrpos("ABCDEF","DAF"));
|
||||
?>
|
||||
|
||||
Will give you different results. The former returns 3 while the latter
|
||||
returns false rather than the position of the last occurrence of 'D'.
|
||||
The same applies to strripos().
|
||||
|
||||
2. Illegal use of string offsets causes E_ERROR instead of E_WARNING.
|
||||
|
||||
EX :
|
||||
<?php
|
||||
$a = "foo";
|
||||
unset($a[0][1][2]);
|
||||
?>
|
||||
|
||||
Fatal error: Cannot use string offset as an array in ... on line 1
|
||||
|
||||
3. array_merge() was changed to accept only arrays. If a non-array variable is
|
||||
passed, a E_WARNING will be thrown for every such parameter. Be careful
|
||||
because your code may start emitting E_WARNING out of the blue.
|
||||
|
||||
4. Be careful when porting from ext/mysql to ext/mysqli. The following
|
||||
functions return NULL when no more data is available in the result set
|
||||
(ext/mysql's functions return FALSE).
|
||||
|
||||
- mysqli_fetch_row()
|
||||
- mysqli_fetch_array()
|
||||
- mysqli_fetch_assoc()
|
||||
|
||||
5. PATH_TRANSLATED server variable is no longer set implicitly under
|
||||
Apache2 SAPI in contrast to the situation in PHP 4, where it is set to the
|
||||
same value as the SCRIPT_FILENAME server variable when it is not populated
|
||||
by Apache. This change was made to comply with the CGI specification.
|
||||
Please refer to bug #23610 for further information.
|
||||
|
||||
6. Starting PHP 5.0.0 the T_ML_CONSTANT constant is no longer defined by the
|
||||
ext/tokenizer extension. If error_reporting is set to E_ALL notices will
|
||||
be produced. Instead of T_ML_CONSTANT for /* */ the T_COMMENT constant
|
||||
is used, thus both // and /* */ are resolved as the T_COMMENT constant.
|
||||
However the PHPDoc style comments /** */ ,which starting PHP 5 are parsed
|
||||
by PHP, are recongnized as T_DOC_COMMENT.
|
||||
|
||||
7. $_SERVER should be populated with argc and argv if variables_order
|
||||
includes "S". If you have specifically configured your system to not
|
||||
create $_SERVER, then of course it shouldn't be there. The change was to
|
||||
always make argc and argv available in the CLI version regardless of the
|
||||
variables_order setting. As in, the CLI version will now always populate
|
||||
the global $argc and $argv variables.
|
||||
|
||||
8. In some cases classes must be declared before used. It only happens only
|
||||
if some of the new features of PHP 5 are used. Otherwise the behaviour is
|
||||
the old.
|
||||
Example 1 (works with no errors):
|
||||
<?php
|
||||
$a = new a();
|
||||
class a {
|
||||
}
|
||||
?>
|
||||
|
||||
Example 2 (throws an error):
|
||||
<?php
|
||||
$a = new a();
|
||||
interface b{
|
||||
}
|
||||
class a implements b {
|
||||
}
|
||||
?>
|
||||
|
||||
Output (example 2) :
|
||||
Fatal error: Class 'a' not found in /tmp/cl.php on line 2
|
||||
|
||||
9. get_class() starting PHP 5 returns the name of the class as it was
|
||||
declared which may lead to problems in older scripts that rely on
|
||||
the previous behaviour - the class name is lowercased.
|
||||
Example :
|
||||
<?php
|
||||
class FooBar {
|
||||
}
|
||||
$a = new FooBar();
|
||||
var_dump(get_class($a));
|
||||
?>
|
||||
|
||||
Output (PHP 4):
|
||||
string(6) "foobar"
|
||||
|
||||
Output (PHP 5):
|
||||
string(6) "FooBar"
|
||||
----------------------------------------------------------------------
|
||||
Example code that will break :
|
||||
//....
|
||||
function someMethod($p) {
|
||||
if (get_class($p) != 'helpingclass') {
|
||||
return FALSE;
|
||||
}
|
||||
//...
|
||||
}
|
||||
//...
|
||||
Possible solution is to search for get_class() in all your scripts and
|
||||
use strtolower().
|
||||
|
||||
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
QNX4 Installation Notes
|
||||
-----------------------
|
||||
|
||||
NOTE: General installation instructions are in the INSTALL file
|
||||
|
||||
|
||||
1. To compile and test PHP3 you have to grab, compile and install:
|
||||
- GNU dbm library or another db library;
|
||||
- GNU bison (1.25 or later; 1.25 tested);
|
||||
- GNU flex (any version supporting -o and -P options; 2.5.4 tested);
|
||||
- GNU diffutils (any version supporting -w option; 2.7 tested);
|
||||
|
||||
2. To use CVS version you may need also:
|
||||
- GNU CVS (1.9 tested);
|
||||
- GNU autoconf (2.12 tested);
|
||||
- GNU m4 (1.3 or later preferable; 1.4 tested);
|
||||
|
||||
3. To run configure define -lunix in command line:
|
||||
LDFLAGS=-lunix ./configure
|
||||
|
||||
4. To use Sybase SQL Anywhere define ODBC_QNX and CUSTOM_ODBC_LIBS in
|
||||
command line and run configure with --with-custom-odbc:
|
||||
CFLAGS=-DODBC_QNX LDFLAGS=-lunix CUSTOM_ODBC_LIBS="-ldblib -lodbc" ./configure --with-custom-odbc=/usr/lib/sqlany50
|
||||
If you have SQL Anywhere version 5.5.00, then you have to add
|
||||
CFLAGS=-DSQLANY_BUG
|
||||
to workaround its SQLFreeEnv() bug. Other versions has not been tested,
|
||||
so try without this flag first.
|
||||
|
||||
5. To build the Apache module, you may have to hardcode an include path for
|
||||
alloc.h in your Apache base directory:
|
||||
- APACHE_DIRECTORY/src/httpd.h:
|
||||
change #include "alloc.h"
|
||||
to #include "APACHE_DIRECTORY/src/alloc.h"
|
||||
Unless you want to use system regex library, you have to hardcode also
|
||||
a path to regex.h:
|
||||
- APACHE_DIRECTORY/src/conf.h:
|
||||
change #include <regex.h>
|
||||
to #include "APACHE_DIRECTORY/src/regex/regex.h"
|
||||
I don't know so far why this required for QNX, may be it is Watcom
|
||||
compiler problem.
|
||||
|
||||
If you building Apache module with SQL Anywhere support, you'll get
|
||||
symbol conflict with BOOL. It is defined in Apache (httpd.h) and in
|
||||
SQL Anywhere (odbc.h). This has nothing to do with PHP, so you have to
|
||||
fix it yourself someway.
|
||||
|
||||
6. With above precautions, it should compile as is and pass regression
|
||||
tests completely:
|
||||
make
|
||||
make check
|
||||
make install
|
||||
|
||||
Don't bother me unless you really sure you made that all but it
|
||||
still doesn't work.
|
||||
|
||||
June 28, 1998
|
||||
Igor Kovalenko -- owl@infomarket.ru
|
||||
@@ -1,155 +0,0 @@
|
||||
$Id$
|
||||
=============================================================================
|
||||
|
||||
HOW TO CREATE A SELF-CONTAINED PHP EXTENSION
|
||||
|
||||
A self-contained extension can be distributed independently of
|
||||
the PHP source. To create such an extension, two things are
|
||||
required:
|
||||
|
||||
- Configuration file (config.m4)
|
||||
- Source code for your module
|
||||
|
||||
We will describe now how to create these and how to put things
|
||||
together.
|
||||
|
||||
PREPARING YOUR SYSTEM
|
||||
|
||||
While the result will run on any system, a developer's setup needs these
|
||||
tools:
|
||||
|
||||
GNU autoconf
|
||||
GNU automake
|
||||
GNU libtool
|
||||
GNU m4
|
||||
|
||||
All of these are available from
|
||||
|
||||
ftp://ftp.gnu.org/pub/gnu/
|
||||
|
||||
CONVERTING AN EXISTING EXTENSION
|
||||
|
||||
Just to show you how easy it is to create a self-contained
|
||||
extension, we will convert an embedded extension into a
|
||||
self-contained one. Install PHP and execute the following
|
||||
commands.
|
||||
|
||||
$ mkdir /tmp/newext
|
||||
$ cd /tmp/newext
|
||||
|
||||
You now have an empty directory. We will copy the files from
|
||||
the mysql extension:
|
||||
|
||||
$ cp -rp php-4.0.X/ext/mysql/* .
|
||||
|
||||
It is time to finish the module. Run:
|
||||
|
||||
$ phpize
|
||||
|
||||
You can now ship the contents of the directory - the extension
|
||||
can live completely on its own.
|
||||
|
||||
The user instructions boil down to
|
||||
|
||||
$ ./configure \
|
||||
[--with-php-config=/path/to/php-config] \
|
||||
[--with-mysql=MYSQL-DIR]
|
||||
$ make install
|
||||
|
||||
The MySQL module will either use the embedded MySQL client
|
||||
library or the MySQL installation in MYSQL-DIR.
|
||||
|
||||
|
||||
DEFINING THE NEW EXTENSION
|
||||
|
||||
Our demo extension is called "foobar".
|
||||
|
||||
It consists of two source files "foo.c" and "bar.c"
|
||||
(and any arbitrary amount of header files, but that is not
|
||||
important here).
|
||||
|
||||
The demo extension does not reference any external
|
||||
libraries (that is important, because the user does not
|
||||
need to specify anything).
|
||||
|
||||
|
||||
LTLIBRARY_SOURCES specifies the names of the sources files. You can
|
||||
name an arbitrary number of source files here.
|
||||
|
||||
CREATING THE M4 CONFIGURATION FILE
|
||||
|
||||
The m4 configuration can perform additional checks. For a
|
||||
self-contained extension, you do not need more than a few
|
||||
macro calls.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
PHP_ARG_ENABLE(foobar,whether to enable foobar,
|
||||
[ --enable-foobar Enable foobar])
|
||||
|
||||
if test "$PHP_FOOBAR" != "no"; then
|
||||
PHP_NEW_EXTENSION(foobar, foo.c bar.c, $ext_shared)
|
||||
fi
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
PHP_ARG_ENABLE will automatically set the correct variables, so
|
||||
that the extension will be enabled by PHP_NEW_EXTENSION in shared mode.
|
||||
|
||||
The first argument of PHP_NEW_EXTENSION describes the name of the
|
||||
extension. The second names the source-code files. The third passes
|
||||
$ext_shared which is set by PHP_ARG_ENABLE/WITH to PHP_NEW_EXTENSION.
|
||||
|
||||
Please use always PHP_ARG_ENABLE or PHP_ARG_WITH. Even if you do not
|
||||
plan to distribute your module with PHP, these facilities allow you
|
||||
to integrate your module easily into the main PHP module framework.
|
||||
|
||||
CREATING SOURCE FILES
|
||||
|
||||
ext_skel can be of great help when creating the common code for all modules
|
||||
in PHP for you and also writing basic function definitions and C code for
|
||||
handling arguments passed to your functions. See README.EXT_SKEL for further
|
||||
information.
|
||||
|
||||
As for the rest, you are currently alone here. There are a lot of existing
|
||||
modules, use a simple module as a starting point and add your own code.
|
||||
|
||||
|
||||
CREATING THE SELF-CONTAINED EXTENSION
|
||||
|
||||
Put config.m4 and the source files into one directory. Then, run phpize
|
||||
(this is installed during make install by PHP 4.0).
|
||||
|
||||
For example, if you configured PHP with --prefix=/php, you would run
|
||||
|
||||
$ /php/bin/phpize
|
||||
|
||||
This will automatically copy the necessary build files and create
|
||||
configure from your config.m4.
|
||||
|
||||
And that's it. You now have a self-contained extension.
|
||||
|
||||
INSTALLING A SELF-CONTAINED EXTENSION
|
||||
|
||||
An extension can be installed by running:
|
||||
|
||||
$ ./configure \
|
||||
[--with-php-config=/path/to/php-config]
|
||||
$ make install
|
||||
|
||||
ADDING SHARED MODULE SUPPORT TO A MODULE
|
||||
|
||||
In order to be useful, a self-contained extension must be loadable
|
||||
as a shared module. I will explain now how you can add shared module
|
||||
support to an existing module called foo.
|
||||
|
||||
1. In config.m4, use PHP_ARG_WITH/PHP_ARG_ENABLE. Then you will
|
||||
automatically be able to use --with-foo=shared[,..] or
|
||||
--enable-foo=shared[,..].
|
||||
|
||||
2. In config.m4, use PHP_NEW_EXTENSION(foo,.., $ext_shared) to enable
|
||||
building the extension.
|
||||
|
||||
3. Add the following lines to your C source file:
|
||||
|
||||
#ifdef COMPILE_DL_FOO
|
||||
ZEND_GET_MODULE(foo)
|
||||
#endif
|
||||
-379
@@ -1,379 +0,0 @@
|
||||
An Overview of the PHP Streams abstraction
|
||||
==========================================
|
||||
$Id$
|
||||
|
||||
WARNING: some prototypes in this file are out of date.
|
||||
The information contained here is being integrated into
|
||||
the PHP manual - stay tuned...
|
||||
|
||||
Please send comments to: Wez Furlong <wez@thebrainroom.com>
|
||||
|
||||
Why Streams?
|
||||
============
|
||||
You may have noticed a shed-load of issock parameters flying around the PHP
|
||||
code; we don't want them - they are ugly and cumbersome and force you to
|
||||
special case sockets and files every time you need to work with a "user-level"
|
||||
PHP file pointer.
|
||||
Streams take care of that and present the PHP extension coder with an ANSI
|
||||
stdio-alike API that looks much nicer and can be extended to support non file
|
||||
based data sources.
|
||||
|
||||
Using Streams
|
||||
=============
|
||||
Streams use a php_stream* parameter just as ANSI stdio (fread etc.) use a
|
||||
FILE* parameter.
|
||||
|
||||
The main functions are:
|
||||
|
||||
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t count);
|
||||
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t
|
||||
count);
|
||||
PHPAPI size_t php_stream_printf(php_stream * stream TSRMLS_DC,
|
||||
const char * fmt, ...);
|
||||
PHPAPI int php_stream_eof(php_stream * stream);
|
||||
PHPAPI int php_stream_getc(php_stream * stream);
|
||||
PHPAPI char *php_stream_gets(php_stream * stream, char *buf, size_t maxlen);
|
||||
PHPAPI int php_stream_close(php_stream * stream);
|
||||
PHPAPI int php_stream_flush(php_stream * stream);
|
||||
PHPAPI int php_stream_seek(php_stream * stream, off_t offset, int whence);
|
||||
PHPAPI off_t php_stream_tell(php_stream * stream);
|
||||
PHPAPI int php_stream_lock(php_stream * stream, int mode);
|
||||
|
||||
These (should) behave in the same way as the ANSI stdio functions with similar
|
||||
names: fread, fwrite, fprintf, feof, fgetc, fgets, fclose, fflush, fseek, ftell, flock.
|
||||
|
||||
Opening Streams
|
||||
===============
|
||||
In most cases, you should use this API:
|
||||
|
||||
PHPAPI php_stream *php_stream_open_wrapper(char *path, char *mode,
|
||||
int options, char **opened_path TSRMLS_DC);
|
||||
|
||||
Where:
|
||||
path is the file or resource to open.
|
||||
mode is the stdio compatible mode eg: "wb", "rb" etc.
|
||||
options is a combination of the following values:
|
||||
IGNORE_PATH (default) - don't use include path to search for the file
|
||||
USE_PATH - use include path to search for the file
|
||||
IGNORE_URL - do not use plugin wrappers
|
||||
REPORT_ERRORS - show errors in a standard format if something
|
||||
goes wrong.
|
||||
STREAM_MUST_SEEK - If you really need to be able to seek the stream
|
||||
and don't need to be able to write to the original
|
||||
file/URL, use this option to arrange for the stream
|
||||
to be copied (if needed) into a stream that can
|
||||
be seek()ed.
|
||||
|
||||
opened_path is used to return the path of the actual file opened,
|
||||
but if you used STREAM_MUST_SEEK, may not be valid. You are
|
||||
responsible for efree()ing opened_path. opened_path may be (and usually
|
||||
is) NULL.
|
||||
|
||||
If you need to open a specific stream, or convert standard resources into
|
||||
streams there are a range of functions to do this defined in php_streams.h.
|
||||
A brief list of the most commonly used functions:
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_from_file(FILE *file, const char *mode);
|
||||
Convert a FILE * into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_tmpfile(void);
|
||||
Open a FILE * with tmpfile() and convert into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_fopen_temporary_file(const char *dir,
|
||||
const char *pfx, char **opened_path TSRMLS_DC);
|
||||
Generate a temporary file name and open it.
|
||||
|
||||
There are some network enabled relatives in php_network.h:
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_from_socket(int socket, int persistent);
|
||||
Convert a socket into a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_host(const char *host, unsigned short port,
|
||||
int socktype, int timeout, int persistent);
|
||||
Open a connection to a host and return a stream.
|
||||
|
||||
PHPAPI php_stream *php_stream_sock_open_unix(const char *path, int persistent,
|
||||
struct timeval *timeout);
|
||||
Open a UNIX domain socket.
|
||||
|
||||
|
||||
Stream Utilities
|
||||
================
|
||||
|
||||
If you need to copy some data from one stream to another, you will be please
|
||||
to know that the streams API provides a standard way to do this:
|
||||
|
||||
PHPAPI size_t php_stream_copy_to_stream(php_stream *src,
|
||||
php_stream *dest, size_t maxlen);
|
||||
|
||||
If you want to copy all remaining data from the src stream, pass
|
||||
PHP_STREAM_COPY_ALL as the maxlen parameter, otherwise maxlen indicates the
|
||||
number of bytes to copy.
|
||||
This function will try to use mmap where available to make the copying more
|
||||
efficient.
|
||||
|
||||
If you want to read the contents of a stream into an allocated memory buffer,
|
||||
you should use:
|
||||
|
||||
PHPAPI size_t php_stream_copy_to_mem(php_stream *src, char **buf,
|
||||
size_t maxlen, int persistent);
|
||||
|
||||
This function will set buf to the address of the buffer that it allocated,
|
||||
which will be maxlen bytes in length, or will be the entire length of the
|
||||
data remaining on the stream if you set maxlen to PHP_STREAM_COPY_ALL.
|
||||
The buffer is allocated using pemalloc(); you need to call pefree() to
|
||||
release the memory when you are done.
|
||||
As with copy_to_stream, this function will try use mmap where it can.
|
||||
|
||||
If you have an existing stream and need to be able to seek() it, you
|
||||
can use this function to copy the contents into a new stream that can
|
||||
be seek()ed:
|
||||
|
||||
PHPAPI int php_stream_make_seekable(php_stream *origstream, php_stream **newstream);
|
||||
|
||||
It returns one of the following values:
|
||||
#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */
|
||||
#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */
|
||||
#define PHP_STREAM_FAILED 2 /* an error occurred while attempting conversion */
|
||||
#define PHP_STREAM_CRITICAL 3 /* an error occurred; origstream is in an unknown state; you should close origstream */
|
||||
|
||||
make_seekable will always set newstream to be the stream that is valid
|
||||
if the function succeeds.
|
||||
When you have finished, remember to close the stream.
|
||||
|
||||
NOTE: If you only need to seek forward, there is no need to call this
|
||||
function, as the php_stream_seek can emulate forward seeking when the
|
||||
whence parameter is SEEK_CUR.
|
||||
|
||||
NOTE: Writing to the stream may not affect the original source, so it
|
||||
only makes sense to use this for read-only use.
|
||||
|
||||
NOTE: If the origstream is network based, this function will block
|
||||
until the whole contents have been downloaded.
|
||||
|
||||
NOTE: Never call this function with an origstream that is referenced
|
||||
as a resource! It will close the origstream on success, and this
|
||||
can lead to a crash when the resource is later used/released.
|
||||
|
||||
NOTE: If you are opening a stream and need it to be seekable, use the
|
||||
STREAM_MUST_SEEK option to php_stream_open_wrapper();
|
||||
|
||||
PHPAPI int php_stream_supports_lock(php_stream * stream);
|
||||
|
||||
This function will return either 1 (success) or 0 (failure) indicating whether or
|
||||
not a lock can be set on this stream. Typically you can only set locks on stdio streams.
|
||||
|
||||
Casting Streams
|
||||
===============
|
||||
What if your extension needs to access the FILE* of a user level file pointer?
|
||||
You need to "cast" the stream into a FILE*, and this is how you do it:
|
||||
|
||||
FILE * fp;
|
||||
php_stream * stream; /* already opened */
|
||||
|
||||
if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void*)&fp, REPORT_ERRORS) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
The prototype is:
|
||||
|
||||
PHPAPI int php_stream_cast(php_stream * stream, int castas, void ** ret, int
|
||||
show_err);
|
||||
|
||||
The show_err parameter, if non-zero, will cause the function to display an
|
||||
appropriate error message of type E_WARNING if the cast fails.
|
||||
|
||||
castas can be one of the following values:
|
||||
PHP_STREAM_AS_STDIO - a stdio FILE*
|
||||
PHP_STREAM_AS_FD - a generic file descriptor
|
||||
PHP_STREAM_AS_SOCKETD - a socket descriptor
|
||||
|
||||
If you ask a socket stream for a FILE*, the abstraction will use fdopen to
|
||||
create it for you. Be warned that doing so may cause buffered data to be lost
|
||||
if you mix ANSI stdio calls on the FILE* with php stream calls on the stream.
|
||||
|
||||
If your system has the fopencookie function, php streams can synthesize a
|
||||
FILE* on top of any stream, which is useful for SSL sockets, memory based
|
||||
streams, data base streams etc. etc.
|
||||
|
||||
In situations where this is not desirable, you should query the stream
|
||||
to see if it naturally supports FILE *. You can use this code snippet
|
||||
for this purpose:
|
||||
|
||||
if (php_stream_is(stream, PHP_STREAM_IS_STDIO)) {
|
||||
/* can safely cast to FILE* with no adverse side effects */
|
||||
}
|
||||
|
||||
You can use:
|
||||
|
||||
PHPAPI int php_stream_can_cast(php_stream * stream, int castas)
|
||||
|
||||
to find out if a stream can be cast, without actually performing the cast, so
|
||||
to check if a stream is a socket you might use:
|
||||
|
||||
if (php_stream_can_cast(stream, PHP_STREAM_AS_SOCKETD) == SUCCESS) {
|
||||
/* it can be a socket */
|
||||
}
|
||||
|
||||
Please note the difference between php_stream_is and php_stream_can_cast;
|
||||
stream_is tells you if the stream is a particular type of stream, whereas
|
||||
can_cast tells you if the stream can be forced into the form you request.
|
||||
The former doesn't change anything, while the later *might* change some
|
||||
state in the stream.
|
||||
|
||||
Stream Internals
|
||||
================
|
||||
|
||||
There are two main structures associated with a stream - the php_stream
|
||||
itself, which holds some state information (and possibly a buffer) and a
|
||||
php_stream_ops structure, which holds the "virtual method table" for the
|
||||
underlying implementation.
|
||||
|
||||
The php_streams ops struct consists of pointers to methods that implement
|
||||
read, write, close, flush, seek, gets and cast operations. Of these, an
|
||||
implementation need only implement write, read, close and flush. The gets
|
||||
method is intended to be used for streams if there is an underlying method
|
||||
that can efficiently behave as fgets. The ops struct also contains a label
|
||||
for the implementation that will be used when printing error messages - the
|
||||
stdio implementation has a label of "STDIO" for example.
|
||||
|
||||
The idea is that a stream implementation defines a php_stream_ops struct, and
|
||||
associates it with a php_stream using php_stream_alloc.
|
||||
|
||||
As an example, the php_stream_fopen() function looks like this:
|
||||
|
||||
PHPAPI php_stream * php_stream_fopen(const char * filename, const char * mode)
|
||||
{
|
||||
FILE * fp = fopen(filename, mode);
|
||||
php_stream * ret;
|
||||
|
||||
if (fp) {
|
||||
ret = php_stream_alloc(&php_stream_stdio_ops, fp, 0, 0, mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
php_stream_stdio_ops is a php_stream_ops structure that can be used to handle
|
||||
FILE* based streams.
|
||||
|
||||
A socket based stream would use code similar to that above to create a stream
|
||||
to be passed back to fopen_wrapper (or it's yet to be implemented successor).
|
||||
|
||||
The prototype for php_stream_alloc is this:
|
||||
|
||||
PHPAPI php_stream * php_stream_alloc(php_stream_ops * ops, void * abstract,
|
||||
size_t bufsize, int persistent, const char * mode)
|
||||
|
||||
ops is a pointer to the implementation,
|
||||
abstract holds implementation specific data that is relevant to this instance
|
||||
of the stream,
|
||||
bufsize is the size of the buffer to use - if 0, then buffering at the stream
|
||||
level will be disabled (recommended for underlying sources that implement
|
||||
their own buffering - such a FILE*),
|
||||
persistent controls how the memory is to be allocated - persistently so that
|
||||
it lasts across requests, or non-persistently so that it is freed at the end
|
||||
of a request (it uses pemalloc),
|
||||
mode is the stdio-like mode of operation - php streams places no real meaning
|
||||
in the mode parameter, except that it checks for a 'w' in the string when
|
||||
attempting to write (this may change).
|
||||
|
||||
The mode parameter is passed on to fdopen/fopencookie when the stream is cast
|
||||
into a FILE*, so it should be compatible with the mode parameter of fopen().
|
||||
|
||||
Writing your own stream implementation
|
||||
======================================
|
||||
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
RULE #1: when writing your own streams: make sure you have configured PHP with
|
||||
--enable-debug.
|
||||
I've taken some great pains to hook into the Zend memory manager to help track
|
||||
down allocation problems. It will also help you spot incorrect use of the
|
||||
STREAMS_DC, STREAMS_CC and the semi-private STREAMS_REL_CC macros for function
|
||||
definitions.
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
RULE #2: Please use the stdio stream as a reference; it will help you
|
||||
understand the semantics of the stream operations, and it will always
|
||||
be more up to date than these docs :-)
|
||||
|
||||
First, you need to figure out what data you need to associate with the
|
||||
php_stream. For example, you might need a pointer to some memory for memory
|
||||
based streams, or if you were making a stream to read data from an RDBMS like
|
||||
MySQL, you might want to store the connection and rowset handles.
|
||||
|
||||
The stream has a field called abstract that you can use to hold this data.
|
||||
If you need to store more than a single field of data, define a structure to
|
||||
hold it, allocate it (use pemalloc with the persistent flag set
|
||||
appropriately), and use the abstract pointer to refer to it.
|
||||
|
||||
For structured state you might have this:
|
||||
|
||||
struct my_state {
|
||||
MYSQL conn;
|
||||
MYSQL_RES * result;
|
||||
};
|
||||
|
||||
struct my_state * state = pemalloc(sizeof(struct my_state), persistent);
|
||||
|
||||
/* initialize the connection, and run a query, using the fields in state to
|
||||
* hold the results */
|
||||
|
||||
state->result = mysql_use_result(&state->conn);
|
||||
|
||||
/* now allocate the stream itself */
|
||||
stream = php_stream_alloc(&my_ops, state, 0, persistent, "r");
|
||||
|
||||
/* now stream->abstract == state */
|
||||
|
||||
Once you have that part figured out, you can write your implementation and
|
||||
define the your own php_stream_ops struct (we called it my_ops in the above
|
||||
example).
|
||||
|
||||
For example, for reading from this weird MySQL stream:
|
||||
|
||||
static size_t php_mysqlop_read(php_stream * stream, char * buf, size_t count)
|
||||
{
|
||||
struct my_state * state = (struct my_state*)stream->abstract;
|
||||
|
||||
if (buf == NULL && count == 0) {
|
||||
/* in this special case, php_streams is asking if we have reached the
|
||||
* end of file */
|
||||
if (... at end of file ...)
|
||||
return EOF;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* pull out some data from the stream and put it in buf */
|
||||
... mysql_fetch_row(state->result) ...
|
||||
/* we could do something strange, like format the data as XML here,
|
||||
and place that in the buf, but that brings in some complexities,
|
||||
such as coping with a buffer size too small to hold the data,
|
||||
so I won't even go in to how to do that here */
|
||||
}
|
||||
|
||||
Implement the other operations - remember that write, read, close and flush
|
||||
are all mandatory. The rest are optional. Declare your stream ops struct:
|
||||
|
||||
php_stream_ops my_ops = {
|
||||
php_mysqlop_write, php_mysqlop_read, php_mysqlop_close,
|
||||
php_mysqlop_flush, NULL, NULL, NULL,
|
||||
"Strange MySQL example"
|
||||
}
|
||||
|
||||
Thats it!
|
||||
|
||||
Take a look at the STDIO implementation in streams.c for more information
|
||||
about how these operations work.
|
||||
The main thing to remember is that in your close operation you need to release
|
||||
and free the resources you allocated for the abstract field. In the case of
|
||||
the example above, you need to use mysql_free_result on the rowset, close the
|
||||
connection and then use pefree to dispose of the struct you allocated.
|
||||
You may read the stream->persistent field to determine if your struct was
|
||||
allocated in persistent mode or not.
|
||||
|
||||
vim:tw=78:et
|
||||
@@ -1,126 +0,0 @@
|
||||
Submitting Patch for PHP
|
||||
========================
|
||||
|
||||
This document describes how to submit a patch for PHP. Since you are
|
||||
reading this document, you are willing to submit a patch for PHP.
|
||||
Please keep reading! Submitting a patch for PHP is easy. The hard
|
||||
part is making it acceptable for inclusion into our repository. :-)
|
||||
|
||||
How to create patch?
|
||||
--------------------
|
||||
We are working with CVS. You need to get CVS source to create a patch
|
||||
that we accept. Visit http://www.php.net/anoncvs.php to get CVS
|
||||
source. You can check out older versions, but make sure you get
|
||||
the default branch (i.e. Do not use -r option when you check out the
|
||||
CVS source)
|
||||
|
||||
Read CODING_STANDARDS file before you start working.
|
||||
|
||||
Now you are ready to create a patch. Modify source to fix a bug in PHP or
|
||||
add a new feature to PHP. After you finished editing, please test your
|
||||
patch. Read README.TESTING for testing.
|
||||
|
||||
After you finish testing your patch, take diff file using
|
||||
"cvs diff > your.patch" command.
|
||||
|
||||
Read README.TESTING for submitting a test script for your patch. This is
|
||||
not strictly required, but it is preferred to submit a test script along
|
||||
with your patch. Making new test script is very easy. It also helps us
|
||||
to understand what you have been fixed or added to PHP.
|
||||
|
||||
|
||||
Tips for creating patch
|
||||
-----------------------
|
||||
If you would like to fix multiple bugs. It is easier for us if you
|
||||
could create 1 patch for 1 bug, but this is not strictly required.
|
||||
Note though that you might get little response, if your patch is
|
||||
too hard to review.
|
||||
|
||||
If you would like change/add many lines, it is better to ask module
|
||||
maintainer and/or internals@lists.php.net, or pear-dev@lists.php.net if
|
||||
you are patching PEAR. Official module maintainers can be found in
|
||||
EXTENSIONS file in PHP source.
|
||||
|
||||
If you are new to CVS (Concurrent Versions System), visit
|
||||
http://cvshome.org/ for details.
|
||||
|
||||
|
||||
Recommended CVS client settings for creating patch file
|
||||
------------------------------------------------------
|
||||
Recommended ~/.cvsrc file setting is:
|
||||
------
|
||||
cvs -z3
|
||||
update -d -P
|
||||
checkout -P
|
||||
diff -u
|
||||
|
||||
------
|
||||
diff -u means:
|
||||
-u Use the unified output format.
|
||||
|
||||
With this CVS setting, you don't have to worry about adding/deleting
|
||||
newlines and spaces.
|
||||
|
||||
|
||||
Check list for submitting patch
|
||||
-------------------------------
|
||||
- Did you run "make test" to check if your patch didn't break
|
||||
other features?
|
||||
- Did you compile PHP with --enable-debug and check the PHP and
|
||||
web server error logs when you test your patch?
|
||||
- Did you build PHP for multi-threaded web servers. (Optional)
|
||||
- Did you create test script for "make test"? (Recommended)
|
||||
- Did you check your patch is unified format and it does not
|
||||
contain white space changes? (If you are not using recommended
|
||||
cvs setting)
|
||||
- Did you update CVS source before you take final patch?
|
||||
- Did you read the patch again?
|
||||
|
||||
|
||||
Where to send your patch?
|
||||
-------------------------
|
||||
If you are patching C source, send the patch to internals@lists.php.net.
|
||||
If you are patching a module, you should also send the patch to the
|
||||
maintainer. Official module maintainers are listed in EXTENSION file
|
||||
in source.
|
||||
|
||||
If you are patching PEAR, send the patch to pear-dev@lists.php.net.
|
||||
|
||||
Please add the prefix "[PATCH]" to your email subject and make sure
|
||||
to include the patch as a MIME attachment even if it is short.
|
||||
|
||||
NOTE: only MIME attachments of type 'text/*' are accepted. The
|
||||
easiest way to accomplish this, is to make the extension
|
||||
'.txt'.
|
||||
|
||||
Test scripts should be included in the same email.
|
||||
Explain what has been fixed/added/changed by your patch.
|
||||
|
||||
Finally, add the bug Id(s) which can be closed by your patch, if any.
|
||||
|
||||
|
||||
What happens after you submit your patch
|
||||
----------------------------------------
|
||||
If your patch is easy to review and has obviously no side-effects,
|
||||
it might take up to a few hours until someone commits it.
|
||||
|
||||
Because this is a volunteer-driven effort, more complex patches will
|
||||
require more patience on your side.
|
||||
|
||||
If you did not receive any feedback in a few days, please consider
|
||||
resubmitting the description of your patch, along-side with
|
||||
these questions:
|
||||
|
||||
- Is my patch too hard to review? Because of which factors?
|
||||
- Should I split it up in multiple parts?
|
||||
- Are there any unwanted whitespace changes?
|
||||
|
||||
|
||||
What happens when your patch is applied?
|
||||
----------------------------------------
|
||||
Your name will be included together with your email address in the CVS
|
||||
commit log. If your patch affects end-users, a brief description
|
||||
and your name might be added to the NEWS file.
|
||||
|
||||
|
||||
Thank you for submitting patch for PHP!
|
||||
-179
@@ -1,179 +0,0 @@
|
||||
[IMPORTANT NOTICE]
|
||||
------------------
|
||||
Failed tests usualy indicate a problem with your local system setup
|
||||
and not within PHP itself (at least for official PHP release versions).
|
||||
You may decide to automaticaly submit a test summary to our QA workflow
|
||||
at the end of a test run.
|
||||
Please do *not* submit a failed test as a bug or ask for help on why
|
||||
it failed on your system without providing substantial backup information
|
||||
on *why* the test failed on your special setup. Thank you :-)
|
||||
|
||||
|
||||
[Testing Basics]
|
||||
----------------
|
||||
The easiest way to test your PHP build is to run "make test" from the
|
||||
command line after successfully compiling. This will run the complete
|
||||
tests for all enabled functionalities and extensions using the PHP
|
||||
CLI binary.
|
||||
To execute test scripts, you must build PHP with some SAPI, then you
|
||||
type "make test" to execute all or some test scripts saved under
|
||||
"tests" directory under source root directory.
|
||||
|
||||
Usage:
|
||||
make test
|
||||
|
||||
"make test" basically executes "run-tests.php" script
|
||||
under the source root (parallel builds will not work). Therefore you
|
||||
can execute the script as follows:
|
||||
|
||||
TEST_PHP_EXECUTABLE=sapi/cli/php \
|
||||
sapi/cli/php [-c /path/to/php.ini] run-tests.php [ext/foo/tests/GLOB]
|
||||
|
||||
|
||||
[Which "php" executable "make test" look for]
|
||||
---------------------------------------------
|
||||
You must use TEST_PHP_EXECUTABLE environment variable to explicitly
|
||||
select the php executable to be used to run the tests. That can either
|
||||
be the CLI or CGI executable.
|
||||
|
||||
"make test" executes "run-tests.php" script with "php" binary. Some
|
||||
test scripts such as session must be executed by CGI SAPI. Therefore,
|
||||
you must build PHP with CGI SAPI to perform all tests.
|
||||
|
||||
NOTE: PHP binary executing "run-tests.php" and php binary used for
|
||||
executing test scripts may differ. If you use different PHP binary for
|
||||
executing "run-tests.php" script, you may get errors.
|
||||
|
||||
|
||||
[Which php.ini is used]
|
||||
-----------------------
|
||||
"make test" uses the same php.ini file as it would once installed.
|
||||
The tests have been written to be independent of that php.ini file,
|
||||
so if you find a test that is affected by a setting, please report
|
||||
this, so we can address the issue.
|
||||
|
||||
|
||||
[Which test scripts are executed]
|
||||
---------------------------------
|
||||
"run-tests.php" ("make test"), without any arguments executes all
|
||||
test scripts by extracting all directories named "tests"
|
||||
from the source root and any subdirectories below. If there are files,
|
||||
which have a "phpt" extension, "run-tests.php" looks at the sections
|
||||
in these files, determines whether it should run it, by evaluating
|
||||
the 'SKIP' section. If the test is eligible for execution, the 'FILE'
|
||||
section is extracted into a ".php" file (with the same name besides
|
||||
the extension) and gets executed.
|
||||
When an argument is given or TESTS environment variable is set, the
|
||||
GLOB is expanded by the shell and any file with extension "*.phpt" is
|
||||
regarded as a test file.
|
||||
|
||||
Tester can easily execute tests selectively with as follows.
|
||||
|
||||
Examples:
|
||||
./sapi/cli/php run-tests.php ext/mbstring/*
|
||||
./sapi/cli/php run-tests.php ext/mbstring/020.phpt
|
||||
|
||||
|
||||
[Test results]
|
||||
--------------
|
||||
Test results are printed to standard output. If there is a failed test,
|
||||
the "run-tests.php" script saves the result, the expected result and the
|
||||
code executed to the test script directory. For example, if
|
||||
ext/myext/tests/myext.phpt fails to pass, the following files are created:
|
||||
|
||||
ext/myext/tests/myext.php - actual test file executed
|
||||
ext/myext/tests/myext.log - log of test execution (L)
|
||||
ext/myext/tests/myext.exp - expected output (E)
|
||||
ext/myext/tests/myext.out - output from test script (O)
|
||||
ext/myext/tests/myext.diff - diff of .out and .exp (D)
|
||||
|
||||
Failed tests are always bugs. Either the test is bugged or not considering
|
||||
factors applying to the tester's environment, or there is a bug in PHP.
|
||||
If this is a known bug, we strive to provide bug numbers, in either the
|
||||
test name or the file name. You can check the status of such a bug, by
|
||||
going to: http://bugs.php.net/12345 where 12345 is the bug number.
|
||||
For clarity and automated processing, bug numbers are prefixed by a hash
|
||||
sign '#' in test names and/or test cases are named bug12345.phpt.
|
||||
|
||||
NOTE: The files generated by tests can be selected by setting the
|
||||
environment variable TEST_PHP_LOG_FORMAT. For each file you want to be
|
||||
generated use the character in brackets as shown above (default is LEOD).
|
||||
The php file will be generated always.
|
||||
|
||||
NOTE: You can set environment variable TEST_PHP_DETAILED to enable
|
||||
detailed test information.
|
||||
|
||||
[Automated testing]
|
||||
If you like to keep up to speed, with latest developments and quality
|
||||
assurance, setting the environment variable NO_INTERACTION to 1, will not
|
||||
prompt the tester for any user input.
|
||||
|
||||
Normally, the exit status of "make test" is zero, regardless of the results
|
||||
of independent tests. Set the environment variable REPORT_EXIT_STATUS to 1,
|
||||
and "make test" will set the exit status ("$?") to non-zero, when an
|
||||
individual test has failed.
|
||||
|
||||
Example script to be run by cron(1):
|
||||
========== qa-test.sh =============
|
||||
#!/bin/sh
|
||||
|
||||
CO_DIR=$HOME/cvs/php5
|
||||
MYMAIL=qa-test@domain.com
|
||||
TMPDIR=/var/tmp
|
||||
TODAY=`date +"%Y%m%d"`
|
||||
|
||||
# Make sure compilation enviroment is correct
|
||||
CONFIGURE_OPTS='--disable-all --enable-cli --with-pcre'
|
||||
export MAKE=gmake
|
||||
export CC=gcc
|
||||
|
||||
# Set test environment
|
||||
export NO_INTERACTION=1
|
||||
export REPORT_EXIT_STATUS=1
|
||||
|
||||
cd $CO_DIR
|
||||
cvs update . >>$TMPDIR/phpqatest.$TODAY
|
||||
./cvsclean ; ./buildconf ; ./configure $CONFIGURE_OPTS ; $MAKE
|
||||
$MAKE test >>$TMPDIR/phpqatest.$TODAY 2>&1
|
||||
if test $? -gt 0
|
||||
then
|
||||
cat $TMPDIR/phpqatest.$TODAY | mail -s"PHP-QA Test Failed for $TODAY" $MYMAIL
|
||||
fi
|
||||
========== end of qa-test.sh =============
|
||||
|
||||
NOTE: the exit status of run-tests.php will be 1 when
|
||||
REPORT_EXIT_STATUS is set. The result of "make test" may be higher
|
||||
than that. At present, gmake 3.79.1 returns 2, so it is
|
||||
advised to test for non-zero, rather then a specific value.
|
||||
|
||||
|
||||
[Creating new test files]
|
||||
-------------------------
|
||||
Writing test file is very easy if you are used to PHP.
|
||||
See the HOWTO at http://qa.php.net/write-test.php
|
||||
|
||||
|
||||
[How to help us]
|
||||
----------------
|
||||
If you find bug in PHP, you can submit bug report AND test script
|
||||
for us. You don't have to write complete script, just give us test
|
||||
script with following format. Please test the script and make sure
|
||||
you write the correct ACTUAL OUTPUT and EXPECTED OUTPUT before you
|
||||
submit.
|
||||
|
||||
<?php
|
||||
/*
|
||||
Bug #12345
|
||||
substr() bug. Do not return expected string.
|
||||
|
||||
ACTUAL OUTPUT
|
||||
XYXA
|
||||
|
||||
EXPECTED OUTPUT
|
||||
ABCD
|
||||
*/
|
||||
|
||||
$str = "XYZABCD";
|
||||
echo substr($str,3,7);
|
||||
|
||||
?>
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
[IMPORTANT NOTICE]
|
||||
------------------
|
||||
This is an addendum to README.TESTING with additional information
|
||||
specific to run-tests2.php.
|
||||
|
||||
run-tests2.php is backward compatible with tests developed for
|
||||
the original run-tests.php script. run-tests2 is *not* used by
|
||||
'make test'. run-tests2 was developed to provide support for
|
||||
testing PHP under it's primary environment, HTTP, and can run the
|
||||
PHP tests under any of the SAPI modules that are direct executables,
|
||||
or are accessable via HTTP.
|
||||
|
||||
[New features]
|
||||
----------------
|
||||
* Command line interface:
|
||||
You can run 'php run-tests2.php -h' to get all the possible options.
|
||||
* Configuration file:
|
||||
the -c argument will allow you to use a configuration file. This is
|
||||
handy if you are testing multiple environments and need various options
|
||||
depending on the environment.
|
||||
see run-tests-config.php for details.
|
||||
* CGI Emulation:
|
||||
Will emulate a CGI environment when testing with the cgi sapi executable.
|
||||
* HTTP testing:
|
||||
can be configured to run test scripts through an HTTP server running
|
||||
on localhost. localhost is required since either the web server must
|
||||
alias a directory to the php source directory, or the test scripts
|
||||
must be copied to a directory under the web server
|
||||
(see config options TEST_WEB_BASE_URL, TEST_BASE_PATH, and TEST_WEB_EXT)
|
||||
* New sections supported for test files (see below)
|
||||
|
||||
When running tests over http, tests that require ini settings different that what
|
||||
the web server runs under will be skipped. Since the test harness defines a number
|
||||
of ini settings by default, the web server may require special configuration to
|
||||
make testing work.
|
||||
|
||||
[Example Usage]
|
||||
----------------
|
||||
Some (but not all!) examples of usage:
|
||||
|
||||
1. run tests from the php source directory
|
||||
php run-tests2.php -p /path/to/php-cli
|
||||
|
||||
2. run tests using cgi emulation
|
||||
php run-tests2.php -p /path/to/php-cgi
|
||||
|
||||
3. run tests over http, copying test files into document root
|
||||
php run-tests2.php -w -u http://localhost/test -m /path/to/htdocs/test
|
||||
|
||||
4. run tests over http, php sources have been aliased in web server
|
||||
php run-tests2.php -w -u http://localhost/test
|
||||
|
||||
5. run tests using configuration file
|
||||
php run-tests2.php -c /path/to/run-tests-config.php
|
||||
|
||||
6. run tests using configuration file, but overriding some settings:
|
||||
(config file must be first)
|
||||
php run-tests2.php -c /path/to/run-tests-config.php -w -t 3 -d /path/to/testdir
|
||||
|
||||
NOTE: configuration as described in README.TESTING still works.
|
||||
|
||||
[New Test Sections]
|
||||
----------------
|
||||
In addition to the traditional test sections
|
||||
(see http://qa.php.net/write-test.php), several new sections are available
|
||||
under run-tests2.
|
||||
|
||||
--POST--
|
||||
This is not a new section, but not multipart posts are supported for testing
|
||||
file uploads, or other types of POST data.
|
||||
|
||||
--CGI--
|
||||
This section takes no value. It merely provides a simple marker for tests
|
||||
that MUST be run as CGI, even if there is no --POST-- or --GET-- sections
|
||||
in the test file.
|
||||
|
||||
--DESCRIPTION--
|
||||
Not used for anything, just a section for documenting the test
|
||||
|
||||
--ENV--
|
||||
This section get's eval()'d to help build an environment for the
|
||||
execution of the test. This can be used to change environment
|
||||
vars that are used for CGI emulation, or simply to set env vars
|
||||
for cli testing. A full example looks like:
|
||||
|
||||
--ENV--
|
||||
return <<<END
|
||||
PATH_TRANSLATED=$filename
|
||||
PATH_INFO=$scriptname
|
||||
SCRIPT_NAME=$scriptname
|
||||
END;
|
||||
|
||||
Some variables are made easily available for use in this section, they
|
||||
include:
|
||||
$filename full native path to file, will become PATH_TRANSLATED
|
||||
$filepath =dirname($filename)
|
||||
$scriptname this is what will become SCRIPT_NAME unless you override it
|
||||
$docroot the equivelant of DOCUMENT_ROOT under Apache
|
||||
$cwd the directory that the test is being initiated from
|
||||
$this->conf all run-tests2 configuration vars
|
||||
$this->env all environment variables that will get passed to the test
|
||||
|
||||
|
||||
--REQUEST--
|
||||
This section is also eval'd, and is similar in nature to --ENV--. However,
|
||||
this section is used to build the url used in an HTTP request. Valid values
|
||||
to set in this section would include:
|
||||
SCRIPT_NAME The inital part of the request url
|
||||
PATH_INFO The pathinfo part of a request url
|
||||
FRAGMENT The fragment section of a url (after #)
|
||||
QUERY_STRING The query part of a url (after ?)
|
||||
|
||||
--REQUEST--
|
||||
return <<<END
|
||||
PATH_INFO=/path/info
|
||||
END;
|
||||
|
||||
--HEADERS--
|
||||
This section is also eval'd. It is used to provide additional headers sent
|
||||
in an HTTP request, such as content type for multipart posts, cookies, etc.
|
||||
|
||||
--HEADERS--
|
||||
return <<<END
|
||||
Content-Type=multipart/form-data; boundary=---------------------------240723202011929
|
||||
Content-Length=100
|
||||
END;
|
||||
|
||||
--EXPECTHEADERS--
|
||||
This section can be used to define what headers are required to be
|
||||
received back from a request, and is checked in addition to the
|
||||
regular expect sections. For example:
|
||||
|
||||
--EXPECTHEADERS--
|
||||
Status: 404
|
||||
|
||||
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
PHP Build System V5 Overview
|
||||
|
||||
- supports Makefile.ins during transition phase
|
||||
- not-really-portable Makefile includes have been eliminated
|
||||
- supports separate build directories without VPATH by using
|
||||
explicit rules only
|
||||
- does not waste disk-space/CPU-time for building temporary libraries
|
||||
=> especially noticeable on slower systems
|
||||
- slow recursive make replaced with one global Makefile
|
||||
- eases integration of proper dependencies
|
||||
- adds PHP_DEFINE(what[, value]) which creates a single include-file
|
||||
per what. This will allow more fine-grained dependencies.
|
||||
- abandoning the "one library per directory" concept
|
||||
- improved integration of the CLI
|
||||
- several new targets
|
||||
build-modules: builds and copies dynamic modules into modules/
|
||||
install-cli: installs the CLI only, so that the install-sapi
|
||||
target does only what its name says
|
||||
- finally abandoned automake (still requires aclocal at this time)
|
||||
- changed some configure-time constructs to run at buildconf-time
|
||||
- upgraded shtool to 1.5.4
|
||||
- removed $(moduledir) (use EXTENSION_DIR)
|
||||
|
||||
The Reason For a New System
|
||||
|
||||
It became more and more apparent that there is a severe need
|
||||
for addressing the portability concerns and improving the chance
|
||||
that your build is correct (how often have you been told to
|
||||
"make clean"? When this is done, you won't need to anymore).
|
||||
|
||||
|
||||
If You Build PHP on a Unix System
|
||||
|
||||
|
||||
You, as a user of PHP, will notice no changes. Of course, the build
|
||||
system will be faster, look better and work smarter.
|
||||
|
||||
|
||||
|
||||
If You Are Developing PHP
|
||||
|
||||
|
||||
|
||||
|
||||
Extension developers:
|
||||
|
||||
Makefile.ins are abandoned. The files which are to be compiled
|
||||
are specified in the config.m4 now using the following macro:
|
||||
|
||||
PHP_NEW_EXTENSION(foo, foo.c bar.c baz.cpp, $ext_shared)
|
||||
|
||||
E.g. this enables the extension foo which consists of three source-code
|
||||
modules, two in C and one in C++. And, depending on the user's wishes,
|
||||
the extension will even be built as a dynamic module.
|
||||
|
||||
The full syntax:
|
||||
|
||||
PHP_NEW_EXTENSION(extname, sources [, shared [,sapi_class[, extra-cflags]]])
|
||||
|
||||
Please have a look at acinclude.m4 for the gory details and meanings
|
||||
of the other parameters.
|
||||
|
||||
And that's basically it for the extension side.
|
||||
|
||||
If you previously built sub-libraries for this module, add
|
||||
the source-code files here as well. If you need to specify
|
||||
separate include directories, do it this way:
|
||||
|
||||
PHP_NEW_EXTENSION(foo, foo.c mylib/bar.c mylib/gregor.c,,,-I@ext_srcdir@/lib)
|
||||
|
||||
E.g. this builds the three files which are located relative to the
|
||||
extension source directory and compiles all three files with the
|
||||
special include directive (@ext_srcdir@ is automatically replaced).
|
||||
|
||||
Now, you need to tell the build system that you want to build files
|
||||
in a directory called $ext_builddir/lib:
|
||||
|
||||
PHP_ADD_BUILD_DIR($ext_builddir/lib)
|
||||
|
||||
Make sure to call this after PHP_NEW_EXTENSION, because $ext_builddir
|
||||
is only set by the latter.
|
||||
|
||||
If you have a complex extension, you might to need add special
|
||||
Make rules. You can do this by calling PHP_ADD_MAKEFILE_FRAGMENT
|
||||
in your config.m4 after PHP_NEW_EXTENSION.
|
||||
|
||||
This will read a file in the source-dir of your extension called
|
||||
Makefile.frag. In this file, $(builddir) and $(srcdir) will be
|
||||
replaced by the values which are correct for your extension
|
||||
and which are again determined by the PHP_NEW_EXTENSION macro.
|
||||
|
||||
Make sure to prefix *all* relative paths correctly with either
|
||||
$(builddir) or $(srcdir). Because the build system does not
|
||||
change the working directory anymore, we must use either
|
||||
absolute paths or relative ones to the top build-directory.
|
||||
Correct prefixing ensures that.
|
||||
|
||||
|
||||
SAPI developers:
|
||||
|
||||
Instead of using PHP_SAPI=foo/PHP_BUILD_XYZ, you will need to type
|
||||
|
||||
PHP_SELECT_SAPI(name, type, sources.c)
|
||||
|
||||
I.e. specify the source-code files as above and also pass the
|
||||
information regarding how PHP is supposed to be built (shared
|
||||
module, program, etc).
|
||||
|
||||
For example for APXS:
|
||||
|
||||
PHP_SELECT_SAPI(apache, shared, sapi_apache.c mod_php5.c php_apache.c)
|
||||
|
||||
|
||||
|
||||
General info
|
||||
|
||||
The foundation for the new system is the flexible handling of
|
||||
sources and their contexts. With the help of macros you
|
||||
can define special flags for each source-file, where it is
|
||||
located, in which target context it can work, etc.
|
||||
|
||||
Have a look at the well documented macros
|
||||
PHP_ADD_SOURCES(_X) in acinclude.m4.
|
||||
@@ -1,174 +0,0 @@
|
||||
The Win32 Build System.
|
||||
$Id$
|
||||
Wez Furlong <wez@thebrainroom.com>
|
||||
|
||||
If you need help with the build system, send mail to
|
||||
internals@lists.php.net; please don't email me directly.
|
||||
|
||||
===========================================================
|
||||
Contents:
|
||||
1. How to build PHP under windows
|
||||
a. Requirements
|
||||
b. Opening a command prompt
|
||||
c. Generating configure.js
|
||||
d. Configuring
|
||||
e. Building
|
||||
f. Cleaning up
|
||||
g. Running the test suite
|
||||
h. snapshot building
|
||||
|
||||
2. How to write config.w32 files
|
||||
x. to be written.
|
||||
|
||||
===========================================================
|
||||
1. How to build PHP under windows
|
||||
a. Requirements
|
||||
|
||||
You need:
|
||||
- Windows Scripting Host (cscript.exe)
|
||||
- Microsoft Build Tools from:
|
||||
Microsoft Visual Studio (VC6) or later
|
||||
|
||||
You also need:
|
||||
- bindlib_w32 [http://www.php.net/extra/bindlib_w32.zip]
|
||||
- win32build [http://www.php.net/extra/win32build.zip]
|
||||
|
||||
b. Opening the Build Environment Command Prompt:
|
||||
- Using Visual Studio (VC6)
|
||||
1. Install it
|
||||
2. If you have a VC++ Command Prompt icon on your start menu,
|
||||
click on it to get a Command Prompt with the env vars
|
||||
set up correctly.
|
||||
|
||||
If not, create a new shortcut and set the Target to:
|
||||
|
||||
%comspec% /k "C:\Program Files\Microsoft Visual Studio\VC98\Bin\vcvars32.bat"
|
||||
|
||||
You might also want to set the prompt to start in
|
||||
a convenient location (such as the root of your
|
||||
PHP source checkout).
|
||||
|
||||
- Using Visual Studio .Net
|
||||
1. Install it.
|
||||
2. Under the Visual Studio .Net Tools sub menu of your start
|
||||
menu, you should have a Visual Studio .Net Command Prompt
|
||||
icon. If not, create a new shortcut and set the Target to:
|
||||
|
||||
%comspec% /k "C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Tools\vsvars32.bat"
|
||||
|
||||
You might also want to set the prompt to start in
|
||||
a convenient location (such as the root of your
|
||||
PHP source checkout).
|
||||
|
||||
- Using the Platform SDK tools
|
||||
1. Download the Platform SDK:
|
||||
http://www.microsoft.com/msdownload/platformsdk/sdkupdate/
|
||||
|
||||
- You need the Core SDK, which is approx 200MB to download
|
||||
and requires approx 500MB of disk space.
|
||||
- The other components of the SDK are not required by PHP
|
||||
- You might be able to reduce the download size by downloading
|
||||
the installer control component first and then selecting
|
||||
only the Build Environment (around 30MB), but I haven't
|
||||
tried this.
|
||||
|
||||
** Note: it seems that MS don't include the 32 bit
|
||||
build tools in the platform SDK any longer, so
|
||||
you will probably have very limited luck if you
|
||||
don't also have VC++ or VS.Net already installed.
|
||||
|
||||
2. Once installed, you will have an icon on your start menu
|
||||
that will launch the build environment; the latest SDK's
|
||||
install a number of different versions of this; you probably
|
||||
want to choose the Windows 2000 Retail build environment.
|
||||
Clicking on this will open a command prompt with its Path,
|
||||
Include and Lib env vars set to point to the build tools
|
||||
and win32 headers.
|
||||
|
||||
c. Generating configure
|
||||
|
||||
Change directory to where you have your PHP 5 sources.
|
||||
Run buildconf.bat.
|
||||
|
||||
d. Configuring
|
||||
|
||||
cscript /nologo configure.js --help
|
||||
|
||||
Will give you a list of configuration options; these will
|
||||
have the form:
|
||||
|
||||
--enable-foo or --disable-foo or --with-foo or --without-foo.
|
||||
|
||||
--enable-foo will turn something on, and is equivalent to
|
||||
specifying --enable-foo=yes
|
||||
|
||||
--disable-foo will turn something off, and is equivalent to
|
||||
specifying --enable-foo=no
|
||||
|
||||
--enable-foo=shared will attempt to build that feature as
|
||||
a shared, dynamically loadable module.
|
||||
|
||||
Sometimes a configure option needs additional information
|
||||
about where to find headers and libraries; quite often
|
||||
you can specify --enable-foo=option where option could be
|
||||
the path to where to find those files. If you want to
|
||||
specify a parameter and build it as shared, you can use
|
||||
this syntax instead: --enable-foo=shared,option
|
||||
|
||||
The same rules all apply to --with-foo and --without-foo;
|
||||
the only difference is the way the options are named;
|
||||
the convention is that --enable-foo means that you are
|
||||
switching on something that comes with PHP, whereas
|
||||
--with-foo means that you want to build in something
|
||||
external to PHP.
|
||||
|
||||
e. Building
|
||||
|
||||
Once you have successfully configured your build (make
|
||||
sure you read the output from the command to make sure
|
||||
it worked correctly), you can build the code; simply type
|
||||
|
||||
"nmake" at the command prompt, and it will build everthing
|
||||
you asked for.
|
||||
|
||||
Once the build has completed, you will find your binaries
|
||||
in the build dir determined by configure; this is typically
|
||||
Release_TS for release builds or Debug_TS for debug builds.
|
||||
If you build a non-thread-safe build, it will use Release
|
||||
or Debug to store the files. Also in this build dir you
|
||||
will find sub directories for each module that went into
|
||||
your PHP build. The files you'll want to keep are the
|
||||
.exe and .dll files directly in your build dir.
|
||||
|
||||
f. Cleaning Up
|
||||
|
||||
You can automatically delete everything that was built
|
||||
by running "nmake clean". This will delete everything
|
||||
that was put there when you ran nmake, including the
|
||||
.exe and .dll files.
|
||||
|
||||
g. Running the test suite
|
||||
|
||||
You can verify that your build is working well by running
|
||||
the regression test suite. You do this by typing
|
||||
"nmake test". You can specify the tests you want to run
|
||||
by defing the TESTS variable - if you wanted to run the
|
||||
sqlite test suite only, you would type
|
||||
"nmake /D TESTS=ext/sqlite/tests test"
|
||||
|
||||
h. Snapshot Building
|
||||
|
||||
If you want to set up an automated build that will tolerate
|
||||
breakages in some of the modules, you can use the
|
||||
--enable-snapshot-build configure option to generate a
|
||||
makefile optimized for that purpose. A snapshot build will
|
||||
switch the argument parser so that the default option for
|
||||
configure switches that your don't specify will be set
|
||||
to "shared". The effect of this is to turn on all options
|
||||
unless you explicitly disable them. When you have configured
|
||||
your snapshot build, you can use "nmake build-snap" to build
|
||||
everything, ignoring build errors in individual extensions
|
||||
or SAPI.
|
||||
|
||||
vim:tw=78:sw=1:ts=1:et
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
Using PHP 5 with the Zeus Web Server
|
||||
-----------------------------------
|
||||
|
||||
Zeus fully supports running PHP in combination with our
|
||||
webserver. There are three different interfaces that can be used to
|
||||
enable PHP:
|
||||
|
||||
* CGI
|
||||
* ISAPI
|
||||
* FastCGI
|
||||
|
||||
Of the three, we recommend using FastCGI, which has been tested and
|
||||
benchmarked as providing the best performance and reliability.
|
||||
|
||||
Full details of how to install PHP are available from our
|
||||
website, at:
|
||||
|
||||
http://support.zeus.com/products/php.html
|
||||
|
||||
If you have any problems, please check the support site for more
|
||||
up-to-date information and advice.
|
||||
|
||||
|
||||
Quick guide to installing CGI/FastCGI with Zeus
|
||||
-----------------------------------------------
|
||||
|
||||
Step 1 - Compile PHP as FastCGI.
|
||||
|
||||
Compile as follows:
|
||||
./configure --enable-fastcgi
|
||||
make
|
||||
|
||||
Note that PHP has many options to the configure script -
|
||||
e.g. --with-mysql. You will probably want to select your usual options
|
||||
before compiling; the above is just a bare minimum, for illustration.
|
||||
|
||||
After compilation finishes, you will be left with an executable
|
||||
program called 'php'. Copy this into your document root, under a
|
||||
dedicated FastCGI directory (e.g. $DOCROOT/fcgi-bin/php)
|
||||
|
||||
|
||||
Step 2 - configure Zeus
|
||||
|
||||
Four stages:
|
||||
- enable FastCGI
|
||||
- configure FastCGI
|
||||
- setup alias for FastCGI
|
||||
- setup alias for PHP
|
||||
|
||||
1) Using the admin server, go to the 'module configuration' page for
|
||||
your virtual server, and ensure that 'fastcgi' is enabled (select the
|
||||
tickbox to the left).
|
||||
|
||||
2) While we can run FastCGI's locally, there are known problems with
|
||||
some OS's (specifically, the communication between web server and
|
||||
FastCGI happens over a unix domain socket, and some OS's have trouble
|
||||
sustaining high connection rates over these sockets). So instead, we
|
||||
are going to set up the PHP FastCGI to run 'remotely' over localhost
|
||||
(this uses TCP sockets, which do not suffer this problem). Go to the
|
||||
'fastcgi configuration' page, and under 'add remote fastcgi':
|
||||
Add Remote FastCGI
|
||||
Docroot path /fcgi-bin/php
|
||||
Remote machine localhost:8002
|
||||
The first entry is where you saved PHP, above.
|
||||
The second entry is localhost:<any unused port>
|
||||
We will start the FastCGI listening on this port shortly.
|
||||
Click 'update' to commit these changes.
|
||||
|
||||
3) Go to the path mapping module and add an alias for FastCGI:
|
||||
Add Alias
|
||||
Docroot path /fcgi-bin
|
||||
Filesystem directory /path/to/docroot/fcgi-bin
|
||||
Alias type fastcgi
|
||||
Click 'update' to commit these changes
|
||||
|
||||
4) Also on the path mapping module, add a handler for PHP:
|
||||
Add handler
|
||||
File extension php
|
||||
Handler /fcgi-bin/php
|
||||
Click 'update' to commit these changes
|
||||
|
||||
Finally restart your virtual server for these changes to take effect.
|
||||
|
||||
|
||||
Step 3 - start PHP as a FastCGI runner
|
||||
|
||||
When you start PHP, it will pre-fork a given number of child processes
|
||||
to handle incoming PHP requests. Each process will handle a given
|
||||
number of requests before exiting (and being replaced by a newly
|
||||
forked process). You can control these two parameters by setting the
|
||||
following environment variables BEFORE starting the FastCGI runner:
|
||||
|
||||
PHP_FCGI_CHILDREN - the number of child processes to pre-fork. This
|
||||
variable MUST be set, if not then the PHP will not run as a FastCGI.
|
||||
We recommend a value of 8 for a fairly busy site. If you have many,
|
||||
long-running PHP scripts, then you may need to increase this further.
|
||||
|
||||
PHP_FCGI_MAX_REQUESTS - the number of requests each PHP child process
|
||||
handles before exiting. If not set, defaults to 500.
|
||||
|
||||
To start the FastCGI runner, execute '$ZEUSHOME/web/bin/fcgirunner
|
||||
8002 $DOCROOT/fcgi-bin/php'. Substitute the appropriate values for
|
||||
$ZEUSHOME and $DOCROOT; also substitute for 8002 the port you chose,
|
||||
above.
|
||||
|
||||
To stop the runner (e.g. to experiment with the above environment
|
||||
variables) you will need to manually stop and running PHP
|
||||
processes. (Use 'ps' and 'kill'). As it is PHP which is forking lots
|
||||
of children and not the runner, Zeus unfortunately cannot keep track
|
||||
of what processes are running, sorry. A typical command line may look
|
||||
like 'ps -efl | grep $DOCROOT/fcgi-bin/php | grep -v grep | awk
|
||||
'{print $4}' | xargs kill'
|
||||
@@ -1,193 +0,0 @@
|
||||
Input Filter Support in PHP 5
|
||||
-----------------------------
|
||||
|
||||
XSS (Cross Site Scripting) hacks are becoming more and more prevalent,
|
||||
and can be quite difficult to prevent. Whenever you accept user data
|
||||
and somehow display this data back to users, you are likely vulnerable
|
||||
to XSS hacks.
|
||||
|
||||
The Input Filter support in PHP 5 is aimed at providing the framework
|
||||
through which a company-wide or site-wide security policy can be
|
||||
enforced. It is implemented as a SAPI hook and is called from the
|
||||
treat_data and post handler functions. To implement your own security
|
||||
policy you will need to write a standard PHP extension.
|
||||
|
||||
A simple implementation might look like the following. This stores the
|
||||
original raw user data and adds a my_get_raw() function while the normal
|
||||
$_POST, $_GET and $_COOKIE arrays are only populated with stripped
|
||||
data. In this simple example all I am doing is calling strip_tags() on
|
||||
the data. If register_globals is turned on, the default globals that
|
||||
are created will be stripped ($foo) while a $RAW_foo is created with the
|
||||
original user input.
|
||||
|
||||
ZEND_BEGIN_MODULE_GLOBALS(my_input_filter)
|
||||
zval *post_array;
|
||||
zval *get_array;
|
||||
zval *cookie_array;
|
||||
ZEND_END_MODULE_GLOBALS(my_input_filter)
|
||||
|
||||
#ifdef ZTS
|
||||
#define IF_G(v) TSRMG(my_input_filter_globals_id, zend_my_input_filter_globals *, v)
|
||||
#else
|
||||
#define IF_G(v) (my_input_filter_globals.v)
|
||||
#endif
|
||||
|
||||
ZEND_DECLARE_MODULE_GLOBALS(my_input_filter)
|
||||
|
||||
function_entry my_input_filter_functions[] = {
|
||||
PHP_FE(my_get_raw, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
zend_module_entry my_input_filter_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"my_input_filter",
|
||||
my_input_filter_functions,
|
||||
PHP_MINIT(my_input_filter),
|
||||
PHP_MSHUTDOWN(my_input_filter),
|
||||
NULL,
|
||||
PHP_RSHUTDOWN(my_input_filter),
|
||||
PHP_MINFO(my_input_filter),
|
||||
"0.1",
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
PHP_MINIT_FUNCTION(my_input_filter)
|
||||
{
|
||||
ZEND_INIT_MODULE_GLOBALS(my_input_filter, php_my_input_filter_init_globals, NULL);
|
||||
|
||||
REGISTER_LONG_CONSTANT("POST", PARSE_POST, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("GET", PARSE_GET, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("COOKIE", PARSE_COOKIE, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
sapi_register_input_filter(my_sapi_input_filter);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_RSHUTDOWN_FUNCTION(my_input_filter)
|
||||
{
|
||||
if(IF_G(get_array)) {
|
||||
zval_ptr_dtor(&IF_G(get_array));
|
||||
IF_G(get_array) = NULL;
|
||||
}
|
||||
if(IF_G(post_array)) {
|
||||
zval_ptr_dtor(&IF_G(post_array));
|
||||
IF_G(post_array) = NULL;
|
||||
}
|
||||
if(IF_G(cookie_array)) {
|
||||
zval_ptr_dtor(&IF_G(cookie_array));
|
||||
IF_G(cookie_array) = NULL;
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_MINFO_FUNCTION(my_input_filter)
|
||||
{
|
||||
php_info_print_table_start();
|
||||
php_info_print_table_row( 2, "My Input Filter Support", "enabled" );
|
||||
php_info_print_table_row( 2, "Revision", "$Revision$");
|
||||
php_info_print_table_end();
|
||||
}
|
||||
|
||||
/* The filter handler. If you return 1 from it, then PHP also registers the
|
||||
* (modified) variable. Returning 0 prevents PHP from registering the variable;
|
||||
* you can use this if your filter already registers the variable under a
|
||||
* different name, or if you just don't want the variable registered at all. */
|
||||
SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
|
||||
{
|
||||
zval new_var;
|
||||
zval *array_ptr = NULL;
|
||||
char *raw_var;
|
||||
int var_len;
|
||||
|
||||
assert(*val != NULL);
|
||||
|
||||
switch(arg) {
|
||||
case PARSE_GET:
|
||||
if(!IF_G(get_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(get_array) = array_ptr;
|
||||
break;
|
||||
case PARSE_POST:
|
||||
if(!IF_G(post_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(post_array) = array_ptr;
|
||||
break;
|
||||
case PARSE_COOKIE:
|
||||
if(!IF_G(cookie_array)) {
|
||||
ALLOC_ZVAL(array_ptr);
|
||||
array_init(array_ptr);
|
||||
INIT_PZVAL(array_ptr);
|
||||
}
|
||||
IF_G(cookie_array) = array_ptr;
|
||||
break;
|
||||
}
|
||||
Z_STRLEN(new_var) = val_len;
|
||||
Z_STRVAL(new_var) = estrndup(*val, val_len);
|
||||
Z_TYPE(new_var) = IS_STRING;
|
||||
|
||||
var_len = strlen(var);
|
||||
raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
|
||||
strcpy(raw_var, "RAW_");
|
||||
strlcat(raw_var,var,var_len+5);
|
||||
|
||||
php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
|
||||
|
||||
php_strip_tags(*val, val_len, NULL, NULL, 0);
|
||||
|
||||
*new_val_len = strlen(*val);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PHP_FUNCTION(my_get_raw)
|
||||
{
|
||||
long arg;
|
||||
char *var;
|
||||
int var_len;
|
||||
zval **tmp;
|
||||
zval *array_ptr = NULL;
|
||||
HashTable *hash_ptr;
|
||||
char *raw_var;
|
||||
|
||||
if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(arg) {
|
||||
case PARSE_GET:
|
||||
array_ptr = IF_G(get_array);
|
||||
break;
|
||||
case PARSE_POST:
|
||||
array_ptr = IF_G(post_array);
|
||||
break;
|
||||
case PARSE_COOKIE:
|
||||
array_ptr = IF_G(post_array);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!array_ptr) RETURN_FALSE;
|
||||
|
||||
/*
|
||||
* I'm changing the variable name here because when running with register_globals on,
|
||||
* the variable will end up in the global symbol table
|
||||
*/
|
||||
raw_var = emalloc(var_len+5); /* RAW_ and a \0 */
|
||||
strcpy(raw_var, "RAW_");
|
||||
strlcat(raw_var,var,var_len+5);
|
||||
hash_ptr = HASH_OF(array_ptr);
|
||||
|
||||
if(zend_hash_find(hash_ptr, raw_var, var_len+5, (void **)&tmp) == SUCCESS) {
|
||||
*return_value = **tmp;
|
||||
zval_copy_ctor(return_value);
|
||||
} else {
|
||||
RETVAL_FALSE;
|
||||
}
|
||||
efree(raw_var);
|
||||
}
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
Things to do or at least think about doing in the future. Name in
|
||||
parenthesis means that person has taken on this project.
|
||||
|
||||
Zend
|
||||
----
|
||||
* Allow foreach ($array as $k => list($a, $b)) syntax for multi
|
||||
dimensional arrays.
|
||||
* Look at replacing c-lib call tolower().
|
||||
* Make hash API functions work with HASH_OF() to save time.
|
||||
* Add configure test to determine if dlsym() requires underscore and set
|
||||
DLSYM_NEEDS_UNDERSCORE accordingly. Perl and zsh have it in configure,
|
||||
for example. (DONE?)
|
||||
* Native large number support (probably with GNU GMP)
|
||||
* Const'ify APIs. Right now, many functions leave parameters untouched,
|
||||
but don't declare those as const. This makes interaction with other
|
||||
interfaces difficult which pass const parameters to us.
|
||||
|
||||
|
||||
global
|
||||
------
|
||||
* Make sure that all ZTS globals get destructed. Most ts_allocate_id()
|
||||
calls should have a dtor entry.
|
||||
* on some platforms unimplemented function will just do nothing
|
||||
(e.g. symlink) they should print a warning or not even be defined!
|
||||
(DONE ?)
|
||||
* --enable-all in configure. (--enable-shared=max ...)
|
||||
* make configure print out a summary when it's done (like XEmacs)
|
||||
* replace standard functions which work on static data with
|
||||
reentrancy-safe functions (DONE?).
|
||||
* make SAPI conform to CGI/1.1. Currently, all SAPI modules
|
||||
define REMOTE_ADDR etc. themselves and reach only various level
|
||||
of compliance.
|
||||
* see what functions might need to be changed to use HashPosition, so
|
||||
that the internal array pointer is not affected.
|
||||
* Move most extensions and PEAR packages out of the PHP CVS tree,
|
||||
include them again during release packaging.
|
||||
|
||||
Other
|
||||
* use thread-safe resolver functions (either require BIND 8 or adns).
|
||||
* implement javadoc based function docs template system.
|
||||
* provide optional IPv6 support (seems to be done?).
|
||||
* find a better way to implement script timeouts. SIGVTALRM is used
|
||||
by some POSIX threads implementations (i.e. OpenBSD) and is not
|
||||
available in ZTS mode.
|
||||
* Implement flush feature suitable for nested output buffers.
|
||||
|
||||
Streams
|
||||
-------
|
||||
* Route filestat.c through the wrapper layer; isolate the statcache code
|
||||
so that it is independent of php functions and can be applied to any
|
||||
stream/path.
|
||||
* Implement generalized connection pool for stated protocols such as
|
||||
ftp and http/1.1 (using keep-alive) to avoid having to negotiate
|
||||
new command/request stream for each subsequent call; Possibly store
|
||||
resources in contexts (creating a default context if necessary) to
|
||||
allow segmentation of connection pools.
|
||||
* Add a method to take ownership of the memory buffer in memory streams so
|
||||
that generating string values for zvals doesn't require an estrdup.
|
||||
* bundle and use curl lib for fopen wrapper.
|
||||
|
||||
documentation
|
||||
-------------
|
||||
* Add remarks in the documentation which functions are not implemented
|
||||
on win32.
|
||||
* Add remarks in the documentation which functions are not binary-safe.
|
||||
* Update curl documentation (DONE?)
|
||||
* Add developer documentation.
|
||||
* Add detailed documentation for Java extension.
|
||||
|
||||
ext/bz2
|
||||
-------
|
||||
* Add an ini directive to specify the size of decompression buffer.
|
||||
The default 4k is too small for large files and also requires much time
|
||||
for decompression. 40k is suitable for such files, however it may be too
|
||||
much under certain environments. There should be appropriate default
|
||||
settings for the various SAPI modules (e.g. apache and cli).
|
||||
|
||||
ext/curl
|
||||
--------
|
||||
* Have a warning scheme for when people use unsupported features.
|
||||
|
||||
ext/oci8
|
||||
--------
|
||||
* All OCIFetch*() functions should return 0 for no more data and false on
|
||||
error.
|
||||
* Have a flag that trims trailing spaces from CHAR fields on retrieval.
|
||||
* Make allow_call_time_pass_reference=Off working.
|
||||
* For additional todo information, see oci8.c, in ext/oci8
|
||||
|
||||
ext/odbc
|
||||
--------
|
||||
For PHP 4.3.0:
|
||||
* update all php_error calls to php_error_docref where valid
|
||||
* integrate EXPERIMENTAL ODBC update for use in PHP 5.0, use for
|
||||
testing purposes only.
|
||||
|
||||
For PHP 5.0.0
|
||||
* Activate EXPERIMENTAL ODBC codebase update
|
||||
|
||||
ext/pcre
|
||||
--------
|
||||
* Allow user to set PCRE_NOTEMPTY, PCRE_ANCHORED at execution time, maybe
|
||||
|
||||
ext/pcntl
|
||||
---------
|
||||
* Change internal callback handler to use TICKS
|
||||
* Remove all zend_extension code
|
||||
* Add object callback support to pcntl_signal()
|
||||
|
||||
ext/pgsql
|
||||
---------
|
||||
For PHP 4.3.0:
|
||||
* Add pg_metadata() with metadata cache feature.
|
||||
* Add pg_convert() to check and convert array value for query.
|
||||
* Add pg_insert/pg_update/pg_delete/pg_select for simple query.
|
||||
|
||||
ext/session
|
||||
-----------
|
||||
For PHP 4.3.0:
|
||||
* session_abort() to abort session. ie: Do not save session data.
|
||||
* Allow unset($_SESSION) or unset($HTTP_SESSION_VARS) to unset
|
||||
session vars regardless of register_globals setting.
|
||||
|
||||
Other:
|
||||
* Maybe implement finer-grained session variables that could be
|
||||
locked individually.
|
||||
* Write a network-transparent storage back-end with fallover
|
||||
facilities
|
||||
* Provide a callback facility which is executed upon encountering
|
||||
an unknown class name during deserialization
|
||||
|
||||
ext/standard
|
||||
------------
|
||||
* Add a version number to data serialized via serialize().
|
||||
* Possibly modify parsing of GPC data to automatically create arrays if
|
||||
variable name is seen more than once.
|
||||
* Implement regex-cache for url-functions.
|
||||
* Move socket related functions to fsock.c.
|
||||
|
||||
ext/wddx
|
||||
--------
|
||||
* See if we can support the remaining data types:
|
||||
dateTime
|
||||
binary
|
||||
|
||||
http://www.wddx.org/WDDX_SDK_10a/7__References/WDDX_DTD.htm
|
||||
(Andrei)
|
||||
|
||||
* implement wddx_packet_as_javascript(). (Andrei)
|
||||
|
||||
other cool stuff
|
||||
----------------
|
||||
* PVM extension
|
||||
|
||||
vim:et:sw=4:ts=4
|
||||
@@ -1,17 +0,0 @@
|
||||
Zend Engine
|
||||
-----------
|
||||
- Look at making zend_constant value member be a zval* instead of zval. (Andi)
|
||||
- Add the patch for referring to existing .ini vars in .ini files. (Andrei)
|
||||
- Implement inheritance rules for type hints. (Marcus)
|
||||
- Implement true/false/NULL as keywords (apply the patch). (Andi, Marcus)
|
||||
- Implement typehinting for arrays (apply the patch). (Andi, Marcus)
|
||||
- Find a keyword for the if-set-or operator (apply the patch). (Marcus, all)
|
||||
- Fix ZTS destruction (apply the patch). (Marcus)
|
||||
|
||||
Build System
|
||||
------------
|
||||
- Implement load order of built-in extensions (apply the patch). (Wez)
|
||||
|
||||
Standard Library
|
||||
----------------
|
||||
- Implement new time/date parsing and handling functions. (Derick)
|
||||
@@ -1,109 +0,0 @@
|
||||
Component: Zend Engine 2
|
||||
|
||||
Important stuff to finish: PPP members/PPP methods,
|
||||
support of overloaded extensions, possibly differentiate
|
||||
between class and namespace as discussed with Stig in
|
||||
Germany.
|
||||
Responsibility: Zeev, Andi, Stas
|
||||
Time frame: Couple of months for first part and extensions will be
|
||||
ongoing while PHP is being fixed.
|
||||
Things to leave for later versions: Native aggregation
|
||||
support, accessing static members via object and not class.
|
||||
|
||||
|
||||
Component: Aggregation
|
||||
Responsibility: Andi, Stig?
|
||||
Time frame: ?
|
||||
|
||||
|
||||
Component: Redesign of API Versioning
|
||||
Responsibility: ?
|
||||
Time frame: 1 month
|
||||
|
||||
|
||||
Component: Thread Safety
|
||||
Identify the extensions that are not thread safe by design
|
||||
or due to dependant libraries and identify them as such.
|
||||
If possible try to resolve thread safety issue via code
|
||||
improvements (if php code or patches will be accepted by
|
||||
library maintainers). For situations where thread safety
|
||||
cannot easily be acheived a flag in the extension API is
|
||||
set so PHP can identify non-thread safe extensions. These
|
||||
extensions will not be loaded in a ZTS compiled binary
|
||||
(unless it is cli/cgi).
|
||||
|
||||
Responsibility: ?
|
||||
Time frame: ?
|
||||
|
||||
|
||||
Component: SAPI
|
||||
Environment variables defined in the CGI spec need to be
|
||||
verified in each SAPI module that they conform to the CGI
|
||||
spec correctly. If they do not, the SAPI module needs to
|
||||
fix the variable prior to script execution. Having this
|
||||
conformity will aid in having PHP scripts run correctly
|
||||
under different sapi modules.
|
||||
|
||||
Responsibility: Shane Caraveo & each sapi module owner
|
||||
Timeframe: ? (but shouldn't be much effort, most modules are probably ok)
|
||||
|
||||
|
||||
Component: Input Filtering
|
||||
- Implement a SAPI input filter hook that will get called
|
||||
just before registering a variable in the
|
||||
treat_data/post_handler hooks. (done)
|
||||
- Make sure this is also done in mbstring (done)
|
||||
- Provide access functions, or perhaps a new
|
||||
$_RAW_GET/POST/Cookie set of superglobals to get at the
|
||||
unfiltered data
|
||||
- Provide a .ini directive which allows people to set their
|
||||
input filter to one of the built-in strip_tags,
|
||||
htmlspecialchars or whatever other internal function might
|
||||
be useful here.
|
||||
- (The main benefit of this is to make it easier for people
|
||||
to solve the XSS problem once and for all without having
|
||||
to go through every line of their code and adding input
|
||||
validation/filtering everywhere)
|
||||
Responsibility: Rasmus
|
||||
Timeframe: Yesterday
|
||||
|
||||
|
||||
Component: RPC Abstraction Layer
|
||||
Porting java, com, dotnet, xmlrpc, corba, soap and python, srm
|
||||
(are there more ?) to work with the new oo api and preferably
|
||||
by using ext/rpc.
|
||||
Responsibility: Harald
|
||||
Time frame: 2 months (but i have to wait for a few engine features first)
|
||||
|
||||
|
||||
Component: OO Extensions
|
||||
Each OO extension has to be revised and rewritten to fit into
|
||||
the new OO model. We should decide which extensions are a must
|
||||
to have for the release and which can be ported by the maintainer
|
||||
later as a separate pecl release.
|
||||
A list of extensions to be extended that have to be investigated:
|
||||
* browscap
|
||||
* aggregate
|
||||
* all *sql extensions (*_fetch_object)
|
||||
* domxml (seems like christian is rewriting it anyways)
|
||||
* ming
|
||||
Responsibility: Harald (, extension maintainers)
|
||||
|
||||
|
||||
Component: Abstract Data Types (ADT)
|
||||
Responsibility: Sterling, Harald
|
||||
Time frame: ?
|
||||
|
||||
|
||||
Component: Test Suite
|
||||
Extending the test suite with atleast a test for every
|
||||
function in an extension that doesn't require external
|
||||
resources. Also developing an automated test thing which
|
||||
cvs ups's, compiles and tests the build on a daily base on
|
||||
as much platforms/extensions as possible.
|
||||
|
||||
The test suite will also be extended to support threaded
|
||||
testing and testing for differing sapi modules (via http
|
||||
calls or other methods).
|
||||
Reponsibility: Derick (, extension maintainers)
|
||||
Time frame: 3 months
|
||||
@@ -1,3 +0,0 @@
|
||||
- clean up .cvsignores
|
||||
- purge Makefile.ins and replace PHP_EXTENSION in config.m4s
|
||||
with appropiate calls to PHP_NEW_EXTENSION
|
||||
@@ -1,26 +0,0 @@
|
||||
Copyright (c) 1999, 2000, Andi Gutmans, Sascha Schumann, Zeev Suraski.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
- Neither name of the copyright holders nor the names of their contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
|
||||
IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -1,6 +0,0 @@
|
||||
## process this file with automake to produce Makefile.am
|
||||
AUTOMAKE_OPTIONS=foreign
|
||||
noinst_LTLIBRARIES=libtsrm.la
|
||||
libtsrm_la_SOURCES = TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c
|
||||
|
||||
depend:
|
||||
@@ -1,2 +0,0 @@
|
||||
- Improve the lock in ts_resource_ex() in order to cover less code.
|
||||
This can probably be done by more careful hash table access
|
||||
-714
@@ -1,714 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Thread Safe Resource Manager |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1999, 2000, Andi Gutmans, Sascha Schumann, Zeev Suraski|
|
||||
| This source file is subject to the TSRM license, that is bundled |
|
||||
| with this package in the file LICENSE |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Zeev Suraski <zeev@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
#ifdef ZTS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
typedef struct _tsrm_tls_entry tsrm_tls_entry;
|
||||
|
||||
struct _tsrm_tls_entry {
|
||||
void **storage;
|
||||
int count;
|
||||
THREAD_T thread_id;
|
||||
tsrm_tls_entry *next;
|
||||
};
|
||||
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
ts_allocate_ctor ctor;
|
||||
ts_allocate_dtor dtor;
|
||||
#ifdef MBO_0
|
||||
int done;
|
||||
#endif
|
||||
} tsrm_resource_type;
|
||||
|
||||
|
||||
/* The memory manager table */
|
||||
static tsrm_tls_entry **tsrm_tls_table=NULL;
|
||||
static int tsrm_tls_table_size;
|
||||
static ts_rsrc_id id_count;
|
||||
|
||||
/* The resource sizes table */
|
||||
static tsrm_resource_type *resource_types_table=NULL;
|
||||
static int resource_types_table_size;
|
||||
|
||||
|
||||
static MUTEX_T tsmm_mutex; /* thread-safe memory manager mutex */
|
||||
|
||||
/* New thread handlers */
|
||||
static tsrm_thread_begin_func_t tsrm_new_thread_begin_handler;
|
||||
static tsrm_thread_end_func_t tsrm_new_thread_end_handler;
|
||||
|
||||
/* Debug support */
|
||||
int tsrm_error(int level, const char *format, ...);
|
||||
|
||||
/* Read a resource from a thread's resource storage */
|
||||
static int tsrm_error_level;
|
||||
static FILE *tsrm_error_file;
|
||||
|
||||
#if TSRM_DEBUG
|
||||
#define TSRM_ERROR(args) tsrm_error args
|
||||
#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
|
||||
{ \
|
||||
int unshuffled_offset = TSRM_UNSHUFFLE_RSRC_ID(offset); \
|
||||
\
|
||||
if (offset==0) { \
|
||||
return &array; \
|
||||
} else if ((unshuffled_offset)>=0 && (unshuffled_offset)<(range)) { \
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Successfully fetched resource id %d for thread id %ld - 0x%0.8X", \
|
||||
unshuffled_offset, (long) thread_resources->thread_id, array[unshuffled_offset])); \
|
||||
return array[unshuffled_offset]; \
|
||||
} else { \
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Resource id %d is out of range (%d..%d)", \
|
||||
unshuffled_offset, TSRM_SHUFFLE_RSRC_ID(0), TSRM_SHUFFLE_RSRC_ID(thread_resources->count-1))); \
|
||||
return NULL; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define TSRM_ERROR(args)
|
||||
#define TSRM_SAFE_RETURN_RSRC(array, offset, range) \
|
||||
if (offset==0) { \
|
||||
return &array; \
|
||||
} else { \
|
||||
return array[TSRM_UNSHUFFLE_RSRC_ID(offset)]; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PTHREADS)
|
||||
/* Thread local storage */
|
||||
static pthread_key_t tls_key;
|
||||
#elif defined(TSRM_ST)
|
||||
static int tls_key;
|
||||
#elif defined(TSRM_WIN32)
|
||||
static DWORD tls_key;
|
||||
#elif defined(BETHREADS)
|
||||
static int32 tls_key;
|
||||
#endif
|
||||
|
||||
/* Startup TSRM (call once for the entire process) */
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename)
|
||||
{
|
||||
#if defined(GNUPTH)
|
||||
pth_init();
|
||||
#elif defined(PTHREADS)
|
||||
pthread_key_create( &tls_key, 0 );
|
||||
#elif defined(TSRM_ST)
|
||||
st_init();
|
||||
st_key_create(&tls_key, 0);
|
||||
#elif defined(TSRM_WIN32)
|
||||
tls_key = TlsAlloc();
|
||||
#elif defined(BETHREADS)
|
||||
tls_key = tls_allocate();
|
||||
#endif
|
||||
|
||||
tsrm_error_file = stderr;
|
||||
tsrm_error_set(debug_level, debug_filename);
|
||||
tsrm_tls_table_size = expected_threads;
|
||||
|
||||
tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *));
|
||||
if (!tsrm_tls_table) {
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table"));
|
||||
return 0;
|
||||
}
|
||||
id_count=0;
|
||||
|
||||
resource_types_table_size = expected_resources;
|
||||
resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type));
|
||||
if (!resource_types_table) {
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table"));
|
||||
free(tsrm_tls_table);
|
||||
tsrm_tls_table = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
tsmm_mutex = tsrm_mutex_alloc();
|
||||
|
||||
tsrm_new_thread_begin_handler = tsrm_new_thread_end_handler = NULL;
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Started up TSRM, %d expected threads, %d expected resources", expected_threads, expected_resources));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Shutdown TSRM (call once for the entire process) */
|
||||
TSRM_API void tsrm_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (tsrm_tls_table) {
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
|
||||
|
||||
while (p) {
|
||||
int j;
|
||||
|
||||
next_p = p->next;
|
||||
for (j=0; j<p->count; j++) {
|
||||
if (p->storage[j]) {
|
||||
#ifdef MBO_0
|
||||
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
|
||||
resource_types_table[j].dtor(p->storage[j], &p->storage);
|
||||
}
|
||||
#endif
|
||||
free(p->storage[j]);
|
||||
}
|
||||
}
|
||||
free(p->storage);
|
||||
free(p);
|
||||
p = next_p;
|
||||
}
|
||||
}
|
||||
free(tsrm_tls_table);
|
||||
tsrm_tls_table = NULL;
|
||||
}
|
||||
if (resource_types_table) {
|
||||
free(resource_types_table);
|
||||
resource_types_table=NULL;
|
||||
}
|
||||
tsrm_mutex_free(tsmm_mutex);
|
||||
tsmm_mutex = NULL;
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
|
||||
if (tsrm_error_file!=stderr) {
|
||||
fclose(tsrm_error_file);
|
||||
}
|
||||
#if defined(GNUPTH)
|
||||
pth_kill();
|
||||
#elif defined(PTHREADS)
|
||||
pthread_setspecific(tls_key, 0);
|
||||
pthread_key_delete(tls_key);
|
||||
#elif defined(TSRM_WIN32)
|
||||
TlsFree(tls_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* allocates a new thread-safe-resource id */
|
||||
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor)
|
||||
{
|
||||
int i;
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtaining a new resource id, %d bytes", size));
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
|
||||
/* obtain a resource id */
|
||||
*rsrc_id = TSRM_SHUFFLE_RSRC_ID(id_count++);
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Obtained resource id %d", *rsrc_id));
|
||||
|
||||
/* store the new resource type in the resource sizes table */
|
||||
if (resource_types_table_size < id_count) {
|
||||
resource_types_table = (tsrm_resource_type *) realloc(resource_types_table, sizeof(tsrm_resource_type)*id_count);
|
||||
if (!resource_types_table) {
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate storage for resource"));
|
||||
*rsrc_id = 0;
|
||||
return 0;
|
||||
}
|
||||
resource_types_table_size = id_count;
|
||||
}
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].size = size;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].ctor = ctor;
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].dtor = dtor;
|
||||
#ifdef MBO_0
|
||||
resource_types_table[TSRM_UNSHUFFLE_RSRC_ID(*rsrc_id)].done = 0;
|
||||
#endif
|
||||
|
||||
/* enlarge the arrays for the already active threads */
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i];
|
||||
|
||||
while (p) {
|
||||
if (p->count < id_count) {
|
||||
int j;
|
||||
|
||||
p->storage = (void *) realloc(p->storage, sizeof(void *)*id_count);
|
||||
for (j=p->count; j<id_count; j++) {
|
||||
p->storage[j] = (void *) malloc(resource_types_table[j].size);
|
||||
if (resource_types_table[j].ctor) {
|
||||
resource_types_table[j].ctor(p->storage[j], &p->storage);
|
||||
}
|
||||
}
|
||||
p->count = id_count;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully allocated new resource id %d", *rsrc_id));
|
||||
return *rsrc_id;
|
||||
}
|
||||
|
||||
|
||||
static void allocate_new_resource(tsrm_tls_entry **thread_resources_ptr, THREAD_T thread_id)
|
||||
{
|
||||
int i;
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Creating data structures for thread %x", thread_id));
|
||||
(*thread_resources_ptr) = (tsrm_tls_entry *) malloc(sizeof(tsrm_tls_entry));
|
||||
(*thread_resources_ptr)->storage = (void **) malloc(sizeof(void *)*id_count);
|
||||
(*thread_resources_ptr)->count = id_count;
|
||||
(*thread_resources_ptr)->thread_id = thread_id;
|
||||
(*thread_resources_ptr)->next = NULL;
|
||||
|
||||
#if defined(PTHREADS)
|
||||
/* Set thread local storage to this new thread resources structure */
|
||||
pthread_setspecific(tls_key, (void *) *thread_resources_ptr);
|
||||
#elif defined(TSRM_ST)
|
||||
st_thread_setspecific(tls_key, (void *) *thread_resources_ptr);
|
||||
#elif defined(TSRM_WIN32)
|
||||
TlsSetValue(tls_key, (void *) *thread_resources_ptr);
|
||||
#elif defined(BETHREADS)
|
||||
tls_set(tls_key, (void*) *thread_resources_ptr);
|
||||
#endif
|
||||
|
||||
if (tsrm_new_thread_begin_handler) {
|
||||
tsrm_new_thread_begin_handler(thread_id, &((*thread_resources_ptr)->storage));
|
||||
}
|
||||
for (i=0; i<id_count; i++) {
|
||||
#if MBO_0
|
||||
if (resource_types_table[i].done) {
|
||||
(*thread_resources_ptr)->storage[i] = NULL;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
(*thread_resources_ptr)->storage[i] = (void *) malloc(resource_types_table[i].size);
|
||||
if (resource_types_table[i].ctor) {
|
||||
resource_types_table[i].ctor((*thread_resources_ptr)->storage[i], &(*thread_resources_ptr)->storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
|
||||
if (tsrm_new_thread_end_handler) {
|
||||
tsrm_new_thread_end_handler(thread_id, &((*thread_resources_ptr)->storage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* fetches the requested resource for the current thread */
|
||||
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id)
|
||||
{
|
||||
THREAD_T thread_id;
|
||||
int hash_value;
|
||||
tsrm_tls_entry *thread_resources;
|
||||
|
||||
#ifdef NETWARE
|
||||
/* The below if loop is added for NetWare to fix an abend while unloading PHP
|
||||
* when an Apache unload command is issued on the system console.
|
||||
* While exiting from PHP, at the end for some reason, this function is called
|
||||
* with tsrm_tls_table = NULL. When this happened, the server abends when
|
||||
* tsrm_tls_table is accessed since it is NULL.
|
||||
*/
|
||||
if(tsrm_tls_table) {
|
||||
#endif
|
||||
if (!th_id) {
|
||||
#if defined(PTHREADS)
|
||||
/* Fast path for looking up the resources for the current
|
||||
* thread. Its used by just about every call to
|
||||
* ts_resource_ex(). This avoids the need for a mutex lock
|
||||
* and our hashtable lookup.
|
||||
*/
|
||||
thread_resources = pthread_getspecific(tls_key);
|
||||
#elif defined(TSRM_ST)
|
||||
thread_resources = st_thread_getspecific(tls_key);
|
||||
#elif defined(TSRM_WIN32)
|
||||
thread_resources = TlsGetValue(tls_key);
|
||||
#elif defined(BETHREADS)
|
||||
thread_resources = (tsrm_tls_entry*)tls_get(tls_key);
|
||||
#else
|
||||
thread_resources = NULL;
|
||||
#endif
|
||||
if (thread_resources) {
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for current thread %d", id, (long) thread_resources->thread_id));
|
||||
/* Read a specific resource from the thread's resources.
|
||||
* This is called outside of a mutex, so have to be aware about external
|
||||
* changes to the structure as we read it.
|
||||
*/
|
||||
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
|
||||
}
|
||||
thread_id = tsrm_thread_id();
|
||||
} else {
|
||||
thread_id = *th_id;
|
||||
}
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Fetching resource id %d for thread %ld", id, (long) thread_id));
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
|
||||
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
|
||||
thread_resources = tsrm_tls_table[hash_value];
|
||||
|
||||
if (!thread_resources) {
|
||||
allocate_new_resource(&tsrm_tls_table[hash_value], thread_id);
|
||||
return ts_resource_ex(id, &thread_id);
|
||||
} else {
|
||||
do {
|
||||
if (thread_resources->thread_id == thread_id) {
|
||||
break;
|
||||
}
|
||||
if (thread_resources->next) {
|
||||
thread_resources = thread_resources->next;
|
||||
} else {
|
||||
allocate_new_resource(&thread_resources->next, thread_id);
|
||||
return ts_resource_ex(id, &thread_id);
|
||||
/*
|
||||
* thread_resources = thread_resources->next;
|
||||
* break;
|
||||
*/
|
||||
}
|
||||
} while (thread_resources);
|
||||
}
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
/* Read a specific resource from the thread's resources.
|
||||
* This is called outside of a mutex, so have to be aware about external
|
||||
* changes to the structure as we read it.
|
||||
*/
|
||||
TSRM_SAFE_RETURN_RSRC(thread_resources->storage, id, thread_resources->count);
|
||||
#ifdef NETWARE
|
||||
} /* if(tsrm_tls_table) */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* frees all resources allocated for the current thread */
|
||||
void ts_free_thread(void)
|
||||
{
|
||||
tsrm_tls_entry *thread_resources;
|
||||
int i;
|
||||
THREAD_T thread_id = tsrm_thread_id();
|
||||
int hash_value;
|
||||
tsrm_tls_entry *last=NULL;
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
|
||||
thread_resources = tsrm_tls_table[hash_value];
|
||||
|
||||
while (thread_resources) {
|
||||
if (thread_resources->thread_id == thread_id) {
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
if (resource_types_table[i].dtor) {
|
||||
resource_types_table[i].dtor(thread_resources->storage[i], &thread_resources->storage);
|
||||
}
|
||||
}
|
||||
for (i=0; i<thread_resources->count; i++) {
|
||||
free(thread_resources->storage[i]);
|
||||
}
|
||||
free(thread_resources->storage);
|
||||
if (last) {
|
||||
last->next = thread_resources->next;
|
||||
} else {
|
||||
tsrm_tls_table[hash_value] = thread_resources->next;
|
||||
}
|
||||
#if defined(PTHREADS)
|
||||
pthread_setspecific(tls_key, 0);
|
||||
#elif defined(TSRM_WIN32)
|
||||
TlsSetValue(tls_key, 0);
|
||||
#endif
|
||||
free(thread_resources);
|
||||
break;
|
||||
}
|
||||
if (thread_resources->next) {
|
||||
last = thread_resources;
|
||||
}
|
||||
thread_resources = thread_resources->next;
|
||||
}
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
}
|
||||
|
||||
|
||||
/* deallocates all occurrences of a given id */
|
||||
void ts_free_id(ts_rsrc_id id)
|
||||
{
|
||||
#ifdef MBO_0
|
||||
int i;
|
||||
int j = TSRM_UNSHUFFLE_RSRC_ID(id);
|
||||
|
||||
tsrm_mutex_lock(tsmm_mutex);
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Freeing resource id %d", id));
|
||||
|
||||
if (tsrm_tls_table) {
|
||||
for (i=0; i<tsrm_tls_table_size; i++) {
|
||||
tsrm_tls_entry *p = tsrm_tls_table[i];
|
||||
|
||||
while (p) {
|
||||
if (p->count > j && p->storage[j]) {
|
||||
if (resource_types_table && resource_types_table[j].dtor) {
|
||||
resource_types_table[j].dtor(p->storage[j], &p->storage);
|
||||
}
|
||||
free(p->storage[j]);
|
||||
p->storage[j] = NULL;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
resource_types_table[j].done = 1;
|
||||
|
||||
tsrm_mutex_unlock(tsmm_mutex);
|
||||
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Utility Functions
|
||||
*/
|
||||
|
||||
/* Obtain the current thread id */
|
||||
TSRM_API THREAD_T tsrm_thread_id(void)
|
||||
{
|
||||
#ifdef TSRM_WIN32
|
||||
return GetCurrentThreadId();
|
||||
#elif defined(NETWARE)
|
||||
/* There seems to be some problem with the LibC call: NXThreadGetId().
|
||||
* Due to this, the PHPMyAdmin application is abending in PHP calls.
|
||||
* Used the call, kCurrentThread instead and it works fine.
|
||||
*/
|
||||
/* return NXThreadGetId(); */
|
||||
return kCurrentThread();
|
||||
#elif defined(GNUPTH)
|
||||
return pth_self();
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_self();
|
||||
#elif defined(NSAPI)
|
||||
return systhread_current();
|
||||
#elif defined(PI3WEB)
|
||||
return PIThread_getCurrent();
|
||||
#elif defined(TSRM_ST)
|
||||
return st_thread_self();
|
||||
#elif defined(BETHREADS)
|
||||
return find_thread(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Allocate a mutex */
|
||||
TSRM_API MUTEX_T tsrm_mutex_alloc(void)
|
||||
{
|
||||
MUTEX_T mutexp;
|
||||
#ifdef NETWARE
|
||||
#ifndef USE_MPK
|
||||
/* To use the Recursive Mutex Locking of LibC */
|
||||
long flags = NX_MUTEX_RECURSIVE;
|
||||
NXHierarchy_t order = 0;
|
||||
NX_LOCK_INFO_ALLOC (lockInfo, "PHP-TSRM", 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
mutexp = malloc(sizeof(CRITICAL_SECTION));
|
||||
InitializeCriticalSection(mutexp);
|
||||
#elif defined(NETWARE)
|
||||
#ifdef USE_MPK
|
||||
mutexp = kMutexAlloc((BYTE*)"PHP-TSRM");
|
||||
#else
|
||||
mutexp = NXMutexAlloc(flags, order, &lockInfo);
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
mutexp = (MUTEX_T) malloc(sizeof(*mutexp));
|
||||
pth_mutex_init(mutexp);
|
||||
#elif defined(PTHREADS)
|
||||
mutexp = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
|
||||
pthread_mutex_init(mutexp,NULL);
|
||||
#elif defined(NSAPI)
|
||||
mutexp = crit_init();
|
||||
#elif defined(PI3WEB)
|
||||
mutexp = PIPlatform_allocLocalMutex();
|
||||
#elif defined(TSRM_ST)
|
||||
mutexp = st_mutex_new();
|
||||
#elif defined(BETHREADS)
|
||||
mutexp = (beos_ben*)malloc(sizeof(beos_ben));
|
||||
mutexp->ben = 0;
|
||||
mutexp->sem = create_sem(1, "PHP sempahore");
|
||||
#endif
|
||||
#ifdef THR_DEBUG
|
||||
printf("Mutex created thread: %d\n",mythreadid());
|
||||
#endif
|
||||
return( mutexp );
|
||||
}
|
||||
|
||||
|
||||
/* Free a mutex */
|
||||
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp)
|
||||
{
|
||||
if (mutexp) {
|
||||
#ifdef TSRM_WIN32
|
||||
DeleteCriticalSection(mutexp);
|
||||
free(mutexp);
|
||||
#elif defined(NETWARE)
|
||||
#ifdef USE_MPK
|
||||
kMutexFree(mutexp);
|
||||
#else
|
||||
NXMutexFree(mutexp);
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
free(mutexp);
|
||||
#elif defined(PTHREADS)
|
||||
pthread_mutex_destroy(mutexp);
|
||||
free(mutexp);
|
||||
#elif defined(NSAPI)
|
||||
crit_terminate(mutexp);
|
||||
#elif defined(PI3WEB)
|
||||
PISync_delete(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
st_mutex_destroy(mutexp);
|
||||
#elif defined(BETHREADS)
|
||||
delete_sem(mutexp->sem);
|
||||
free(mutexp);
|
||||
#endif
|
||||
}
|
||||
#ifdef THR_DEBUG
|
||||
printf("Mutex freed thread: %d\n",mythreadid());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Lock a mutex */
|
||||
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp)
|
||||
{
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex locked thread: %ld", tsrm_thread_id()));
|
||||
#ifdef TSRM_WIN32
|
||||
EnterCriticalSection(mutexp);
|
||||
return 1;
|
||||
#elif defined(NETWARE)
|
||||
#ifdef USE_MPK
|
||||
return kMutexLock(mutexp);
|
||||
#else
|
||||
return NXLock(mutexp);
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
return pth_mutex_acquire(mutexp, 0, NULL);
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_mutex_lock(mutexp);
|
||||
#elif defined(NSAPI)
|
||||
return crit_enter(mutexp);
|
||||
#elif defined(PI3WEB)
|
||||
return PISync_lock(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
return st_mutex_lock(mutexp);
|
||||
#elif defined(BETHREADS)
|
||||
if (atomic_add(&mutexp->ben, 1) != 0)
|
||||
return acquire_sem(mutexp->sem);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Unlock a mutex */
|
||||
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp)
|
||||
{
|
||||
TSRM_ERROR((TSRM_ERROR_LEVEL_INFO, "Mutex unlocked thread: %ld", tsrm_thread_id()));
|
||||
#ifdef TSRM_WIN32
|
||||
LeaveCriticalSection(mutexp);
|
||||
return 1;
|
||||
#elif defined(NETWARE)
|
||||
#ifdef USE_MPK
|
||||
return kMutexUnlock(mutexp);
|
||||
#else
|
||||
return NXUnlock(mutexp);
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
return pth_mutex_release(mutexp);
|
||||
#elif defined(PTHREADS)
|
||||
return pthread_mutex_unlock(mutexp);
|
||||
#elif defined(NSAPI)
|
||||
return crit_exit(mutexp);
|
||||
#elif defined(PI3WEB)
|
||||
return PISync_unlock(mutexp);
|
||||
#elif defined(TSRM_ST)
|
||||
return st_mutex_unlock(mutexp);
|
||||
#elif defined(BETHREADS)
|
||||
if (atomic_add(&mutexp->ben, -1) != 1)
|
||||
return release_sem(mutexp->sem);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler)
|
||||
{
|
||||
void *retval = (void *) tsrm_new_thread_begin_handler;
|
||||
|
||||
tsrm_new_thread_begin_handler = new_thread_begin_handler;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler)
|
||||
{
|
||||
void *retval = (void *) tsrm_new_thread_end_handler;
|
||||
|
||||
tsrm_new_thread_end_handler = new_thread_end_handler;
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Debug support
|
||||
*/
|
||||
|
||||
#if TSRM_DEBUG
|
||||
int tsrm_error(int level, const char *format, ...)
|
||||
{
|
||||
if (level<=tsrm_error_level) {
|
||||
va_list args;
|
||||
int size;
|
||||
|
||||
fprintf(tsrm_error_file, "TSRM: ");
|
||||
va_start(args, format);
|
||||
size = vfprintf(tsrm_error_file, format, args);
|
||||
va_end(args);
|
||||
fprintf(tsrm_error_file, "\n");
|
||||
fflush(tsrm_error_file);
|
||||
return size;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void tsrm_error_set(int level, char *debug_filename)
|
||||
{
|
||||
tsrm_error_level = level;
|
||||
|
||||
#if TSRM_DEBUG
|
||||
if (tsrm_error_file!=stderr) { /* close files opened earlier */
|
||||
fclose(tsrm_error_file);
|
||||
}
|
||||
|
||||
if (debug_filename) {
|
||||
tsrm_error_file = fopen(debug_filename, "w");
|
||||
if (!tsrm_error_file) {
|
||||
tsrm_error_file = stderr;
|
||||
}
|
||||
} else {
|
||||
tsrm_error_file = stderr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ZTS */
|
||||
-186
@@ -1,186 +0,0 @@
|
||||
# Microsoft Developer Studio Project File - Name="TSRM" - Package Owner=<4>
|
||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
||||
# ** DO NOT EDIT **
|
||||
|
||||
# TARGTYPE "Win32 (x86) Static Library" 0x0104
|
||||
|
||||
CFG=TSRM - Win32 Debug_TS
|
||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||
!MESSAGE use the Export Makefile command and run
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "TSRM.mak".
|
||||
!MESSAGE
|
||||
!MESSAGE You can specify a configuration when running NMAKE
|
||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||
!MESSAGE
|
||||
!MESSAGE NMAKE /f "TSRM.mak" CFG="TSRM - Win32 Debug_TS"
|
||||
!MESSAGE
|
||||
!MESSAGE Possible choices for configuration are:
|
||||
!MESSAGE
|
||||
!MESSAGE "TSRM - Win32 Debug_TS" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "TSRM - Win32 Release_TS" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "TSRM - Win32 Release_TS_inline" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE "TSRM - Win32 Release_TSDbg" (based on "Win32 (x86) Static Library")
|
||||
!MESSAGE
|
||||
|
||||
# Begin Project
|
||||
# PROP AllowPerConfigDependencies 0
|
||||
# PROP Scc_ProjName ""
|
||||
# PROP Scc_LocalPath ""
|
||||
CPP=cl.exe
|
||||
RSC=rc.exe
|
||||
|
||||
!IF "$(CFG)" == "TSRM - Win32 Debug_TS"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 1
|
||||
# PROP BASE Output_Dir "TSRM___Win32_Debug_TS"
|
||||
# PROP BASE Intermediate_Dir "TSRM___Win32_Debug_TS"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 1
|
||||
# PROP Output_Dir "Debug_TS"
|
||||
# PROP Intermediate_Dir "Debug_TS"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I "C:\Projects\TSRM" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "." /D "_DEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=1 /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x40d /d "_DEBUG"
|
||||
# ADD RSC /l 0x40d /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TS"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "TSRM___Win32_Release_TS"
|
||||
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TS"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release_TS"
|
||||
# PROP Intermediate_Dir "Release_TS"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
|
||||
# ADD BASE RSC /l 0x40d /d "NDEBUG"
|
||||
# ADD RSC /l 0x40d /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TS_inline"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "TSRM___Win32_Release_TS_inline"
|
||||
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TS_inline"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release_TS_inline"
|
||||
# PROP Intermediate_Dir "Release_TS_inline"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D "TSRM_EXPORTS" /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
|
||||
# ADD BASE RSC /l 0x40d /d "NDEBUG"
|
||||
# ADD RSC /l 0x40d /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ELSEIF "$(CFG)" == "TSRM - Win32 Release_TSDbg"
|
||||
|
||||
# PROP BASE Use_MFC 0
|
||||
# PROP BASE Use_Debug_Libraries 0
|
||||
# PROP BASE Output_Dir "TSRM___Win32_Release_TSDbg"
|
||||
# PROP BASE Intermediate_Dir "TSRM___Win32_Release_TSDbg"
|
||||
# PROP BASE Target_Dir ""
|
||||
# PROP Use_MFC 0
|
||||
# PROP Use_Debug_Libraries 0
|
||||
# PROP Output_Dir "Release_TSDbg"
|
||||
# PROP Intermediate_Dir "Release_TSDbg"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
|
||||
# ADD CPP /nologo /MD /W3 /GX /Zi /Od /I "." /D "NDEBUG" /D "ZTS" /D "_LIB" /D "TSRM_EXPORTS" /D "WIN32" /D "_MBCS" /D TSRM_DEBUG=0 /YX /FD /c
|
||||
# ADD BASE RSC /l 0x40d /d "NDEBUG"
|
||||
# ADD RSC /l 0x40d /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
# ADD BASE BSC32 /nologo
|
||||
# ADD BSC32 /nologo
|
||||
LIB32=link.exe -lib
|
||||
# ADD BASE LIB32 /nologo
|
||||
# ADD LIB32 /nologo
|
||||
|
||||
!ENDIF
|
||||
|
||||
# Begin Target
|
||||
|
||||
# Name "TSRM - Win32 Debug_TS"
|
||||
# Name "TSRM - Win32 Release_TS"
|
||||
# Name "TSRM - Win32 Release_TS_inline"
|
||||
# Name "TSRM - Win32 Release_TSDbg"
|
||||
# Begin Group "Source Files"
|
||||
|
||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\TSRM.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_strtok_r.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_virtual_cwd.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_win32.c
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "Header Files"
|
||||
|
||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\readdir.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\TSRM.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_config.w32.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_config_common.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_strtok_r.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_virtual_cwd.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\tsrm_win32.h
|
||||
# End Source File
|
||||
# End Group
|
||||
# End Target
|
||||
# End Project
|
||||
-177
@@ -1,177 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| Thread Safe Resource Manager |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1999, 2000, Andi Gutmans, Sascha Schumann, Zeev Suraski|
|
||||
| This source file is subject to the TSRM license, that is bundled |
|
||||
| with this package in the file LICENSE |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Zeev Suraski <zeev@zend.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#ifndef TSRM_H
|
||||
#define TSRM_H
|
||||
|
||||
/* #ifndef WIN32 */
|
||||
#if !defined(WIN32) && !defined(NETWARE)
|
||||
# include "tsrm_config.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define TSRM_WIN32
|
||||
# include "tsrm_config.w32.h"
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# ifdef TSRM_EXPORTS
|
||||
# define TSRM_API __declspec(dllexport)
|
||||
# else
|
||||
# define TSRM_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define TSRM_API
|
||||
#endif
|
||||
|
||||
/* Only compile multi-threading functions if we're in ZTS mode */
|
||||
#ifdef ZTS
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# ifndef TSRM_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# endif
|
||||
# include <windows.h>
|
||||
# include <shellapi.h>
|
||||
#elif defined(NETWARE)
|
||||
# include <nks/thread.h>
|
||||
#ifdef USE_MPK
|
||||
# include <mpklib4php.h>
|
||||
#else
|
||||
# include <nks/synch.h>
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
# include <pth.h>
|
||||
#elif defined(PTHREADS)
|
||||
# include <pthread.h>
|
||||
#elif defined(TSRM_ST)
|
||||
# include <st.h>
|
||||
#elif defined(BETHREADS)
|
||||
#include <kernel/OS.h>
|
||||
#include <TLS.h>
|
||||
#endif
|
||||
|
||||
typedef int ts_rsrc_id;
|
||||
|
||||
/* Define THREAD_T and MUTEX_T */
|
||||
#ifdef TSRM_WIN32
|
||||
# define THREAD_T DWORD
|
||||
# define MUTEX_T CRITICAL_SECTION *
|
||||
#elif defined(NETWARE)
|
||||
# define THREAD_T NXThreadId_t
|
||||
#ifdef USE_MPK
|
||||
# define MUTEX_T MUTEX
|
||||
#else
|
||||
# define MUTEX_T NXMutex_t *
|
||||
#endif
|
||||
#elif defined(GNUPTH)
|
||||
# define THREAD_T pth_t
|
||||
# define MUTEX_T pth_mutex_t *
|
||||
#elif defined(PTHREADS)
|
||||
# define THREAD_T pthread_t
|
||||
# define MUTEX_T pthread_mutex_t *
|
||||
#elif defined(NSAPI)
|
||||
# define THREAD_T SYS_THREAD
|
||||
# define MUTEX_T CRITICAL
|
||||
#elif defined(PI3WEB)
|
||||
# define THREAD_T PIThread *
|
||||
# define MUTEX_T PISync *
|
||||
#elif defined(TSRM_ST)
|
||||
# define THREAD_T st_thread_t
|
||||
# define MUTEX_T st_mutex_t
|
||||
#elif defined(BETHREADS)
|
||||
# define THREAD_T thread_id
|
||||
typedef struct {
|
||||
sem_id sem;
|
||||
int32 ben;
|
||||
} beos_ben;
|
||||
# define MUTEX_T beos_ben *
|
||||
#endif
|
||||
|
||||
typedef void (*ts_allocate_ctor)(void *, void ***);
|
||||
typedef void (*ts_allocate_dtor)(void *, void ***);
|
||||
|
||||
#define THREAD_HASH_OF(thr,ts) (unsigned long)thr%(unsigned long)ts
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* startup/shutdown */
|
||||
TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename);
|
||||
TSRM_API void tsrm_shutdown(void);
|
||||
|
||||
/* allocates a new thread-safe-resource id */
|
||||
TSRM_API ts_rsrc_id ts_allocate_id(ts_rsrc_id *rsrc_id, size_t size, ts_allocate_ctor ctor, ts_allocate_dtor dtor);
|
||||
|
||||
/* fetches the requested resource for the current thread */
|
||||
TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
|
||||
#define ts_resource(id) ts_resource_ex(id, NULL)
|
||||
|
||||
/* frees all resources allocated for the current thread */
|
||||
TSRM_API void ts_free_thread(void);
|
||||
|
||||
/* deallocates all occurrences of a given id */
|
||||
TSRM_API void ts_free_id(ts_rsrc_id id);
|
||||
|
||||
|
||||
/* Debug support */
|
||||
#define TSRM_ERROR_LEVEL_ERROR 1
|
||||
#define TSRM_ERROR_LEVEL_CORE 2
|
||||
#define TSRM_ERROR_LEVEL_INFO 3
|
||||
|
||||
typedef void (*tsrm_thread_begin_func_t)(THREAD_T thread_id, void ***tsrm_ls);
|
||||
typedef void (*tsrm_thread_end_func_t)(THREAD_T thread_id, void ***tsrm_ls);
|
||||
|
||||
|
||||
TSRM_API int tsrm_error(int level, const char *format, ...);
|
||||
TSRM_API void tsrm_error_set(int level, char *debug_filename);
|
||||
|
||||
/* utility functions */
|
||||
TSRM_API THREAD_T tsrm_thread_id(void);
|
||||
TSRM_API MUTEX_T tsrm_mutex_alloc(void);
|
||||
TSRM_API void tsrm_mutex_free(MUTEX_T mutexp);
|
||||
TSRM_API int tsrm_mutex_lock(MUTEX_T mutexp);
|
||||
TSRM_API int tsrm_mutex_unlock(MUTEX_T mutexp);
|
||||
|
||||
TSRM_API void *tsrm_set_new_thread_begin_handler(tsrm_thread_begin_func_t new_thread_begin_handler);
|
||||
TSRM_API void *tsrm_set_new_thread_end_handler(tsrm_thread_end_func_t new_thread_end_handler);
|
||||
|
||||
#define TSRM_SHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)+1)
|
||||
#define TSRM_UNSHUFFLE_RSRC_ID(rsrc_id) ((rsrc_id)-1)
|
||||
|
||||
#define TSRMLS_FETCH() void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL)
|
||||
#define TSRMLS_FETCH_FROM_CTX(ctx) void ***tsrm_ls = (void ***) ctx
|
||||
#define TSRMLS_SET_CTX(ctx) (void ***) ctx = tsrm_ls
|
||||
#define TSRMG(id, type, element) (((type) (*((void ***) tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->element)
|
||||
#define TSRMLS_D void ***tsrm_ls
|
||||
#define TSRMLS_DC , TSRMLS_D
|
||||
#define TSRMLS_C tsrm_ls
|
||||
#define TSRMLS_CC , TSRMLS_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* non ZTS */
|
||||
|
||||
#define TSRMLS_FETCH()
|
||||
#define TSRMLS_FETCH_FROM_CTX(ctx)
|
||||
#define TSRMLS_SET_CTX(ctx)
|
||||
#define TSRMLS_D void
|
||||
#define TSRMLS_DC
|
||||
#define TSRMLS_C
|
||||
#define TSRMLS_CC
|
||||
|
||||
#endif /* ZTS */
|
||||
|
||||
#endif /* TSRM_H */
|
||||
@@ -1 +0,0 @@
|
||||
#undef PTHREADS
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
AC_DEFUN(AM_SET_LIBTOOL_VARIABLE,[
|
||||
LIBTOOL='$(SHELL) $(top_builddir)/libtool $1'
|
||||
])
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
# Makefile to generate build tools
|
||||
#
|
||||
# Standard usage:
|
||||
# make -f build.mk
|
||||
#
|
||||
# Written by Sascha Schumann
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
LT_TARGETS = ltmain.sh ltconfig
|
||||
|
||||
config_h_in = tsrm_config.h.in
|
||||
|
||||
makefile_am_files = Makefile.am
|
||||
makefile_in_files = $(makefile_am_files:.am=.in)
|
||||
makefile_files = $(makefile_am_files:e.am=e)
|
||||
|
||||
targets = $(makefile_in_files) $(LT_TARGETS) configure $(config_h_in)
|
||||
|
||||
all: $(targets)
|
||||
|
||||
clean:
|
||||
rm -f $(targets)
|
||||
|
||||
$(LT_TARGETS):
|
||||
rm -f $(LT_TARGETS)
|
||||
libtoolize --automake $(AMFLAGS) -f
|
||||
|
||||
$(makefile_in_files): $(makefile_am_files)
|
||||
automake -a -i $(AMFLAGS) $(makefile_files)
|
||||
|
||||
aclocal.m4: configure.in acinclude.m4
|
||||
aclocal
|
||||
|
||||
$(config_h_in): configure.in acconfig.h
|
||||
# explicitly remove target since autoheader does not seem to work
|
||||
# correctly otherwise (timestamps are not updated)
|
||||
@rm -f $@
|
||||
autoheader
|
||||
|
||||
configure: aclocal.m4 configure.in
|
||||
autoconf
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
--copy)
|
||||
automake_flags=--copy
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
|
||||
libtoolize --force --automake $automake_flags
|
||||
|
||||
mv aclocal.m4 aclocal.m4.old 2>/dev/null
|
||||
aclocal
|
||||
if cmp aclocal.m4.old aclocal.m4 > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}aclocal.m4"
|
||||
mv aclocal.m4.old aclocal.m4
|
||||
else
|
||||
echo "buildconf: created or modified ${1}aclocal.m4"
|
||||
fi
|
||||
|
||||
autoheader
|
||||
|
||||
automake --add-missing --include-deps $automake_flags
|
||||
|
||||
mv configure configure.old 2>/dev/null
|
||||
autoconf
|
||||
if cmp configure.old configure > /dev/null 2>&1; then
|
||||
echo "buildconf: keeping ${1}configure"
|
||||
mv configure.old configure
|
||||
else
|
||||
echo "buildconf: created or modified ${1}configure"
|
||||
fi
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// vim:ft=javascript
|
||||
// $Id$
|
||||
|
||||
if (CHECK_HEADER_ADD_INCLUDE("NewAPIs.h", "CFLAGS_PHP", php_usual_include_suspects)) {
|
||||
// Need to add the flag directly, since TSRM doesn't include the config
|
||||
// header
|
||||
ADD_FLAG("CFLAGS_PHP", "/DHAVE_NEWAPIS_H=1");
|
||||
}
|
||||
ADD_SOURCES("TSRM", "TSRM.c tsrm_strtok_r.c tsrm_virtual_cwd.c tsrm_win32.c");
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
dnl $Id$
|
||||
dnl
|
||||
dnl Minimalistic configure.in for TSRM.
|
||||
dnl
|
||||
|
||||
AC_INIT(TSRM.c)
|
||||
AM_INIT_AUTOMAKE(TSRM, 1.0, nodefine)
|
||||
AM_CONFIG_HEADER(tsrm_config.h)
|
||||
|
||||
sinclude(tsrm.m4)
|
||||
|
||||
TSRM_BASIC_CHECKS
|
||||
TSRM_THREADS_CHECKS
|
||||
|
||||
AM_PROG_LIBTOOL
|
||||
if test "$enable_debug" != "yes"; then
|
||||
AM_SET_LIBTOOL_VARIABLE([--silent])
|
||||
fi
|
||||
|
||||
dnl TSRM_PTHREAD
|
||||
|
||||
AC_CHECK_HEADERS(
|
||||
utime.h \
|
||||
dirent.h \
|
||||
stdarg.h \
|
||||
alloca.h \
|
||||
unistd.h \
|
||||
limits.h
|
||||
)
|
||||
|
||||
AC_OUTPUT(Makefile)
|
||||
@@ -1,44 +0,0 @@
|
||||
#ifndef READDIR_H
|
||||
#define READDIR_H
|
||||
|
||||
|
||||
/*
|
||||
* Structures and types used to implement opendir/readdir/closedir
|
||||
* on Windows 95/NT.
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
/* struct dirent - same as Unix */
|
||||
|
||||
struct dirent {
|
||||
long d_ino; /* inode (always 1 in WIN32) */
|
||||
off_t d_off; /* offset to this dirent */
|
||||
unsigned short d_reclen; /* length of d_name */
|
||||
char d_name[_MAX_FNAME + 1]; /* filename (null terminated) */
|
||||
};
|
||||
|
||||
|
||||
/* typedef DIR - not the same as Unix */
|
||||
typedef struct {
|
||||
long handle; /* _findfirst/_findnext handle */
|
||||
short offset; /* offset into directory */
|
||||
short finished; /* 1 if there are not more files */
|
||||
struct _finddata_t fileinfo; /* from _findfirst/_findnext */
|
||||
char *dir; /* the dir we are reading */
|
||||
struct dirent dent; /* the dirent to return */
|
||||
} DIR;
|
||||
|
||||
/* Function prototypes */
|
||||
DIR *opendir(const char *);
|
||||
struct dirent *readdir(DIR *);
|
||||
int readdir_r(DIR *, struct dirent *, struct dirent **);
|
||||
int closedir(DIR *);
|
||||
void rewinddir(DIR *);
|
||||
|
||||
|
||||
#endif /* READDIR_H */
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
dnl Copyright (c) 1999, 2000 Sascha Schumann. All rights reserved.
|
||||
dnl
|
||||
dnl Redistribution and use in source and binary forms, with or without
|
||||
dnl modification, are permitted provided that the following conditions
|
||||
dnl are met:
|
||||
dnl
|
||||
dnl 1. Redistributions of source code must retain the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer.
|
||||
dnl
|
||||
dnl 2. Redistributions in binary form must reproduce the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer in
|
||||
dnl the documentation and/or other materials provided with the
|
||||
dnl distribution.
|
||||
dnl
|
||||
dnl THIS SOFTWARE IS PROVIDED BY SASCHA SCHUMANN ``AS IS'' AND ANY
|
||||
dnl EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
dnl IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
dnl PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SASCHA SCHUMANN OR
|
||||
dnl HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
dnl NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
dnl LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
dnl HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
dnl STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
dnl ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
dnl OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
dnl
|
||||
dnl PTHREADS_FLAGS
|
||||
dnl
|
||||
dnl Set some magic defines to achieve POSIX threads conformance
|
||||
dnl
|
||||
AC_DEFUN(PTHREADS_FLAGS,[
|
||||
if test -z "$host_alias" && test -n "$host"; then
|
||||
host_alias=$host
|
||||
fi
|
||||
if test -z "$host_alias"; then
|
||||
AC_MSG_ERROR(host_alias is not set. Make sure to run config.guess)
|
||||
fi
|
||||
case $host_alias in
|
||||
*solaris*)
|
||||
PTHREAD_FLAGS="-D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT";;
|
||||
*freebsd*)
|
||||
PTHREAD_FLAGS="-D_REENTRANT -D_THREAD_SAFE";;
|
||||
*linux*)
|
||||
PTHREAD_FLAGS=-D_REENTRANT;;
|
||||
*aix*)
|
||||
PTHREAD_FLAGS=-D_THREAD_SAFE;;
|
||||
*irix*)
|
||||
PTHREAD_FLAGS=-D_POSIX_THREAD_SAFE_FUNCTIONS;;
|
||||
*hpux*)
|
||||
PTHREAD_FLAGS=-D_REENTRANT;;
|
||||
*sco*)
|
||||
PTHREAD_FLAGS=-D_REENTRANT;;
|
||||
dnl Solves sigwait() problem, creates problems with u_long etc.
|
||||
dnl PTHREAD_FLAGS="-D_REENTRANT -D_XOPEN_SOURCE=500 -D_POSIX_C_SOURCE=199506 -D_XOPEN_SOURCE_EXTENDED=1";;
|
||||
esac
|
||||
|
||||
if test -n "$PTHREAD_FLAGS"; then
|
||||
CPPFLAGS="$CPPFLAGS $PTHREAD_FLAGS"
|
||||
fi
|
||||
])dnl
|
||||
dnl
|
||||
dnl PTHREADS_CHECK_COMPILE
|
||||
dnl
|
||||
dnl Check whether the current setup can use POSIX threads calls
|
||||
dnl
|
||||
AC_DEFUN(PTHREADS_CHECK_COMPILE, [
|
||||
AC_TRY_RUN( [
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *thread_routine(void *data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t thd;
|
||||
pthread_mutexattr_t mattr;
|
||||
int data = 1;
|
||||
pthread_mutexattr_init(&mattr);
|
||||
return pthread_create(&thd, NULL, thread_routine, &data);
|
||||
} ], [
|
||||
pthreads_working=yes
|
||||
], [
|
||||
pthreads_working=no
|
||||
], pthreads_working=no ) ] )dnl
|
||||
dnl
|
||||
dnl PTHREADS_CHECK()
|
||||
dnl
|
||||
dnl Try to find a way to enable POSIX threads
|
||||
dnl
|
||||
dnl Magic flags
|
||||
dnl -kthread gcc (FreeBSD)
|
||||
dnl -Kthread UDK cc (UnixWare)
|
||||
dnl -mt WorkShop cc (Solaris)
|
||||
dnl -mthreads gcc (AIX)
|
||||
dnl -pthread gcc (Linux, FreeBSD, NetBSD, OpenBSD)
|
||||
dnl -pthreads gcc (Solaris)
|
||||
dnl -qthreaded AIX cc V5
|
||||
dnl -threads gcc (HP-UX)
|
||||
dnl
|
||||
AC_DEFUN(PTHREADS_CHECK,[
|
||||
|
||||
if test "$beos_threads" = "1"; then
|
||||
pthreads_working="yes"
|
||||
ac_cv_pthreads_cflags=""
|
||||
else
|
||||
save_CFLAGS=$CFLAGS
|
||||
save_LIBS=$LIBS
|
||||
PTHREADS_ASSIGN_VARS
|
||||
PTHREADS_CHECK_COMPILE
|
||||
LIBS=$save_LIBS
|
||||
CFLAGS=$save_CFLAGS
|
||||
|
||||
AC_CACHE_CHECK(for pthreads_cflags,ac_cv_pthreads_cflags,[
|
||||
ac_cv_pthreads_cflags=
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
for flag in -kthread -pthread -pthreads -mthreads -Kthread -threads -mt -qthreaded; do
|
||||
ac_save=$CFLAGS
|
||||
CFLAGS="$CFLAGS $flag"
|
||||
PTHREADS_CHECK_COMPILE
|
||||
CFLAGS=$ac_save
|
||||
if test "$pthreads_working" = "yes"; then
|
||||
ac_cv_pthreads_cflags=$flag
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_CACHE_CHECK(for pthreads_lib, ac_cv_pthreads_lib,[
|
||||
ac_cv_pthreads_lib=
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
for lib in pthread pthreads c_r; do
|
||||
ac_save=$LIBS
|
||||
LIBS="$LIBS -l$lib"
|
||||
PTHREADS_CHECK_COMPILE
|
||||
LIBS=$ac_save
|
||||
if test "$pthreads_working" = "yes"; then
|
||||
ac_cv_pthreads_lib=$lib
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$pthreads_working" = "yes"; then
|
||||
threads_result="POSIX-Threads found"
|
||||
else
|
||||
threads_result="POSIX-Threads not found"
|
||||
fi
|
||||
])dnl
|
||||
dnl
|
||||
dnl
|
||||
AC_DEFUN(PTHREADS_ASSIGN_VARS,[
|
||||
if test -n "$ac_cv_pthreads_lib"; then
|
||||
LIBS="$LIBS -l$ac_cv_pthreads_lib"
|
||||
fi
|
||||
|
||||
if test -n "$ac_cv_pthreads_cflags"; then
|
||||
CFLAGS="$CFLAGS $ac_cv_pthreads_cflags"
|
||||
fi
|
||||
])dnl
|
||||
-129
@@ -1,129 +0,0 @@
|
||||
|
||||
dnl TSRM_CHECK_GCC_ARG(ARG, ACTION-IF-FOUND, ACTION-IF-NOT_FOUND)
|
||||
AC_DEFUN(TSRM_CHECK_GCC_ARG,[
|
||||
gcc_arg_name=[ac_cv_gcc_arg]translit($1,A-Z-,a-z_)
|
||||
AC_CACHE_CHECK([whether $CC supports $1], [ac_cv_gcc_arg]translit($1,A-Z-,a-z_), [
|
||||
echo 'void somefunc() { };' > conftest.c
|
||||
cmd='$CC $1 -c conftest.c'
|
||||
if eval $cmd 2>&1 | egrep -e $1 >/dev/null ; then
|
||||
ac_result=no
|
||||
else
|
||||
ac_result=yes
|
||||
fi
|
||||
eval $gcc_arg_name=$ac_result
|
||||
rm -f conftest.*
|
||||
])
|
||||
if eval test "\$$gcc_arg_name" = "yes"; then
|
||||
$2
|
||||
else
|
||||
:
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(TSRM_BASIC_CHECKS,[
|
||||
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
dnl AC_REQUIRE([AM_PROG_CC_STDC])dnl
|
||||
AC_REQUIRE([AC_PROG_CC_C_O])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
|
||||
AC_CHECK_HEADERS(stdarg.h)
|
||||
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(TSRM_CHECK_PTH,[
|
||||
|
||||
AC_MSG_CHECKING(for GNU Pth)
|
||||
PTH_PREFIX="`$1 --prefix`"
|
||||
if test -z "$PTH_PREFIX"; then
|
||||
AC_MSG_RESULT(Please check your Pth installation)
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS `$1 --cflags`"
|
||||
LDFLAGS="$LDFLAGS `$1 --ldflags`"
|
||||
LIBS="$LIBS `$1 --libs`"
|
||||
|
||||
AC_DEFINE(GNUPTH, 1, [Whether you use GNU Pth])
|
||||
AC_MSG_RESULT(yes - installed in $PTH_PREFIX)
|
||||
|
||||
])
|
||||
|
||||
AC_DEFUN(TSRM_CHECK_ST,[
|
||||
if test -r "$1/include/st.h"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$1/include"
|
||||
LDFLAGS="$LDFLAGS -L$1/lib"
|
||||
elif test -r "$1/st.h"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$1"
|
||||
LDFLAGS="$LDFLAGS -L$1"
|
||||
fi
|
||||
AC_CHECK_HEADERS(st.h,[],[
|
||||
AC_MSG_ERROR([Sorry[,] I was unable to locate the State Threads header file. Please specify the prefix using --with-tsrm-st=/prefix])
|
||||
])
|
||||
LIBS="$LIBS -lst"
|
||||
AC_MSG_CHECKING(for SGI's State Threads)
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(TSRM_ST, 1, [ ])
|
||||
])
|
||||
|
||||
sinclude(threads.m4)
|
||||
sinclude(TSRM/threads.m4)
|
||||
|
||||
AC_DEFUN(TSRM_CHECK_PTHREADS,[
|
||||
|
||||
PTHREADS_CHECK
|
||||
|
||||
if test "$beos_threads" = "1"; then
|
||||
AC_DEFINE(BETHREADS, 1, Whether to use native BeOS threads)
|
||||
else
|
||||
if test "$pthreads_working" != "yes"; then
|
||||
AC_MSG_ERROR(Your system seems to lack POSIX threads.)
|
||||
fi
|
||||
|
||||
AC_DEFINE(PTHREADS, 1, Whether to use Pthreads)
|
||||
|
||||
AC_MSG_CHECKING(for POSIX threads)
|
||||
AC_MSG_RESULT(yes)
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN(TSRM_THREADS_CHECKS,[
|
||||
|
||||
dnl For the thread implementations, we always use --with-*
|
||||
dnl to maintain consistency
|
||||
|
||||
AC_ARG_WITH(tsrm-pth,
|
||||
[ --with-tsrm-pth[=pth-config]
|
||||
Use GNU Pth.],[
|
||||
TSRM_PTH=$withval
|
||||
],[
|
||||
TSRM_PTH=no
|
||||
])
|
||||
|
||||
AC_ARG_WITH(tsrm-st,
|
||||
[ --with-tsrm-st Use SGI's State Threads],[
|
||||
TSRM_ST=$withval
|
||||
],[
|
||||
TSRM_ST=no
|
||||
])
|
||||
|
||||
AC_ARG_WITH(tsrm-pthreads,
|
||||
[ --with-tsrm-pthreads Use POSIX threads (default)],[
|
||||
TSRM_PTHREADS=$withval
|
||||
],[
|
||||
TSRM_PTHREADS=yes
|
||||
])
|
||||
|
||||
test "$TSRM_PTH" = "yes" && TSRM_PTH=pth-config
|
||||
|
||||
if test "$TSRM_PTH" != "no"; then
|
||||
TSRM_CHECK_PTH($TSRM_PTH)
|
||||
elif test "$TSRM_ST" != "no"; then
|
||||
TSRM_CHECK_ST($TSRM_ST)
|
||||
elif test "$TSRM_PTHREADS" != "no"; then
|
||||
TSRM_CHECK_PTHREADS
|
||||
fi
|
||||
|
||||
])
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef TSRM_CONFIG_NW_H
|
||||
#define TSRM_CONFIG_NW_H
|
||||
|
||||
#define HAVE_UTIME 1
|
||||
|
||||
/* Though we have alloca(), this seems to be causing some problem
|
||||
* with the stack pointer. Hence not using it
|
||||
*/
|
||||
/*#define HAVE_ALLOCA 1*/
|
||||
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
#ifndef TSRM_CONFIG_W32_H
|
||||
#define TSRM_CONFIG_W32_H
|
||||
|
||||
#define HAVE_UTIME 1
|
||||
#define HAVE_ALLOCA 1
|
||||
#define HAVE_REALPATH 1
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <crtdbg.h>
|
||||
|
||||
#undef inline
|
||||
#ifdef ZEND_WIN32_FORCE_INLINE
|
||||
# define inline __forceinline
|
||||
#else
|
||||
# define inline
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
#ifndef TSRM_CONFIG_COMMON_H
|
||||
#define TSRM_CONFIG_COMMON_H
|
||||
|
||||
#if WINNT|WIN32
|
||||
# define TSRM_WIN32
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# include "tsrm_config.w32.h"
|
||||
#elif defined(NETWARE)
|
||||
# include "tsrm_config.nw.h"
|
||||
#else
|
||||
# include "tsrm_config.h"
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_ALLOCA_H && !defined(_ALLOCA_H)
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
/* AIX requires this to be the first thing in the file. */
|
||||
#ifndef __GNUC__
|
||||
# ifndef HAVE_ALLOCA_H
|
||||
# ifdef _AIX
|
||||
#pragma alloca
|
||||
# else
|
||||
# ifndef alloca /* predefined by HP cc +Olibcalls */
|
||||
# ifndef NETWARE
|
||||
char *alloca ();
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef MAXPATHLEN
|
||||
# ifdef PATH_MAX
|
||||
# define MAXPATHLEN PATH_MAX
|
||||
# else
|
||||
# define MAXPATHLEN 256
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2))
|
||||
# define tsrm_do_alloca(p) alloca(p)
|
||||
# define tsrm_free_alloca(p)
|
||||
#else
|
||||
# define tsrm_do_alloca(p) malloc(p)
|
||||
# define tsrm_free_alloca(p) free(p)
|
||||
#endif
|
||||
|
||||
#endif /* TSRM_CONFIG_COMMON_H */
|
||||
-240
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
|
||||
| Anantha Kesari H Y <hyanantha@novell.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
#ifdef NETWARE
|
||||
|
||||
#ifdef USE_MKFIFO
|
||||
#include <sys/stat.h>
|
||||
#elif !defined(USE_PIPE_OPEN) /* NXFifoOpen */
|
||||
#include <nks/fsio.h>
|
||||
#endif
|
||||
|
||||
#include <nks/vm.h>
|
||||
#include <nks/memory.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mktemp.h"
|
||||
|
||||
/* strtok() call in LibC is abending when used in a different address space
|
||||
* -- hence using PHP's version itself for now
|
||||
*/
|
||||
#include "tsrm_strtok_r.h"
|
||||
#define tsrm_strtok_r(a,b,c) strtok((a),(b))
|
||||
|
||||
#define WHITESPACE " \t"
|
||||
#define MAX_ARGS 10
|
||||
|
||||
|
||||
TSRM_API FILE* popen(const char *commandline, const char *type)
|
||||
{
|
||||
char *command = NULL, *argv[MAX_ARGS] = {'\0'}, **env = NULL;
|
||||
char *tempName = "sys:/php/temp/phpXXXXXX.tmp";
|
||||
char *filePath = NULL;
|
||||
char *ptr = NULL;
|
||||
int ptrLen = 0, argc = 0, i = 0, envCount = 0, err = 0;
|
||||
FILE *stream = NULL;
|
||||
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
|
||||
int pipe_handle;
|
||||
int mode = O_RDONLY;
|
||||
#else
|
||||
NXHandle_t pipe_handle;
|
||||
NXMode_t mode = NX_O_RDONLY;
|
||||
#endif
|
||||
NXExecEnvSpec_t envSpec;
|
||||
NXNameSpec_t nameSpec;
|
||||
NXVmId_t newVM = 0;
|
||||
|
||||
/* Check for validity of input parameters */
|
||||
if (!commandline || !type)
|
||||
return NULL;
|
||||
|
||||
/* Get temporary file name */
|
||||
filePath = mktemp(tempName);
|
||||
if (!filePath)
|
||||
return NULL;
|
||||
|
||||
/* Set pipe mode according to type -- for now allow only "r" or "w" */
|
||||
if (strcmp(type, "r") == 0)
|
||||
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
|
||||
mode = O_RDONLY;
|
||||
#else
|
||||
mode = NX_O_RDONLY;
|
||||
#endif
|
||||
else if (strcmp(type, "w") == 0)
|
||||
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
|
||||
mode = O_WRONLY;
|
||||
#else
|
||||
mode = NX_O_WRONLY;
|
||||
#endif
|
||||
else
|
||||
return NULL;
|
||||
|
||||
#ifdef USE_PIPE_OPEN
|
||||
pipe_handle = pipe_open(filePath, mode);
|
||||
if (pipe_handle == -1)
|
||||
return NULL;
|
||||
#elif defined(USE_MKFIFO)
|
||||
pipe_handle = mkfifo(filePath, mode);
|
||||
if (pipe_handle == -1)
|
||||
return NULL;
|
||||
#else
|
||||
/* - NetWare doesn't require first parameter
|
||||
* - Allowing LibC to choose the buffer size for now
|
||||
*/
|
||||
err = NXFifoOpen(0, filePath, mode, 0, &pipe_handle);
|
||||
if (err)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
/* Copy the environment variables in preparation for the spawn call */
|
||||
envCount = NXGetEnvCount() + 1; /* add one for NULL */
|
||||
env = (char **) NXMemAlloc(sizeof(char *) * envCount, 0);
|
||||
if (!env)
|
||||
return NULL;
|
||||
|
||||
err = NXCopyEnv(env, envCount);
|
||||
if (err) {
|
||||
NXMemFree (env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Separate commandline string into words */
|
||||
ptr = tsrm_strtok_r((char*)commandline, WHITESPACE, NULL);
|
||||
ptrLen = strlen(ptr);
|
||||
|
||||
command = (char*)malloc(ptrLen + 1);
|
||||
if (!command) {
|
||||
NXMemFree (env);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy (command, ptr);
|
||||
|
||||
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
|
||||
while (ptr && (argc < MAX_ARGS)) {
|
||||
ptrLen = strlen(ptr);
|
||||
|
||||
argv[argc] = (char*)malloc(ptrLen + 1);
|
||||
if (!argv[argc]) {
|
||||
NXMemFree (env);
|
||||
if (command)
|
||||
free (command);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i])
|
||||
free (argv[i]);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy (argv[argc], ptr);
|
||||
argc++;
|
||||
ptr = tsrm_strtok_r(NULL, WHITESPACE, NULL);
|
||||
}
|
||||
|
||||
/* Setup the execution environment and spawn new process */
|
||||
envSpec.esFlags = 0; /* Not used */
|
||||
envSpec.esArgc = argc;
|
||||
envSpec.esArgv = (void **) argv;
|
||||
envSpec.esEnv = (void **) env;
|
||||
|
||||
/* envSpec.esStdin.ssType = */
|
||||
envSpec.esStdout.ssType = NX_OBJ_FIFO;
|
||||
envSpec.esStderr.ssType = NX_OBJ_FILE;
|
||||
|
||||
/* 'ssHandle' is not a struct/union/class member */
|
||||
/*
|
||||
envSpec.esStdin.ssHandle =
|
||||
envSpec.esStdout.ssHandle =
|
||||
envSpec.esStderr.ssHandle = -1;
|
||||
*/
|
||||
envSpec.esStdin.ssPathCtx = NULL;
|
||||
envSpec.esStdout.ssPathCtx = NULL;
|
||||
envSpec.esStderr.ssPathCtx = NULL;
|
||||
|
||||
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
|
||||
if (mode == O_RDONLY) {
|
||||
#else
|
||||
if (mode == NX_O_RDONLY) {
|
||||
#endif
|
||||
envSpec.esStdin.ssPath = filePath;
|
||||
envSpec.esStdout.ssPath = stdout;
|
||||
} else { /* Write Only */
|
||||
envSpec.esStdin.ssPath = stdin;
|
||||
envSpec.esStdout.ssPath = filePath;
|
||||
}
|
||||
|
||||
envSpec.esStderr.ssPath = stdout;
|
||||
|
||||
nameSpec.ssType = NX_OBJ_FIFO;
|
||||
/* nameSpec.ssHandle = 0; */ /* 'ssHandle' is not a struct/union/class member */
|
||||
nameSpec.ssPathCtx = NULL; /* Not used */
|
||||
nameSpec.ssPath = argv[0];
|
||||
err = NXVmSpawn(&nameSpec, &envSpec, 0, &newVM);
|
||||
if (!err)
|
||||
/* Get file pointer corresponding to the pipe (file) opened */
|
||||
stream = fdopen(pipe_handle, type);
|
||||
|
||||
/* Clean-up */
|
||||
if (env)
|
||||
NXMemFree (env);
|
||||
|
||||
if (pipe_handle)
|
||||
#if defined(USE_PIPE_OPEN) || defined(USE_MKFIFO)
|
||||
close(pipe_handle);
|
||||
#else
|
||||
NXClose(pipe_handle);
|
||||
#endif
|
||||
|
||||
if (command)
|
||||
free (command);
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (argv[i])
|
||||
free (argv[i]);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
TSRM_API int pclose(FILE* stream)
|
||||
{
|
||||
int err = 0;
|
||||
NXHandle_t fd = 0;
|
||||
|
||||
/* Get the process associated with this pipe (file) handle and terminate it */
|
||||
fd = fileno(stream);
|
||||
NXClose (fd);
|
||||
|
||||
err = fclose(stream);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif /* NETWARE */
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Venkat Raghavan S <rvenkat@novell.com> |
|
||||
| Anantha Kesari H Y <hyanantha@novell.com> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TSRM_NW_H
|
||||
#define TSRM_NW_H
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
TSRM_API FILE* popen(const char *command, const char *type);
|
||||
TSRM_API int pclose(FILE* stream);
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "tsrm_config_common.h"
|
||||
#include "tsrm_strtok_r.h"
|
||||
|
||||
static inline int in_character_class(char ch, const char *delim)
|
||||
{
|
||||
while (*delim) {
|
||||
if (*delim == ch) {
|
||||
return 1;
|
||||
}
|
||||
delim++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *tsrm_strtok_r(char *s, const char *delim, char **last)
|
||||
{
|
||||
char *token;
|
||||
|
||||
if (s == NULL) {
|
||||
s = *last;
|
||||
}
|
||||
|
||||
while (*s && in_character_class(*s, delim)) {
|
||||
s++;
|
||||
}
|
||||
if (!*s) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
token = s;
|
||||
|
||||
while (*s && !in_character_class(*s, delim)) {
|
||||
s++;
|
||||
}
|
||||
if (!*s) {
|
||||
*last = s;
|
||||
} else {
|
||||
*s = '\0';
|
||||
*last = s + 1;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
main()
|
||||
{
|
||||
char foo[] = "/foo/bar//\\barbara";
|
||||
char *last;
|
||||
char *token;
|
||||
|
||||
token = tsrm_strtok_r(foo, "/\\", &last);
|
||||
while (token) {
|
||||
printf ("Token = '%s'\n", token);
|
||||
token = tsrm_strtok_r(NULL, "/\\", &last);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef TSRM_STRTOK_R
|
||||
#define TSRM_STRTOK_R
|
||||
|
||||
char *tsrm_strtok_r(char *s, const char *delim, char **last);
|
||||
|
||||
#endif
|
||||
@@ -1,893 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Andi Gutmans <andi@zend.com> |
|
||||
| Sascha Schumann <sascha@schumann.cx> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "tsrm_virtual_cwd.h"
|
||||
#include "tsrm_strtok_r.h"
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
#include <io.h>
|
||||
#include "tsrm_win32.h"
|
||||
# if HAVE_NEWAPIS_H
|
||||
# define WANT_GETLONGPATHNAME_WRAPPER
|
||||
# define COMPILE_NEWAPIS_STUBS
|
||||
# include <NewAPIs.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NETWARE
|
||||
/*#include "pipe.h"*/
|
||||
#include "tsrm_nw.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_REALPATH
|
||||
#define realpath(x,y) strcpy(y,x)
|
||||
#endif
|
||||
|
||||
#define VIRTUAL_CWD_DEBUG 0
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
/* Only need mutex for popen() in Windows and NetWare because it doesn't chdir() on UNIX */
|
||||
#if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
|
||||
MUTEX_T cwd_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef ZTS
|
||||
static ts_rsrc_id cwd_globals_id;
|
||||
#else
|
||||
static virtual_cwd_globals cwd_globals;
|
||||
#endif
|
||||
|
||||
cwd_state main_cwd_state; /* True global */
|
||||
|
||||
#ifndef TSRM_WIN32
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(mode) ((mode) & _S_IFDIR)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(mode) ((mode) & _S_IFREG)
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
#include <tchar.h>
|
||||
#define tsrm_strtok_r(a,b,c) _tcstok((a),(b))
|
||||
#define TOKENIZER_STRING "/\\"
|
||||
|
||||
static int php_check_dots(const char *element, int n)
|
||||
{
|
||||
while (n-- > 0) if (element[n] != '.') break;
|
||||
|
||||
return (n != -1);
|
||||
}
|
||||
|
||||
#define IS_DIRECTORY_UP(element, len) \
|
||||
(len >= 2 && !php_check_dots(element, len))
|
||||
|
||||
#define IS_DIRECTORY_CURRENT(element, len) \
|
||||
(len == 1 && element[0] == '.')
|
||||
|
||||
#elif defined(NETWARE)
|
||||
/* NetWare has strtok() (in LibC) and allows both slashes in paths, like Windows --
|
||||
but rest of the stuff is like Unix */
|
||||
/* strtok() call in LibC is abending when used in a different address space -- hence using
|
||||
PHP's version itself for now */
|
||||
/*#define tsrm_strtok_r(a,b,c) strtok((a),(b))*/
|
||||
#define TOKENIZER_STRING "/\\"
|
||||
|
||||
#else
|
||||
#define TOKENIZER_STRING "/"
|
||||
#endif
|
||||
|
||||
|
||||
/* default macros */
|
||||
|
||||
#ifndef IS_DIRECTORY_UP
|
||||
#define IS_DIRECTORY_UP(element, len) \
|
||||
(len == 2 && element[0] == '.' && element[1] == '.')
|
||||
#endif
|
||||
|
||||
#ifndef IS_DIRECTORY_CURRENT
|
||||
#define IS_DIRECTORY_CURRENT(element, len) \
|
||||
(len == 1 && element[0] == '.')
|
||||
#endif
|
||||
|
||||
/* define this to check semantics */
|
||||
#define IS_DIR_OK(s) (1)
|
||||
|
||||
#ifndef IS_DIR_OK
|
||||
#define IS_DIR_OK(state) (php_is_dir_ok(state) == 0)
|
||||
#endif
|
||||
|
||||
|
||||
#define CWD_STATE_COPY(d, s) \
|
||||
(d)->cwd_length = (s)->cwd_length; \
|
||||
(d)->cwd = (char *) malloc((s)->cwd_length+1); \
|
||||
memcpy((d)->cwd, (s)->cwd, (s)->cwd_length+1);
|
||||
|
||||
#define CWD_STATE_FREE(s) \
|
||||
free((s)->cwd);
|
||||
|
||||
static int php_is_dir_ok(const cwd_state *state)
|
||||
{
|
||||
#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH))
|
||||
struct stat buf;
|
||||
|
||||
if (stat(state->cwd, &buf) == 0 && S_ISDIR(buf.st_mode))
|
||||
#else
|
||||
struct stat_libc buf;
|
||||
|
||||
if (stat(state->cwd, (struct stat*)(&buf)) == 0 && S_ISDIR(buf.st_mode))
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int php_is_file_ok(const cwd_state *state)
|
||||
{
|
||||
#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH))
|
||||
struct stat buf;
|
||||
|
||||
if (stat(state->cwd, &buf) == 0 && S_ISREG(buf.st_mode))
|
||||
#else
|
||||
struct stat_libc buf;
|
||||
|
||||
if (stat(state->cwd, (struct stat*)(&buf)) == 0 && S_ISREG(buf.st_mode))
|
||||
#endif
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void cwd_globals_ctor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
|
||||
{
|
||||
CWD_STATE_COPY(&cwd_globals->cwd, &main_cwd_state);
|
||||
}
|
||||
|
||||
static void cwd_globals_dtor(virtual_cwd_globals *cwd_globals TSRMLS_DC)
|
||||
{
|
||||
CWD_STATE_FREE(&cwd_globals->cwd);
|
||||
}
|
||||
|
||||
static char *tsrm_strndup(const char *s, size_t length)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = (char *) malloc(length+1);
|
||||
if (!p) {
|
||||
return (char *)NULL;
|
||||
}
|
||||
if (length) {
|
||||
memcpy(p,s,length);
|
||||
}
|
||||
p[length]=0;
|
||||
return p;
|
||||
}
|
||||
|
||||
CWD_API void virtual_cwd_startup(void)
|
||||
{
|
||||
char cwd[MAXPATHLEN];
|
||||
char *result;
|
||||
|
||||
result = getcwd(cwd, sizeof(cwd));
|
||||
if (!result) {
|
||||
cwd[0] = '\0';
|
||||
}
|
||||
main_cwd_state.cwd = strdup(cwd);
|
||||
main_cwd_state.cwd_length = strlen(cwd);
|
||||
|
||||
#ifdef ZTS
|
||||
ts_allocate_id(&cwd_globals_id, sizeof(virtual_cwd_globals), (ts_allocate_ctor) cwd_globals_ctor, (ts_allocate_dtor) cwd_globals_dtor);
|
||||
#else
|
||||
cwd_globals_ctor(&cwd_globals TSRMLS_CC);
|
||||
#endif
|
||||
|
||||
#if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
|
||||
cwd_mutex = tsrm_mutex_alloc();
|
||||
#endif
|
||||
}
|
||||
|
||||
CWD_API void virtual_cwd_shutdown(void)
|
||||
{
|
||||
#ifndef ZTS
|
||||
cwd_globals_dtor(&cwd_globals TSRMLS_CC);
|
||||
#endif
|
||||
#if (defined(TSRM_WIN32) || defined(NETWARE)) && defined(ZTS)
|
||||
tsrm_mutex_free(cwd_mutex);
|
||||
#endif
|
||||
|
||||
free(main_cwd_state.cwd); /* Don't use CWD_STATE_FREE because the non global states will probably use emalloc()/efree() */
|
||||
}
|
||||
|
||||
CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC)
|
||||
{
|
||||
cwd_state *state;
|
||||
|
||||
state = &CWDG(cwd);
|
||||
|
||||
if (state->cwd_length == 0) {
|
||||
char *retval;
|
||||
|
||||
*length = 1;
|
||||
retval = (char *) malloc(2);
|
||||
retval[0] = DEFAULT_SLASH;
|
||||
retval[1] = '\0';
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
/* If we have something like C: */
|
||||
if (state->cwd_length == 2 && state->cwd[state->cwd_length-1] == ':') {
|
||||
char *retval;
|
||||
|
||||
*length = state->cwd_length+1;
|
||||
retval = (char *) malloc(*length+1);
|
||||
memcpy(retval, state->cwd, *length);
|
||||
retval[*length-1] = DEFAULT_SLASH;
|
||||
retval[*length] = '\0';
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
*length = state->cwd_length;
|
||||
return strdup(state->cwd);
|
||||
}
|
||||
|
||||
|
||||
/* Same semantics as UNIX getcwd() */
|
||||
CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC)
|
||||
{
|
||||
size_t length;
|
||||
char *cwd;
|
||||
|
||||
cwd = virtual_getcwd_ex(&length TSRMLS_CC);
|
||||
|
||||
if (buf == NULL) {
|
||||
return cwd;
|
||||
}
|
||||
if (length > size-1) {
|
||||
free(cwd);
|
||||
errno = ERANGE; /* Is this OK? */
|
||||
return NULL;
|
||||
}
|
||||
memcpy(buf, cwd, length+1);
|
||||
free(cwd);
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* Resolve path relatively to state and put the real path into state */
|
||||
/* returns 0 for ok, 1 for error */
|
||||
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath)
|
||||
{
|
||||
int path_length = strlen(path);
|
||||
char *ptr, *path_copy;
|
||||
char *tok = NULL;
|
||||
int ptr_length;
|
||||
cwd_state *old_state;
|
||||
int ret = 0;
|
||||
int copy_amount = -1;
|
||||
char *free_path;
|
||||
unsigned char is_absolute = 0;
|
||||
#ifndef TSRM_WIN32
|
||||
char resolved_path[MAXPATHLEN];
|
||||
#else
|
||||
char *new_path;
|
||||
#endif
|
||||
|
||||
if (path_length == 0)
|
||||
return (0);
|
||||
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
/* cwd_length can be 0 when getcwd() fails.
|
||||
* This can happen under solaris when a dir does not have read permissions
|
||||
* but *does* have execute permissions */
|
||||
if (IS_ABSOLUTE_PATH(path, path_length) || (state->cwd_length < 1)) {
|
||||
if (use_realpath && realpath(path, resolved_path)) {
|
||||
path = resolved_path;
|
||||
path_length = strlen(path);
|
||||
}
|
||||
} else { /* Concat current directory with relative path and then run realpath() on it */
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
|
||||
ptr = tmp = (char *) malloc(state->cwd_length+path_length+sizeof("/"));
|
||||
if (!tmp) {
|
||||
return 1;
|
||||
}
|
||||
memcpy(ptr, state->cwd, state->cwd_length);
|
||||
ptr += state->cwd_length;
|
||||
*ptr++ = DEFAULT_SLASH;
|
||||
memcpy(ptr, path, path_length);
|
||||
ptr += path_length;
|
||||
*ptr = '\0';
|
||||
if (use_realpath && realpath(tmp, resolved_path)) {
|
||||
path = resolved_path;
|
||||
path_length = strlen(path);
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
#endif
|
||||
#if defined(TSRM_WIN32)
|
||||
{
|
||||
char *dummy = NULL;
|
||||
int new_path_length;
|
||||
|
||||
new_path_length = GetLongPathName(path, dummy, 0) + 1;
|
||||
if (new_path_length == 0) {
|
||||
return 1;
|
||||
}
|
||||
new_path = (char *) malloc(new_path_length);
|
||||
if (!new_path) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (GetLongPathName(path, new_path, new_path_length) != 0) {
|
||||
path = new_path;
|
||||
path_length = new_path_length;
|
||||
} else {
|
||||
free(new_path);
|
||||
new_path = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free_path = path_copy = tsrm_strndup(path, path_length);
|
||||
|
||||
old_state = (cwd_state *) malloc(sizeof(cwd_state));
|
||||
CWD_STATE_COPY(old_state, state);
|
||||
#if VIRTUAL_CWD_DEBUG
|
||||
fprintf(stderr,"cwd = %s path = %s\n", state->cwd, path);
|
||||
#endif
|
||||
if (IS_ABSOLUTE_PATH(path_copy, path_length)) {
|
||||
copy_amount = COPY_WHEN_ABSOLUTE(path_copy);
|
||||
is_absolute = 1;
|
||||
#ifdef TSRM_WIN32
|
||||
} else if (IS_SLASH(path_copy[0])) {
|
||||
copy_amount = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (copy_amount != -1) {
|
||||
state->cwd = (char *) realloc(state->cwd, copy_amount + 1);
|
||||
if (copy_amount) {
|
||||
if (is_absolute) {
|
||||
memcpy(state->cwd, path_copy, copy_amount);
|
||||
path_copy += copy_amount;
|
||||
} else {
|
||||
memcpy(state->cwd, old_state->cwd, copy_amount);
|
||||
}
|
||||
}
|
||||
state->cwd[copy_amount] = '\0';
|
||||
state->cwd_length = copy_amount;
|
||||
}
|
||||
|
||||
|
||||
if (state->cwd_length > 0 || IS_ABSOLUTE_PATH(path, path_length)) {
|
||||
ptr = tsrm_strtok_r(path_copy, TOKENIZER_STRING, &tok);
|
||||
while (ptr) {
|
||||
ptr_length = strlen(ptr);
|
||||
|
||||
if (IS_DIRECTORY_UP(ptr, ptr_length)) {
|
||||
char save;
|
||||
|
||||
save = DEFAULT_SLASH;
|
||||
|
||||
#define PREVIOUS state->cwd[state->cwd_length - 1]
|
||||
|
||||
while (IS_ABSOLUTE_PATH(state->cwd, state->cwd_length) &&
|
||||
!IS_SLASH(PREVIOUS)) {
|
||||
save = PREVIOUS;
|
||||
PREVIOUS = '\0';
|
||||
state->cwd_length--;
|
||||
}
|
||||
|
||||
if (!IS_ABSOLUTE_PATH(state->cwd, state->cwd_length)) {
|
||||
state->cwd[state->cwd_length++] = save;
|
||||
state->cwd[state->cwd_length] = '\0';
|
||||
} else {
|
||||
PREVIOUS = '\0';
|
||||
state->cwd_length--;
|
||||
}
|
||||
} else if (!IS_DIRECTORY_CURRENT(ptr, ptr_length)) {
|
||||
state->cwd = (char *) realloc(state->cwd, state->cwd_length+ptr_length+1+1);
|
||||
#ifdef TSRM_WIN32
|
||||
/* Windows 9x will consider C:\\Foo as a network path. Avoid it. */
|
||||
if ((state->cwd[state->cwd_length-1]!='\\' && state->cwd[state->cwd_length-1]!='/') ||
|
||||
IsDBCSLeadByte(state->cwd[state->cwd_length-2])) {
|
||||
state->cwd[state->cwd_length++] = DEFAULT_SLASH;
|
||||
}
|
||||
#elif defined(NETWARE)
|
||||
/* If the token is a volume name, it will have colon at the end -- so, no slash before it */
|
||||
if (ptr[ptr_length-1] != ':') {
|
||||
state->cwd[state->cwd_length++] = DEFAULT_SLASH;
|
||||
}
|
||||
#else
|
||||
state->cwd[state->cwd_length++] = DEFAULT_SLASH;
|
||||
#endif
|
||||
memcpy(&state->cwd[state->cwd_length], ptr, ptr_length+1);
|
||||
state->cwd_length += ptr_length;
|
||||
}
|
||||
ptr = tsrm_strtok_r(NULL, TOKENIZER_STRING, &tok);
|
||||
}
|
||||
|
||||
if (state->cwd_length == COPY_WHEN_ABSOLUTE(state->cwd)) {
|
||||
state->cwd = (char *) realloc(state->cwd, state->cwd_length+1+1);
|
||||
state->cwd[state->cwd_length] = DEFAULT_SLASH;
|
||||
state->cwd[state->cwd_length+1] = '\0';
|
||||
state->cwd_length++;
|
||||
}
|
||||
} else {
|
||||
state->cwd = (char *) realloc(state->cwd, path_length+1);
|
||||
memcpy(state->cwd, path, path_length+1);
|
||||
state->cwd_length = path_length;
|
||||
}
|
||||
|
||||
if (verify_path && verify_path(state)) {
|
||||
CWD_STATE_FREE(state);
|
||||
|
||||
*state = *old_state;
|
||||
|
||||
ret = 1;
|
||||
} else {
|
||||
CWD_STATE_FREE(old_state);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
free(old_state);
|
||||
#ifdef TSRM_WIN32
|
||||
if (new_path) {
|
||||
free(new_path);
|
||||
}
|
||||
#endif
|
||||
free(free_path);
|
||||
#if VIRTUAL_CWD_DEBUG
|
||||
fprintf (stderr, "virtual_file_ex() = %s\n",state->cwd);
|
||||
#endif
|
||||
return (ret);
|
||||
}
|
||||
|
||||
CWD_API int virtual_chdir(const char *path TSRMLS_DC)
|
||||
{
|
||||
return virtual_file_ex(&CWDG(cwd), path, php_is_dir_ok, 1)?-1:0;
|
||||
}
|
||||
|
||||
CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC)
|
||||
{
|
||||
int length = strlen(path);
|
||||
char *temp;
|
||||
int retval;
|
||||
|
||||
if (length == 0) {
|
||||
return 1; /* Can't cd to empty string */
|
||||
}
|
||||
while(--length >= 0 && !IS_SLASH(path[length])) {
|
||||
}
|
||||
|
||||
if (length == -1) {
|
||||
/* No directory only file name */
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */
|
||||
length++;
|
||||
}
|
||||
temp = (char *) tsrm_do_alloca(length+1);
|
||||
memcpy(temp, path, length);
|
||||
temp[length] = 0;
|
||||
#if VIRTUAL_CWD_DEBUG
|
||||
fprintf (stderr, "Changing directory to %s\n", temp);
|
||||
#endif
|
||||
retval = p_chdir(temp TSRMLS_CC);
|
||||
tsrm_free_alloca(temp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
char *retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
|
||||
if (virtual_file_ex(&new_state, path, NULL, 1)==0) {
|
||||
int len = new_state.cwd_length>MAXPATHLEN-1?MAXPATHLEN-1:new_state.cwd_length;
|
||||
|
||||
memcpy(real_path, new_state.cwd, len);
|
||||
real_path[len] = '\0';
|
||||
retval = real_path;
|
||||
} else {
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
retval = virtual_file_ex(&new_state, path, verify_path, 1);
|
||||
|
||||
*filepath = new_state.cwd;
|
||||
|
||||
return retval;
|
||||
|
||||
}
|
||||
|
||||
CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC)
|
||||
{
|
||||
return virtual_filepath_ex(path, filepath, php_is_file_ok TSRMLS_CC);
|
||||
}
|
||||
|
||||
CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
FILE *f;
|
||||
|
||||
if (path[0] == '\0') { /* Fail to open empty path */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 1);
|
||||
|
||||
f = fopen(new_state.cwd, mode);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return f;
|
||||
}
|
||||
|
||||
CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int ret;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, pathname, NULL, 1);
|
||||
|
||||
#if defined(TSRM_WIN32)
|
||||
ret = tsrm_win32_access(new_state.cwd, mode);
|
||||
#else
|
||||
ret = access(new_state.cwd, mode);
|
||||
#endif
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#if HAVE_UTIME
|
||||
CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int ret;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, filename, NULL, 0);
|
||||
|
||||
ret = utime(new_state.cwd, buf);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int ret;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, filename, NULL, 1);
|
||||
|
||||
ret = chmod(new_state.cwd, mode);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int ret;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, filename, NULL, 0);
|
||||
|
||||
ret = chown(new_state.cwd, owner, group);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int f;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 1);
|
||||
|
||||
if (flags & O_CREAT) {
|
||||
mode_t mode;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, flags);
|
||||
mode = (mode_t) va_arg(arg, int);
|
||||
va_end(arg);
|
||||
|
||||
f = open(new_state.cwd, flags, mode);
|
||||
} else {
|
||||
f = open(new_state.cwd, flags);
|
||||
}
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return f;
|
||||
}
|
||||
|
||||
CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int f;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 1);
|
||||
|
||||
f = creat(new_state.cwd, mode);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return f;
|
||||
}
|
||||
|
||||
CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC)
|
||||
{
|
||||
cwd_state old_state;
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&old_state, &CWDG(cwd));
|
||||
virtual_file_ex(&old_state, oldname, NULL, 0);
|
||||
oldname = old_state.cwd;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, newname, NULL, 0);
|
||||
newname = new_state.cwd;
|
||||
|
||||
retval = rename(oldname, newname);
|
||||
|
||||
CWD_STATE_FREE(&old_state);
|
||||
CWD_STATE_FREE(&new_state);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH))
|
||||
CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 1);
|
||||
|
||||
retval = stat(new_state.cwd, buf);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
#else
|
||||
CWD_API int virtual_stat(const char *path, struct stat_libc *buf TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 1);
|
||||
|
||||
retval = stat(new_state.cwd, (struct stat*)buf);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 0);
|
||||
|
||||
retval = lstat(new_state.cwd, buf);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
CWD_API int virtual_unlink(const char *path TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, path, NULL, 0);
|
||||
|
||||
retval = unlink(new_state.cwd);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
|
||||
CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, pathname, NULL, 1);
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
retval = mkdir(new_state.cwd);
|
||||
#else
|
||||
retval = mkdir(new_state.cwd, mode);
|
||||
#endif
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
|
||||
CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
int retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, pathname, NULL, 0);
|
||||
|
||||
retval = rmdir(new_state.cwd);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
DIR *opendir(const char *name);
|
||||
#endif
|
||||
|
||||
CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC)
|
||||
{
|
||||
cwd_state new_state;
|
||||
DIR *retval;
|
||||
|
||||
CWD_STATE_COPY(&new_state, &CWDG(cwd));
|
||||
virtual_file_ex(&new_state, pathname, NULL, 1);
|
||||
|
||||
retval = opendir(new_state.cwd);
|
||||
|
||||
CWD_STATE_FREE(&new_state);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
|
||||
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
|
||||
{
|
||||
return popen_ex(command, type, CWDG(cwd).cwd, NULL);
|
||||
}
|
||||
|
||||
#elif defined(NETWARE)
|
||||
|
||||
/* On NetWare, the trick of prepending "cd cwd; " doesn't work so we need to perform
|
||||
a VCWD_CHDIR() and mutex it
|
||||
*/
|
||||
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
|
||||
{
|
||||
char prev_cwd[MAXPATHLEN];
|
||||
char *getcwd_result;
|
||||
FILE *retval;
|
||||
|
||||
getcwd_result = VCWD_GETCWD(prev_cwd, MAXPATHLEN);
|
||||
if (!getcwd_result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_mutex_lock(cwd_mutex);
|
||||
#endif
|
||||
|
||||
VCWD_CHDIR(CWDG(cwd).cwd);
|
||||
retval = popen(command, type);
|
||||
VCWD_CHDIR(prev_cwd);
|
||||
|
||||
#ifdef ZTS
|
||||
tsrm_mutex_unlock(cwd_mutex);
|
||||
#endif
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else /* Unix */
|
||||
|
||||
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC)
|
||||
{
|
||||
int command_length;
|
||||
char *command_line;
|
||||
char *ptr;
|
||||
FILE *retval;
|
||||
|
||||
command_length = strlen(command);
|
||||
|
||||
ptr = command_line = (char *) malloc(command_length + sizeof("cd ; ") + CWDG(cwd).cwd_length+1);
|
||||
if (!command_line) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(ptr, "cd ", sizeof("cd ")-1);
|
||||
ptr += sizeof("cd ")-1;
|
||||
|
||||
if (CWDG(cwd).cwd_length == 0) {
|
||||
*ptr++ = DEFAULT_SLASH;
|
||||
} else {
|
||||
memcpy(ptr, CWDG(cwd).cwd, CWDG(cwd).cwd_length);
|
||||
ptr += CWDG(cwd).cwd_length;
|
||||
}
|
||||
|
||||
*ptr++ = ' ';
|
||||
*ptr++ = ';';
|
||||
*ptr++ = ' ';
|
||||
|
||||
memcpy(ptr, command, command_length+1);
|
||||
retval = popen(command_line, type);
|
||||
|
||||
free(command_line);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
* c-basic-offset: 4
|
||||
* End:
|
||||
*/
|
||||
@@ -1,293 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Andi Gutmans <andi@zend.com> |
|
||||
| Sascha Schumann <sascha@schumann.cx> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef VIRTUAL_CWD_H
|
||||
#define VIRTUAL_CWD_H
|
||||
|
||||
#include "TSRM.h"
|
||||
#include "tsrm_config_common.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_UTIME_H
|
||||
#include <utime.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#ifndef TSRM_WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(__osf__) || defined(_AIX)
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
#include "readdir.h"
|
||||
#include <sys/utime.h>
|
||||
/* mode_t isn't defined on Windows */
|
||||
typedef unsigned short mode_t;
|
||||
|
||||
#define DEFAULT_SLASH '\\'
|
||||
#define DEFAULT_DIR_SEPARATOR ';'
|
||||
#define IS_SLASH(c) ((c) == '/' || (c) == '\\')
|
||||
#define IS_SLASH_P(c) (*(c) == '/' || \
|
||||
(*(c) == '\\' && !IsDBCSLeadByte(*(c-1))))
|
||||
|
||||
/* COPY_WHEN_ABSOLUTE is 2 under Win32 because by chance both regular absolute paths
|
||||
in the file system and UNC paths need copying of two characters */
|
||||
#define COPY_WHEN_ABSOLUTE(path) 2
|
||||
#define IS_UNC_PATH(path, len) \
|
||||
(len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1]))
|
||||
#define IS_ABSOLUTE_PATH(path, len) \
|
||||
(len >= 2 && ((isalpha(path[0]) && path[1] == ':') || IS_UNC_PATH(path, len)))
|
||||
|
||||
#elif defined(NETWARE)
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SLASH '/'
|
||||
#define DEFAULT_DIR_SEPARATOR ';'
|
||||
#define IS_SLASH(c) ((c) == '/' || (c) == '\\')
|
||||
#define IS_SLASH_P(c) IS_SLASH(*(c))
|
||||
#define COPY_WHEN_ABSOLUTE(path) \
|
||||
(strchr(path, ':') - path + 1) /* Take the volume name which ends with a colon */
|
||||
#define IS_ABSOLUTE_PATH(path, len) \
|
||||
(strchr(path, ':') != NULL) /* Colon indicates volume name */
|
||||
|
||||
#else
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SLASH '/'
|
||||
|
||||
#ifdef __riscos__
|
||||
#define DEFAULT_DIR_SEPARATOR ';'
|
||||
#else
|
||||
#define DEFAULT_DIR_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
#define IS_SLASH(c) ((c) == '/')
|
||||
#define IS_SLASH_P(c) (*(c) == '/')
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef COPY_WHEN_ABSOLUTE
|
||||
#define COPY_WHEN_ABSOLUTE(path) 0
|
||||
#endif
|
||||
|
||||
#ifndef IS_ABSOLUTE_PATH
|
||||
#define IS_ABSOLUTE_PATH(path, len) \
|
||||
(IS_SLASH(path[0]))
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_EXPORTS
|
||||
#define CWD_EXPORTS
|
||||
#endif
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
# ifdef CWD_EXPORTS
|
||||
# define CWD_API __declspec(dllexport)
|
||||
# else
|
||||
# define CWD_API __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
#define CWD_API
|
||||
#endif
|
||||
|
||||
typedef struct _cwd_state {
|
||||
char *cwd;
|
||||
int cwd_length;
|
||||
} cwd_state;
|
||||
|
||||
typedef int (*verify_path_func)(const cwd_state *);
|
||||
|
||||
CWD_API void virtual_cwd_startup(void);
|
||||
CWD_API void virtual_cwd_shutdown(void);
|
||||
CWD_API char *virtual_getcwd_ex(size_t *length TSRMLS_DC);
|
||||
CWD_API char *virtual_getcwd(char *buf, size_t size TSRMLS_DC);
|
||||
CWD_API int virtual_chdir(const char *path TSRMLS_DC);
|
||||
CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path TSRMLS_DC) TSRMLS_DC);
|
||||
CWD_API int virtual_filepath(const char *path, char **filepath TSRMLS_DC);
|
||||
CWD_API int virtual_filepath_ex(const char *path, char **filepath, verify_path_func verify_path TSRMLS_DC);
|
||||
CWD_API char *virtual_realpath(const char *path, char *real_path TSRMLS_DC);
|
||||
CWD_API FILE *virtual_fopen(const char *path, const char *mode TSRMLS_DC);
|
||||
CWD_API int virtual_open(const char *path TSRMLS_DC, int flags, ...);
|
||||
CWD_API int virtual_creat(const char *path, mode_t mode TSRMLS_DC);
|
||||
CWD_API int virtual_rename(char *oldname, char *newname TSRMLS_DC);
|
||||
#if !(defined(NETWARE) && defined(CLIB_STAT_PATCH))
|
||||
CWD_API int virtual_stat(const char *path, struct stat *buf TSRMLS_DC);
|
||||
#else
|
||||
CWD_API int virtual_stat(const char *path, struct stat_libc *buf TSRMLS_DC);
|
||||
#endif
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
CWD_API int virtual_lstat(const char *path, struct stat *buf TSRMLS_DC);
|
||||
#endif
|
||||
CWD_API int virtual_unlink(const char *path TSRMLS_DC);
|
||||
CWD_API int virtual_mkdir(const char *pathname, mode_t mode TSRMLS_DC);
|
||||
CWD_API int virtual_rmdir(const char *pathname TSRMLS_DC);
|
||||
CWD_API DIR *virtual_opendir(const char *pathname TSRMLS_DC);
|
||||
CWD_API FILE *virtual_popen(const char *command, const char *type TSRMLS_DC);
|
||||
CWD_API int virtual_access(const char *pathname, int mode TSRMLS_DC);
|
||||
#if defined(TSRM_WIN32)
|
||||
/* these are not defined in win32 headers */
|
||||
#ifndef W_OK
|
||||
#define W_OK 0x02
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 0x04
|
||||
#endif
|
||||
#ifndef X_OK
|
||||
#define X_OK 0x01
|
||||
#endif
|
||||
#ifndef F_OK
|
||||
#define F_OK 0x00
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* On AIX & Tru64 when a file does not exist realpath() returns
|
||||
* NULL, and sets errno to ENOENT. Unlike in other libc implementations
|
||||
* the destination is not filled and remains undefined. Therefor, we
|
||||
* must populate it manually using strcpy as done on systems with no
|
||||
* realpath() function.
|
||||
*/
|
||||
#if defined(__osf__) || defined(_AIX)
|
||||
static char *php_realpath_hack(char *src, char *dest)
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if ((ret = realpath(src, dest)) == NULL && errno == ENOENT) {
|
||||
return strcpy(dest, src);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_UTIME
|
||||
CWD_API int virtual_utime(const char *filename, struct utimbuf *buf TSRMLS_DC);
|
||||
#endif
|
||||
CWD_API int virtual_chmod(const char *filename, mode_t mode TSRMLS_DC);
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
CWD_API int virtual_chown(const char *filename, uid_t owner, gid_t group TSRMLS_DC);
|
||||
#endif
|
||||
|
||||
CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func verify_path, int use_realpath);
|
||||
|
||||
typedef struct _virtual_cwd_globals {
|
||||
cwd_state cwd;
|
||||
} virtual_cwd_globals;
|
||||
|
||||
#ifdef ZTS
|
||||
# define CWDG(v) TSRMG(cwd_globals_id, virtual_cwd_globals *, v)
|
||||
#else
|
||||
# define CWDG(v) (cwd_globals.v)
|
||||
#endif
|
||||
|
||||
/* The actual macros to be used in programs using TSRM
|
||||
* If the program defines VIRTUAL_DIR it will use the
|
||||
* virtual_* functions
|
||||
*/
|
||||
|
||||
#ifdef VIRTUAL_DIR
|
||||
|
||||
#define VCWD_GETCWD(buff, size) virtual_getcwd(buff, size TSRMLS_CC)
|
||||
#define VCWD_FOPEN(path, mode) virtual_fopen(path, mode TSRMLS_CC)
|
||||
/* Because open() has two modes, we have to macros to replace it */
|
||||
#define VCWD_OPEN(path, flags) virtual_open(path TSRMLS_CC, flags)
|
||||
#define VCWD_OPEN_MODE(path, flags, mode) virtual_open(path TSRMLS_CC, flags, mode)
|
||||
#define VCWD_CREAT(path, mode) virtual_creat(path, mode TSRMLS_CC)
|
||||
#define VCWD_CHDIR(path) virtual_chdir(path TSRMLS_CC)
|
||||
#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, virtual_chdir TSRMLS_CC)
|
||||
#define VCWD_GETWD(buf)
|
||||
#define VCWD_REALPATH(path, real_path) virtual_realpath(path, real_path TSRMLS_CC)
|
||||
#define VCWD_RENAME(oldname, newname) virtual_rename(oldname, newname TSRMLS_CC)
|
||||
#define VCWD_STAT(path, buff) virtual_stat(path, buff TSRMLS_CC)
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
#define VCWD_LSTAT(path, buff) virtual_lstat(path, buff TSRMLS_CC)
|
||||
#endif
|
||||
#define VCWD_UNLINK(path) virtual_unlink(path TSRMLS_CC)
|
||||
#define VCWD_MKDIR(pathname, mode) virtual_mkdir(pathname, mode TSRMLS_CC)
|
||||
#define VCWD_RMDIR(pathname) virtual_rmdir(pathname TSRMLS_CC)
|
||||
#define VCWD_OPENDIR(pathname) virtual_opendir(pathname TSRMLS_CC)
|
||||
#define VCWD_POPEN(command, type) virtual_popen(command, type TSRMLS_CC)
|
||||
#define VCWD_ACCESS(pathname, mode) virtual_access(pathname, mode TSRMLS_CC)
|
||||
#if HAVE_UTIME
|
||||
#define VCWD_UTIME(path, time) virtual_utime(path, time TSRMLS_CC)
|
||||
#endif
|
||||
#define VCWD_CHMOD(path, mode) virtual_chmod(path, mode TSRMLS_CC)
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
#define VCWD_CHOWN(path, owner, group) virtual_chown(path, owner, group TSRMLS_CC)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define VCWD_GETCWD(buff, size) getcwd(buff, size)
|
||||
#define VCWD_FOPEN(path, mode) fopen(path, mode)
|
||||
#define VCWD_OPEN(path, flags) open(path, flags)
|
||||
#define VCWD_OPEN_MODE(path, flags, mode) open(path, flags, mode)
|
||||
#define VCWD_CREAT(path, mode) creat(path, mode)
|
||||
#define VCWD_RENAME(oldname, newname) rename(oldname, newname)
|
||||
#define VCWD_CHDIR(path) chdir(path)
|
||||
#define VCWD_CHDIR_FILE(path) virtual_chdir_file(path, chdir)
|
||||
#define VCWD_GETWD(buf) getwd(buf)
|
||||
#define VCWD_STAT(path, buff) stat(path, buff)
|
||||
#define VCWD_LSTAT(path, buff) lstat(path, buff)
|
||||
#define VCWD_UNLINK(path) unlink(path)
|
||||
#define VCWD_MKDIR(pathname, mode) mkdir(pathname, mode)
|
||||
#define VCWD_RMDIR(pathname) rmdir(pathname)
|
||||
#define VCWD_OPENDIR(pathname) opendir(pathname)
|
||||
#define VCWD_POPEN(command, type) popen(command, type)
|
||||
#if defined(TSRM_WIN32)
|
||||
#define VCWD_ACCESS(pathname, mode) tsrm_win32_access(pathname, mode)
|
||||
#else
|
||||
#define VCWD_ACCESS(pathname, mode) access(pathname, mode)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_REALPATH
|
||||
#if defined(__osf__) || defined(_AIX)
|
||||
#define VCWD_REALPATH(path, real_path) php_realpath_hack(path, real_path)
|
||||
#else
|
||||
#define VCWD_REALPATH(path, real_path) realpath(path, real_path)
|
||||
#endif
|
||||
#else
|
||||
#define VCWD_REALPATH(path, real_path) strcpy(real_path, path)
|
||||
#endif
|
||||
|
||||
#if HAVE_UTIME
|
||||
#define VCWD_UTIME(path, time) utime(path, time)
|
||||
#endif
|
||||
#define VCWD_CHMOD(path, mode) chmod(path, mode)
|
||||
#if !defined(TSRM_WIN32) && !defined(NETWARE)
|
||||
#define VCWD_CHOWN(path, owner, group) chown(path, owner, group)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* VIRTUAL_CWD_H */
|
||||
@@ -1,388 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Daniel Beulshausen <daniel@php4win.de> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
|
||||
#define TSRM_INCLUDE_FULL_WINDOWS_HEADERS
|
||||
|
||||
#include "TSRM.h"
|
||||
|
||||
#ifdef TSRM_WIN32
|
||||
|
||||
#include "tsrm_win32.h"
|
||||
|
||||
#ifdef ZTS
|
||||
static ts_rsrc_id win32_globals_id;
|
||||
#else
|
||||
static tsrm_win32_globals win32_globals;
|
||||
#endif
|
||||
|
||||
static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
|
||||
{
|
||||
globals->process = NULL;
|
||||
globals->shm = NULL;
|
||||
globals->process_size = 0;
|
||||
globals->shm_size = 0;
|
||||
globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
|
||||
}
|
||||
|
||||
static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
|
||||
{
|
||||
shm_pair *ptr;
|
||||
|
||||
if (globals->process) {
|
||||
free(globals->process);
|
||||
}
|
||||
|
||||
if (globals->shm) {
|
||||
for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
|
||||
UnmapViewOfFile(ptr->addr);
|
||||
CloseHandle(ptr->segment);
|
||||
UnmapViewOfFile(ptr->descriptor);
|
||||
CloseHandle(ptr->info);
|
||||
}
|
||||
free(globals->shm);
|
||||
}
|
||||
|
||||
free(globals->comspec);
|
||||
}
|
||||
|
||||
TSRM_API void tsrm_win32_startup(void)
|
||||
{
|
||||
#ifdef ZTS
|
||||
ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
|
||||
#else
|
||||
tsrm_win32_ctor(&win32_globals TSRMLS_CC);
|
||||
#endif
|
||||
}
|
||||
|
||||
TSRM_API void tsrm_win32_shutdown(void)
|
||||
{
|
||||
#ifndef ZTS
|
||||
tsrm_win32_dtor(&win32_globals TSRMLS_CC);
|
||||
#endif
|
||||
}
|
||||
|
||||
TSRM_API int tsrm_win32_access(const char *pathname, int mode)
|
||||
{
|
||||
SHFILEINFO sfi;
|
||||
|
||||
if (mode == 1 /*X_OK*/) {
|
||||
return access(pathname, 0) == 0 &&
|
||||
SHGetFileInfo(pathname, 0, &sfi, sizeof(SHFILEINFO), SHGFI_EXETYPE) != 0 ? 0 : -1;
|
||||
} else {
|
||||
return access(pathname, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static process_pair *process_get(FILE *stream TSRMLS_DC)
|
||||
{
|
||||
process_pair *ptr;
|
||||
process_pair *newptr;
|
||||
|
||||
for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
|
||||
if (ptr->stream == stream) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr < (TWG(process) + TWG(process_size))) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
|
||||
if (newptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TWG(process) = newptr;
|
||||
ptr = newptr + TWG(process_size);
|
||||
TWG(process_size)++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static shm_pair *shm_get(int key, void *addr)
|
||||
{
|
||||
shm_pair *ptr;
|
||||
shm_pair *newptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
|
||||
if (!ptr->descriptor) {
|
||||
continue;
|
||||
}
|
||||
if (!addr && ptr->descriptor->shm_perm.key == key) {
|
||||
break;
|
||||
} else if (ptr->addr == addr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr < (TWG(shm) + TWG(shm_size))) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
|
||||
if (newptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TWG(shm) = newptr;
|
||||
ptr = newptr + TWG(shm_size);
|
||||
TWG(shm_size)++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
|
||||
HANDLE copy, self = GetCurrentProcess();
|
||||
if (!DuplicateHandle(self, fh, self, ©, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
TSRM_API FILE *popen(const char *command, const char *type)
|
||||
{
|
||||
return popen_ex(command, type, NULL, NULL);
|
||||
}
|
||||
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
|
||||
{
|
||||
FILE *stream = NULL;
|
||||
int fno, str_len = strlen(type), read, mode;
|
||||
STARTUPINFO startup;
|
||||
PROCESS_INFORMATION process;
|
||||
SECURITY_ATTRIBUTES security;
|
||||
HANDLE in, out;
|
||||
char *cmd;
|
||||
process_pair *proc;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
security.bInheritHandle = TRUE;
|
||||
security.lpSecurityDescriptor = NULL;
|
||||
|
||||
if (!str_len || !CreatePipe(&in, &out, &security, 2048L)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(&startup, 0, sizeof(STARTUPINFO));
|
||||
memset(&process, 0, sizeof(PROCESS_INFORMATION));
|
||||
|
||||
startup.cb = sizeof(STARTUPINFO);
|
||||
startup.dwFlags = STARTF_USESTDHANDLES;
|
||||
startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
read = (type[0] == 'r') ? TRUE : FALSE;
|
||||
mode = ((str_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
|
||||
|
||||
|
||||
if (read) {
|
||||
in = dupHandle(in, FALSE);
|
||||
startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
startup.hStdOutput = out;
|
||||
} else {
|
||||
out = dupHandle(out, FALSE);
|
||||
startup.hStdInput = in;
|
||||
startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
|
||||
cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));
|
||||
sprintf(cmd, "%s /c %s", TWG(comspec), command);
|
||||
if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS, env, cwd, &startup, &process)) {
|
||||
return NULL;
|
||||
}
|
||||
free(cmd);
|
||||
|
||||
CloseHandle(process.hThread);
|
||||
proc = process_get(NULL TSRMLS_CC);
|
||||
|
||||
if (read) {
|
||||
fno = _open_osfhandle((long)in, _O_RDONLY | mode);
|
||||
CloseHandle(out);
|
||||
} else {
|
||||
fno = _open_osfhandle((long)out, _O_WRONLY | mode);
|
||||
CloseHandle(in);
|
||||
}
|
||||
|
||||
stream = _fdopen(fno, type);
|
||||
proc->prochnd = process.hProcess;
|
||||
proc->stream = stream;
|
||||
return stream;
|
||||
}
|
||||
|
||||
TSRM_API int pclose(FILE *stream)
|
||||
{
|
||||
DWORD termstat = 0;
|
||||
process_pair *process;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if ((process = process_get(stream TSRMLS_CC)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fflush(process->stream);
|
||||
fclose(process->stream);
|
||||
|
||||
WaitForSingleObject(process->prochnd, INFINITE);
|
||||
GetExitCodeProcess(process->prochnd, &termstat);
|
||||
process->stream = NULL;
|
||||
CloseHandle(process->prochnd);
|
||||
|
||||
return termstat;
|
||||
}
|
||||
|
||||
TSRM_API int shmget(int key, int size, int flags)
|
||||
{
|
||||
shm_pair *shm;
|
||||
char shm_segment[26], shm_info[29];
|
||||
HANDLE shm_handle, info_handle;
|
||||
BOOL created = FALSE;
|
||||
|
||||
if (size < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
|
||||
sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
|
||||
|
||||
shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
|
||||
info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
|
||||
|
||||
if ((!shm_handle && !info_handle)) {
|
||||
if (flags & IPC_EXCL) {
|
||||
return -1;
|
||||
}
|
||||
if (flags & IPC_CREAT) {
|
||||
shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
|
||||
info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
|
||||
created = TRUE;
|
||||
}
|
||||
if ((!shm_handle || !info_handle)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
shm = shm_get(key, NULL);
|
||||
shm->segment = shm_handle;
|
||||
shm->info = info_handle;
|
||||
shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
|
||||
|
||||
if (created) {
|
||||
shm->descriptor->shm_perm.key = key;
|
||||
shm->descriptor->shm_segsz = size;
|
||||
shm->descriptor->shm_ctime = time(NULL);
|
||||
shm->descriptor->shm_cpid = getpid();
|
||||
shm->descriptor->shm_perm.mode = flags;
|
||||
|
||||
shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
|
||||
shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
|
||||
shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
|
||||
shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
|
||||
shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
|
||||
}
|
||||
|
||||
if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
|
||||
CloseHandle(shm->segment);
|
||||
UnmapViewOfFile(shm->descriptor);
|
||||
CloseHandle(shm->info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
TSRM_API void *shmat(int key, const void *shmaddr, int flags)
|
||||
{
|
||||
shm_pair *shm = shm_get(key, NULL);
|
||||
|
||||
if (!shm->segment) {
|
||||
return (void*)-1;
|
||||
}
|
||||
|
||||
shm->descriptor->shm_atime = time(NULL);
|
||||
shm->descriptor->shm_lpid = getpid();
|
||||
shm->descriptor->shm_nattch++;
|
||||
|
||||
shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
|
||||
|
||||
return shm->addr;
|
||||
}
|
||||
|
||||
TSRM_API int shmdt(const void *shmaddr)
|
||||
{
|
||||
shm_pair *shm = shm_get(0, (void*)shmaddr);
|
||||
|
||||
if (!shm->segment) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
shm->descriptor->shm_dtime = time(NULL);
|
||||
shm->descriptor->shm_lpid = getpid();
|
||||
shm->descriptor->shm_nattch--;
|
||||
|
||||
return UnmapViewOfFile(shm->addr) ? 0 : -1;
|
||||
}
|
||||
|
||||
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
|
||||
shm_pair *shm = shm_get(key, NULL);
|
||||
|
||||
if (!shm->segment) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case IPC_STAT:
|
||||
memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
|
||||
return 0;
|
||||
|
||||
case IPC_SET:
|
||||
shm->descriptor->shm_ctime = time(NULL);
|
||||
shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
|
||||
shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
|
||||
shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
|
||||
return 0;
|
||||
|
||||
case IPC_RMID:
|
||||
if (shm->descriptor->shm_nattch < 1) {
|
||||
shm->descriptor->shm_perm.key = -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
TSRM_API char *realpath(char *orig_path, char *buffer)
|
||||
{
|
||||
int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
|
||||
if(!ret || ret > _MAX_PATH) {
|
||||
return NULL;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
+----------------------------------------------------------------------+
|
||||
| PHP Version 5 |
|
||||
+----------------------------------------------------------------------+
|
||||
| Copyright (c) 1997-2004 The PHP Group |
|
||||
+----------------------------------------------------------------------+
|
||||
| This source file is subject to version 3.0 of the PHP license, |
|
||||
| that is bundled with this package in the file LICENSE, and is |
|
||||
| available through the world-wide-web at the following url: |
|
||||
| http://www.php.net/license/3_0.txt. |
|
||||
| If you did not receive a copy of the PHP license and are unable to |
|
||||
| obtain it through the world-wide-web, please send a note to |
|
||||
| license@php.net so we can mail you a copy immediately. |
|
||||
+----------------------------------------------------------------------+
|
||||
| Authors: Daniel Beulshausen <daniel@php4win.de> |
|
||||
+----------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef TSRM_WIN32_H
|
||||
#define TSRM_WIN32_H
|
||||
|
||||
#include "TSRM.h"
|
||||
#include <windows.h>
|
||||
|
||||
struct ipc_perm {
|
||||
int key;
|
||||
unsigned short uid;
|
||||
unsigned short gid;
|
||||
unsigned short cuid;
|
||||
unsigned short cgid;
|
||||
unsigned short mode;
|
||||
unsigned short seq;
|
||||
};
|
||||
|
||||
struct shmid_ds {
|
||||
struct ipc_perm shm_perm;
|
||||
int shm_segsz;
|
||||
time_t shm_atime;
|
||||
time_t shm_dtime;
|
||||
time_t shm_ctime;
|
||||
unsigned short shm_cpid;
|
||||
unsigned short shm_lpid;
|
||||
short shm_nattch;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
FILE *stream;
|
||||
HANDLE prochnd;
|
||||
} process_pair;
|
||||
|
||||
typedef struct {
|
||||
void *addr;
|
||||
HANDLE info;
|
||||
HANDLE segment;
|
||||
struct shmid_ds *descriptor;
|
||||
} shm_pair;
|
||||
|
||||
typedef struct {
|
||||
process_pair *process;
|
||||
shm_pair *shm;
|
||||
int process_size;
|
||||
int shm_size;
|
||||
char *comspec;
|
||||
} tsrm_win32_globals;
|
||||
|
||||
#ifdef ZTS
|
||||
# define TWG(v) TSRMG(win32_globals_id, tsrm_win32_globals *, v)
|
||||
#else
|
||||
# define TWG(v) (win32_globals.v)
|
||||
#endif
|
||||
|
||||
#define IPC_PRIVATE 0
|
||||
#define IPC_CREAT 00001000
|
||||
#define IPC_EXCL 00002000
|
||||
#define IPC_NOWAIT 00004000
|
||||
|
||||
#define IPC_RMID 0
|
||||
#define IPC_SET 1
|
||||
#define IPC_STAT 2
|
||||
#define IPC_INFO 3
|
||||
|
||||
#define SHM_R PAGE_READONLY
|
||||
#define SHM_W PAGE_READWRITE
|
||||
|
||||
#define SHM_RDONLY FILE_MAP_READ
|
||||
#define SHM_RND FILE_MAP_WRITE
|
||||
#define SHM_REMAP FILE_MAP_COPY
|
||||
|
||||
|
||||
TSRM_API void tsrm_win32_startup(void);
|
||||
TSRM_API void tsrm_win32_shutdown(void);
|
||||
|
||||
TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env);
|
||||
TSRM_API FILE *popen(const char *command, const char *type);
|
||||
TSRM_API int pclose(FILE *stream);
|
||||
TSRM_API int tsrm_win32_access(const char *pathname, int mode);
|
||||
|
||||
TSRM_API int shmget(int key, int size, int flags);
|
||||
TSRM_API void *shmat(int key, const void *shmaddr, int flags);
|
||||
TSRM_API int shmdt(const void *shmaddr);
|
||||
TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf);
|
||||
|
||||
TSRM_API char *realpath(char *orig_path, char *buffer);
|
||||
#endif
|
||||
+586
@@ -1,3 +1,589 @@
|
||||
2004-09-06 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_objects.c:
|
||||
- Fix handling of exceptions in dtors
|
||||
|
||||
2004-09-05 Zeev Suraski <zeev@zend.com>
|
||||
|
||||
* zend.c
|
||||
zend.h
|
||||
zend_ini_parser.y:
|
||||
Fix reverse dependency
|
||||
|
||||
2004-09-04 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_API.c:
|
||||
- Don't destroy object when calling overloaded cast method in
|
||||
- zend_parse_parameters()
|
||||
|
||||
2004-09-02 Sebastian Bergmann <sb@sebastian-bergmann.de>
|
||||
|
||||
* zend_compile.c:
|
||||
Fugbix typo.
|
||||
|
||||
2004-08-30 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* (PHP_5_0)
|
||||
ZEND_CHANGES:
|
||||
MFH: Add some information about array overloading
|
||||
|
||||
* ZEND_CHANGES:
|
||||
Add some information about array overloading
|
||||
|
||||
2004-08-30 Stanislav Malyshev <stas@zend.com>
|
||||
|
||||
* zend_execute.c:
|
||||
fix crash #29893
|
||||
|
||||
2004-08-29 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_execute.c:
|
||||
String offset starts with 0, fix isset($str[$len])
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_compile.c:
|
||||
MFH: Bugfix #29882 isset crashes on arrays
|
||||
|
||||
* zend_compile.c:
|
||||
Bugfix #29882 isset crashes on arrays
|
||||
|
||||
2004-08-27 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_alloc.c:
|
||||
- Fix leak report for 0 byte allocations (Dmitry)
|
||||
|
||||
2004-08-26 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_compile.c:
|
||||
MFH: Enforce semantics: Classes cannot extend Interfaces
|
||||
|
||||
* zend_compile.c:
|
||||
Enforce semantics: Classes cannot extend Interfaces
|
||||
|
||||
* tests/bug29828.phpt:
|
||||
Fix test: Classes cannot extend Interfaces
|
||||
|
||||
* zend_compile.c:
|
||||
Drop doubled check
|
||||
|
||||
* zend_compile.c:
|
||||
- Bugfix #29828 Interfaces no longer work
|
||||
|
||||
* tests/bug29828.phpt:
|
||||
|
||||
Add new test
|
||||
|
||||
2004-08-25 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
- Add interface_exists() and differentiate between classes and interfaces
|
||||
(Andrey Hristov)
|
||||
|
||||
2004-08-24 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_API.c:
|
||||
- Add missing brackets
|
||||
|
||||
2004-08-23 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_compile.c:
|
||||
- Drop unused variable
|
||||
|
||||
* zend_execute_API.c
|
||||
zend_globals.h:
|
||||
- Boost up __autoload() calls by caching the lookup
|
||||
|
||||
2004-08-23 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_compile.c:
|
||||
- Improve performance of switch()
|
||||
|
||||
2004-08-23 Zeev Suraski <zeev@zend.com>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_reflection_api.c:
|
||||
Fix names
|
||||
|
||||
2004-08-21 Sara Golemon <php@alphaweb.net>
|
||||
|
||||
* zend_compile.c:
|
||||
Bugfix#29777 Some compilers don't like // style comments
|
||||
|
||||
2004-08-20 Sara Golemon <php@alphaweb.net>
|
||||
|
||||
* zend_ini_parser.y:
|
||||
Fix compile
|
||||
|
||||
2004-08-19 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_execute.c:
|
||||
- Cleanup
|
||||
|
||||
* zend.c
|
||||
zend_execute_API.c
|
||||
zend_globals.h:
|
||||
- Second wave of garbage removal.
|
||||
|
||||
* zend_compile.h
|
||||
zend_execute.c:
|
||||
- Stop using garbage. Please let me know if you find any bugs resulting
|
||||
- of this patch (very likely). (Dmitry, Andi)
|
||||
|
||||
2004-08-19 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Implement #29728: Reflection API Feature: Default parameter value.
|
||||
. ReflectionParameter::isDefaultValueAvailable()
|
||||
. ReflectionParameter::getDefaultValue()
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Nedd to work on copy
|
||||
|
||||
2004-08-18 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Show default value of optional parameters of user defined functions.
|
||||
|
||||
2004-08-18 Andrei Zmievski <andreiz@gmail.com>
|
||||
|
||||
* zend_ini_parser.y:
|
||||
Forgot to turn off debugging.
|
||||
|
||||
* zend_ini_parser.y
|
||||
zend_ini_scanner.l:
|
||||
Re-add my patch for .ini variable access.
|
||||
|
||||
2004-08-16 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_reflection_api.c:
|
||||
MFH: Fix bug #29447: Reflection API issues
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Fix bug #29447: Reflection API issues
|
||||
|
||||
2004-08-15 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_compile.c:
|
||||
Remove unnecessary check
|
||||
|
||||
2004-08-14 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_compile.c:
|
||||
Add missing check
|
||||
|
||||
2004-08-12 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- Back to 5.0.2-dev
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- Roll 5.0.1
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- Back to -dev
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- 5.0.1RC2
|
||||
|
||||
* zend_compile.c
|
||||
zend_compile.h
|
||||
zend_execute.c:
|
||||
- Don't use magic numbers
|
||||
|
||||
* zend_compile.c
|
||||
zend_execute.c:
|
||||
- Significantly improve performance of foreach($arr as $data). (Marcus)
|
||||
|
||||
2004-08-11 Ilia Alshanetsky <ilia@prohost.org>
|
||||
|
||||
* zend_highlight.c:
|
||||
MFH: Fixed bug #29607 (highlighting code with HEREDOC produces invalid
|
||||
output).
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_highlight.c:
|
||||
Fixed bug #29607 (highlighting code with HEREDOC produces invalid output).
|
||||
|
||||
2004-08-11 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_execute.c:
|
||||
More meaningfull error message
|
||||
|
||||
2004-08-11 Derick Rethans <php@derickrethans.nl>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_alloc.h:
|
||||
- MFH: Patch to allow the Zend memory allocators to be disabled.
|
||||
|
||||
* zend_alloc.h:
|
||||
- Added missing defines.
|
||||
|
||||
2004-08-10 Ilia Alshanetsky <ilia@prohost.org>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_highlight.c:
|
||||
MFH: Fixed bug #29606 (php_strip_whitespace() prints to stdout rather then
|
||||
returning the value).
|
||||
|
||||
* zend_highlight.c:
|
||||
Fixed bug #29606 (php_strip_whitespace() prints to stdout rather then
|
||||
returning the value).
|
||||
|
||||
2004-08-10 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- Back to -dev
|
||||
|
||||
* (PHP_5_0)
|
||||
zend.h:
|
||||
- 5.0.1RC1
|
||||
|
||||
2004-08-10 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_execute.c:
|
||||
- Fix warnings
|
||||
|
||||
2004-08-07 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_alloc.h:
|
||||
- Commit Derick's patch for allowing Zend to use regular libc memory
|
||||
- allocation functions. Mainly useful in conjunction with tools such as
|
||||
- valgrind which enables us to find bugs we might not find with the
|
||||
- current memory managers boundary protection.
|
||||
|
||||
2004-08-05 Ilia Alshanetsky <ilia@prohost.org>
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
Eliminate unneeded variable.
|
||||
|
||||
2004-08-04 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c
|
||||
tests/bug29523.phpt:
|
||||
- Fix bug #29523 (ReflectionParameter::isOptional() is incorrect)
|
||||
|
||||
2004-08-03 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* ZEND_CHANGES:
|
||||
Update
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_builtin_functions.c
|
||||
tests/bug29505.phpt:
|
||||
- MFH Bug #29505 get_class_vars() severely broken when used with arrays
|
||||
|
||||
* tests/bug29505.phpt:
|
||||
|
||||
Add new test
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
- Fixed Bug #29505 get_class_vars() severely broken when used with arrays
|
||||
|
||||
2004-08-02 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Add methods to check parameter count
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_compile.c:
|
||||
MFH Change to use memcmp instead of strcmp
|
||||
|
||||
* zend_compile.c:
|
||||
- Change to use memcmp instead of strcmp
|
||||
|
||||
2004-08-02 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_compile.c:
|
||||
- Fix typo
|
||||
|
||||
2004-08-02 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_language_parser.y
|
||||
zend_language_scanner.l:
|
||||
- Remove all for now
|
||||
|
||||
* zend_compile.c
|
||||
zend_compile.h
|
||||
zend_execute_API.c:
|
||||
MFB: Enforce protocol on magic methods/functions
|
||||
|
||||
2004-08-02 Ilia Alshanetsky <ilia@prohost.org>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_execute.c:
|
||||
MFH: A gentler (performance wise) allocation of buffer for temp variables.
|
||||
|
||||
* zend_execute.c:
|
||||
A gentler (performance wise) allocation of buffer for temp variables.
|
||||
|
||||
2004-08-01 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_compile.c
|
||||
zend_compile.h
|
||||
zend_execute_API.c:
|
||||
- Enforce protocol on magic methods/functions
|
||||
|
||||
2004-07-30 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_execute.c
|
||||
zend_execute_API.c
|
||||
zend_ptr_stack.c
|
||||
zend_ptr_stack.h:
|
||||
- More ptr_stack optimizations and cleanups
|
||||
|
||||
* zend_alloc.c
|
||||
zend_alloc.h
|
||||
zend_execute.c
|
||||
zend_fast_cache.h
|
||||
zend_ptr_stack.h:
|
||||
- Improve performance by inlining zend_ptr_stack_n_push(). var_args can
|
||||
usually not be inlined by compilers.
|
||||
|
||||
2004-07-29 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_hash.c:
|
||||
- Increase performance of *sort() and some internal sort operations.
|
||||
|
||||
2004-07-29 Sara Golemon <php@alphaweb.net>
|
||||
|
||||
* zend_compile.c
|
||||
zend_compile.h
|
||||
zend_execute.c
|
||||
zend_language_parser.y
|
||||
zend_language_scanner.l
|
||||
zend_opcode.c:
|
||||
Revert goto opcode
|
||||
|
||||
* zend_execute.c:
|
||||
&tmp and label are the same thing, don't free it till we're done with it.
|
||||
|
||||
* zend_compile.c
|
||||
zend_execute.c:
|
||||
Plug some memory leaks and promote unknown label to E_ERROR.
|
||||
If someone tries to jump to a non-existant label execution really
|
||||
shouldn't try to carry on.
|
||||
|
||||
* zend_compile.c
|
||||
zend_compile.h
|
||||
zend_execute.c
|
||||
zend_language_parser.y
|
||||
zend_language_scanner.l
|
||||
zend_opcode.c:
|
||||
Add goto operator by popular request.
|
||||
|
||||
2004-07-28 Wez Furlong <wez.php@thebrainroom.net>
|
||||
|
||||
* zend_ini.c:
|
||||
Fix: ini entries for dl()'d modules now work under ZTS
|
||||
Side-effect: avoid possible crashes when multiple threads load/unload
|
||||
modules and mess with the global hash table.
|
||||
|
||||
2004-07-28 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend.h
|
||||
zend.h:
|
||||
- Fix MAC OSX to always use native DSO loading
|
||||
|
||||
2004-07-27 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_exceptions.c:
|
||||
- Be specific about visibility
|
||||
|
||||
2004-07-27 Wez Furlong <wez.php@thebrainroom.net>
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
Fix two possible crashes. Latter is unlikely unless you are doing scary
|
||||
things, but former looks nasty.
|
||||
|
||||
2004-07-26 Stanislav Malyshev <stas@zend.com>
|
||||
|
||||
* zend_interfaces.c:
|
||||
quick fix for #29382
|
||||
|
||||
2004-07-25 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Show visibility errors (try to fix #29354)
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_execute.c
|
||||
zend_objects_API.c
|
||||
zend_objects_API.h:
|
||||
- MFH: Fix bug #29368 : The destructor is called when an exception is
|
||||
thrown from the constructor
|
||||
|
||||
* zend_execute.c
|
||||
zend_objects_API.c
|
||||
zend_objects_API.h:
|
||||
- Fix bug #29368 : The destructor is called when an exception is thrown
|
||||
from the constructor
|
||||
|
||||
* zend.c
|
||||
zend.h
|
||||
zend_execute.h
|
||||
zend_execute_API.c:
|
||||
- Execute destructors earlier (Florian Schaper, fschaper at intux org)
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Add ReflectionParameter::isOptional() to test whether a parameter is
|
||||
optional and also show this information in export.
|
||||
|
||||
* zend_exceptions.c:
|
||||
- Add optional parameters $filename and $lineno to ErrorException
|
||||
constructor to allow overwriting automatically retrieved information.
|
||||
|
||||
2004-07-23 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_execute.c:
|
||||
Fix 0 Byte leak after alloca to emalloc change
|
||||
|
||||
2004-07-22 Zeev Suraski <zeev@zend.com>
|
||||
|
||||
* zend_object_handlers.c:
|
||||
Fix bug in handling of protected properties
|
||||
|
||||
2004-07-21 Edin Kadribasic <edink@emini.dk>
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
Fixed build
|
||||
|
||||
2004-07-21 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_builtin_functions.c:
|
||||
MFH: Fixded #29291: get_class_vars() return names with NULLs
|
||||
|
||||
* zend_builtin_functions.c:
|
||||
- Fixded #29291: get_class_vars() return names with NULLs
|
||||
|
||||
2004-07-20 Moriyoshi Koizumi <moriyoshi@at.wakwak.com>
|
||||
|
||||
* zend_alloc.c
|
||||
zend_alloc.h:
|
||||
- Add safe_pemalloc()
|
||||
|
||||
2004-07-20 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
- Fixed bug 28895 again (long live the dead)
|
||||
|
||||
2004-07-20 Zeev Suraski <zeev@zend.com>
|
||||
|
||||
* zend_exceptions.c:
|
||||
Fix prototypes
|
||||
|
||||
* zend_exceptions.c:
|
||||
Add descriptions
|
||||
|
||||
2004-07-20 Stanislav Malyshev <stas@zend.com>
|
||||
|
||||
* zend_compile.c:
|
||||
add todo
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_ini.h
|
||||
zend_ini_parser.y:
|
||||
export ini parser
|
||||
|
||||
2004-07-19 Sebastian Bergmann <sb@sebastian-bergmann.de>
|
||||
|
||||
* zend_reflection_api.c:
|
||||
Fix prototypes: Reflection_* -> Reflection*.
|
||||
|
||||
* zend_reflection_api.c:
|
||||
Make ReflectionClass::getMethod() and ReflectionClass::getProperty() raise
|
||||
an ReflectionException instead of returning NULL on failure.
|
||||
|
||||
* zend_reflection_api.c:
|
||||
Do not use contracted forms.
|
||||
|
||||
2004-07-19 Stanislav Malyshev <stas@zend.com>
|
||||
|
||||
* zend_ini.h
|
||||
zend_ini_parser.y:
|
||||
export INI parser
|
||||
|
||||
* zend_object_handlers.c:
|
||||
__set and __get will be called not only when variable doesn't exist but
|
||||
also when it's
|
||||
invisible
|
||||
|
||||
2004-07-19 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_extensions.h
|
||||
zend_modules.h:
|
||||
- Bump API number due to empty_string change
|
||||
|
||||
* zend.c
|
||||
zend.h
|
||||
zend_API.h
|
||||
zend_alloc.h
|
||||
zend_execute.c
|
||||
zend_object_handlers.c
|
||||
zend_operators.c
|
||||
zend_variables.c:
|
||||
- Nuke empty_string. It is a reminanent from the time where RETURN_FALSE()
|
||||
used to return "" and not bool(false). It's not worth keeping it because
|
||||
STR_FREE() and zval_dtor() always have to check for it and it slows down
|
||||
the general case. In addition, it seems that empty_string has been
|
||||
abused
|
||||
quite a lot, and was used not only for setting zval's but generally in
|
||||
PHP code instead of "", which wasn't the intention. Last but not least,
|
||||
nuking empty_string should improve stability as I doubt every place
|
||||
correctly checked if they are not mistakenly erealloc()'ing it or
|
||||
calling efree() on it.
|
||||
NOTE: Some code is probably broken. Each extension maintainer should
|
||||
check and see that my changes are OK. Also, I haven't had time to touch
|
||||
PECL yet. Will try and do it tomorrow.
|
||||
|
||||
2004-07-18 Wez Furlong <wez.php@thebrainroom.net>
|
||||
|
||||
* zend_execute_API.c:
|
||||
No point allocating 0 bytes
|
||||
|
||||
2004-07-16 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_language_parser.y
|
||||
zend_language_scanner.l:
|
||||
- Speed up by making null/false/true reserved word which allows to drop
|
||||
an opcode (FETCH_CONSTANT) for every usage.
|
||||
|
||||
* zend_execute.c:
|
||||
Bugfix #28464 catch() does not catch exceptions by interfaces
|
||||
|
||||
2004-07-16 Ilia Alshanetsky <ilia@prohost.org>
|
||||
|
||||
* zend_operators.h:
|
||||
MFB: Fixed bug #28800 (strings beginning with "inf" improperly converted).
|
||||
|
||||
* (PHP_5_0)
|
||||
zend_operators.h:
|
||||
Fixed bug #28800 (strings beginning with "inf" improperly converted).
|
||||
|
||||
2004-07-15 Andi Gutmans <andi@zend.com>
|
||||
|
||||
* zend_alloc.c
|
||||
zend_alloc.h:
|
||||
- Improve performance of zend_alloc by stopping the size from being a bit
|
||||
- field.
|
||||
|
||||
2004-07-15 Marcus Boerger <marcus.boerger@post.rwth-aachen.de>
|
||||
|
||||
* zend_exceptions.c
|
||||
zend_exceptions.h:
|
||||
- Add new class ErrorException to encapsulate errors in exceptions
|
||||
|
||||
* zend_dynamic_array.h:
|
||||
- Fix prototype
|
||||
|
||||
2004-07-14 Stanislav Malyshev <stas@zend.com>
|
||||
|
||||
* zend_object_handlers.c:
|
||||
|
||||
+42
-1
@@ -545,7 +545,7 @@ Changes in the Zend Engine 2.0
|
||||
|
||||
<?php
|
||||
class Exception {
|
||||
function __construct(string $message=NULL, int $code=0) {
|
||||
function __construct(/*string*/ $message=NULL, /*int*/ $code=0) {
|
||||
if (func_num_args()) {
|
||||
$this->message = $message;
|
||||
}
|
||||
@@ -890,6 +890,47 @@ Changes in the Zend Engine 2.0
|
||||
the use of all abstract methods declared in the interfaces Iterator
|
||||
and IteratorAggregate respectively.
|
||||
|
||||
* Array overloading
|
||||
|
||||
Objects can be used with Array notation when they implement the
|
||||
interface ArrayAccess. You cannot use such objects in standard
|
||||
array functions, however you have full control over the array
|
||||
notation. This allows lazy initialization or read only array.
|
||||
|
||||
Note that setting [] results in a call to offsetSet() with
|
||||
index being NULL. That means that as with standard arrays you
|
||||
cannot store NULL keys.
|
||||
|
||||
Example:
|
||||
|
||||
<?php
|
||||
class ArrayClass implements ArrayAccess {
|
||||
public $a = array();
|
||||
|
||||
function offsetExists($index) {
|
||||
return array_key_exists($index, $this->a);
|
||||
}
|
||||
function offsetGet($index) {
|
||||
return $this->a[$index];
|
||||
}
|
||||
function offsetSet($index, $newval) {
|
||||
return $this->a[$index] = $newval;
|
||||
}
|
||||
function offsetUnset($index) {
|
||||
unset($this->a[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
$obj = new ArrayClass;
|
||||
|
||||
$obj[0] = 'bla'; // calls offsetSet(0,'bla')
|
||||
$obj[] = 42; // calls offsetSet(NULL, 42)
|
||||
$x = $obj[0]; // calls offsetGet(0)
|
||||
$b = isset($obj[0]); // calls offsetExists(0)
|
||||
unset($obj[0]); // calls offsetUnset(0)
|
||||
?>
|
||||
|
||||
|
||||
* __METHOD__
|
||||
|
||||
The pseudo constant __METHOD__ shows the current class and method
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
--TEST--
|
||||
Bug #29505 (get_class_vars() severely broken when used with arrays)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Test {
|
||||
public $empty = array();
|
||||
public $three = array(1, "b"=>"c", 3=>array());
|
||||
}
|
||||
|
||||
var_dump(get_class_vars('Test'));
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
["empty"]=>
|
||||
array(0) {
|
||||
}
|
||||
["three"]=>
|
||||
array(3) {
|
||||
[0]=>
|
||||
int(1)
|
||||
["b"]=>
|
||||
string(1) "c"
|
||||
[3]=>
|
||||
array(0) {
|
||||
}
|
||||
}
|
||||
}
|
||||
===DONE===
|
||||
+12
-19
@@ -55,6 +55,7 @@ ZEND_API void (*zend_unblock_interruptions)(void);
|
||||
ZEND_API void (*zend_ticks_function)(int ticks);
|
||||
ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
|
||||
int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
|
||||
|
||||
void (*zend_on_timeout)(int seconds TSRMLS_DC);
|
||||
|
||||
@@ -194,7 +195,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
|
||||
switch (expr->type) {
|
||||
case IS_NULL:
|
||||
expr_copy->value.str.len = 0;
|
||||
expr_copy->value.str.val = empty_string;
|
||||
expr_copy->value.str.val = STR_EMPTY_ALLOC();
|
||||
break;
|
||||
case IS_BOOL:
|
||||
if (expr->value.lval) {
|
||||
@@ -202,7 +203,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
|
||||
expr_copy->value.str.val = estrndup("1", 1);
|
||||
} else {
|
||||
expr_copy->value.str.len = 0;
|
||||
expr_copy->value.str.val = empty_string;
|
||||
expr_copy->value.str.val = STR_EMPTY_ALLOC();
|
||||
}
|
||||
break;
|
||||
case IS_RESOURCE:
|
||||
@@ -242,7 +243,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
|
||||
if (EG(exception)) {
|
||||
zval_dtor(expr_copy);
|
||||
expr_copy->value.str.len = 0;
|
||||
expr_copy->value.str.val = empty_string;
|
||||
expr_copy->value.str.val = STR_EMPTY_ALLOC();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -577,6 +578,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
|
||||
zend_ticks_function = utility_functions->ticks_function;
|
||||
zend_on_timeout = utility_functions->on_timeout;
|
||||
zend_vspprintf = utility_functions->vspprintf_function;
|
||||
zend_getenv = utility_functions->getenv_function;
|
||||
|
||||
zend_compile_file = compile_file;
|
||||
zend_execute = execute;
|
||||
@@ -805,6 +807,13 @@ void zend_deactivate_modules(TSRMLS_D)
|
||||
} zend_end_try();
|
||||
}
|
||||
|
||||
void zend_call_destructors(TSRMLS_D)
|
||||
{
|
||||
zend_try {
|
||||
shutdown_destructors(TSRMLS_C);
|
||||
} zend_end_try();
|
||||
}
|
||||
|
||||
void zend_deactivate(TSRMLS_D)
|
||||
{
|
||||
/* we're no longer executing anything */
|
||||
@@ -872,8 +881,6 @@ ZEND_API void zend_error(int type, const char *format, ...)
|
||||
char *error_filename;
|
||||
uint error_lineno;
|
||||
zval *orig_user_error_handler;
|
||||
zval *orig_garbage[2];
|
||||
int orig_garbage_ptr;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
/* Obtain relevant filename and lineno */
|
||||
@@ -966,12 +973,6 @@ ZEND_API void zend_error(int type, const char *format, ...)
|
||||
orig_user_error_handler = EG(user_error_handler);
|
||||
EG(user_error_handler) = NULL;
|
||||
|
||||
orig_garbage_ptr = EG(garbage_ptr);
|
||||
EG(garbage_ptr) = 0;
|
||||
if (orig_garbage_ptr > 0) {
|
||||
memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr);
|
||||
}
|
||||
|
||||
if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) {
|
||||
if (retval) {
|
||||
if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) {
|
||||
@@ -984,14 +985,6 @@ ZEND_API void zend_error(int type, const char *format, ...)
|
||||
zend_error_cb(type, error_filename, error_lineno, format, args);
|
||||
}
|
||||
|
||||
if (orig_garbage_ptr > 0) {
|
||||
while (EG(garbage_ptr)) {
|
||||
zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]);
|
||||
}
|
||||
EG(garbage_ptr) = orig_garbage_ptr;
|
||||
memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr);
|
||||
}
|
||||
|
||||
EG(user_error_handler) = orig_user_error_handler;
|
||||
|
||||
efree(params);
|
||||
|
||||
+12
-12
@@ -91,7 +91,7 @@ const char *zend_mh_bundle_error(void);
|
||||
|
||||
#endif /* HAVE_MACH_O_DYLD_H */
|
||||
|
||||
#if defined(HAVE_LIBDL)
|
||||
#if defined(HAVE_LIBDL) && !defined(HAVE_MACH_O_DYLD_H)
|
||||
|
||||
# ifndef RTLD_LAZY
|
||||
# define RTLD_LAZY 1 /* Solaris 1, FreeBSD's (2.1.7.1 and older) */
|
||||
@@ -357,6 +357,7 @@ typedef struct _zend_utility_functions {
|
||||
void (*on_timeout)(int seconds TSRMLS_DC);
|
||||
int (*stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
|
||||
int (*vspprintf_function)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
char *(*getenv_function)(char *name, size_t name_len TSRMLS_DC);
|
||||
} zend_utility_functions;
|
||||
|
||||
|
||||
@@ -450,6 +451,7 @@ END_EXTERN_C()
|
||||
|
||||
void zend_activate(TSRMLS_D);
|
||||
void zend_deactivate(TSRMLS_D);
|
||||
void zend_call_destructors(TSRMLS_D);
|
||||
void zend_activate_modules(TSRMLS_D);
|
||||
void zend_deactivate_modules(TSRMLS_D);
|
||||
void zend_post_deactivate_modules(TSRMLS_D);
|
||||
@@ -460,22 +462,19 @@ void zend_post_deactivate_modules(TSRMLS_D);
|
||||
#define Z_DBG(expr)
|
||||
#endif
|
||||
|
||||
ZEND_API extern char *empty_string;
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
ZEND_API void free_estring(char **str_p);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define STR_FREE(ptr) if (ptr && ptr!=empty_string) { efree(ptr); }
|
||||
#define STR_FREE_REL(ptr) if (ptr && ptr!=empty_string) { efree_rel(ptr); }
|
||||
/* FIXME: Check if we can save if (ptr) too */
|
||||
|
||||
#define STR_REALLOC(ptr, size) \
|
||||
if (ptr!=empty_string) { \
|
||||
ptr = (char *) erealloc(ptr, size); \
|
||||
} else { \
|
||||
ptr = (char *) emalloc(size); \
|
||||
memset(ptr, 0, size); \
|
||||
}
|
||||
#define STR_FREE(ptr) if (ptr) { efree(ptr); }
|
||||
#define STR_FREE_REL(ptr) if (ptr) { efree_rel(ptr); }
|
||||
|
||||
#define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1)
|
||||
|
||||
#define STR_REALLOC(ptr, size) \
|
||||
ptr = (char *) erealloc(ptr, size);
|
||||
|
||||
/* output support */
|
||||
#define ZEND_WRITE(str, str_len) zend_write((str), (str_len))
|
||||
@@ -494,6 +493,7 @@ extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, cons
|
||||
extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
|
||||
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
|
||||
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
|
||||
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
|
||||
|
||||
|
||||
ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
|
||||
+4
-3
@@ -318,6 +318,7 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
|
||||
case IS_OBJECT: {
|
||||
if (Z_OBJ_HANDLER_PP(arg, cast_object)
|
||||
&& Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
|
||||
SEPARATE_ZVAL_IF_NOT_REF(arg);
|
||||
*pl = Z_STRLEN_PP(arg);
|
||||
*p = Z_STRVAL_PP(arg);
|
||||
break;
|
||||
@@ -1344,21 +1345,21 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
|
||||
if (ctor) {
|
||||
ctor->common.fn_flags |= ZEND_ACC_CTOR;
|
||||
if (ctor->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
zend_error(error_type, "Constructor %s::%s cannot be static", ctor->common.scope->name, ctor->common.function_name);
|
||||
zend_error(error_type, "Constructor %s::%s() cannot be static", ctor->common.scope->name, ctor->common.function_name);
|
||||
}
|
||||
ctor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
|
||||
}
|
||||
if (dtor) {
|
||||
dtor->common.fn_flags |= ZEND_ACC_DTOR;
|
||||
if (dtor->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
zend_error(error_type, "Destructor %s::%s cannot be static", dtor->common.scope->name, dtor->common.function_name);
|
||||
zend_error(error_type, "Destructor %s::%s() cannot be static", dtor->common.scope->name, dtor->common.function_name);
|
||||
}
|
||||
dtor->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
|
||||
}
|
||||
if (clone) {
|
||||
clone->common.fn_flags |= ZEND_ACC_CLONE;
|
||||
if (clone->common.fn_flags & ZEND_ACC_STATIC) {
|
||||
zend_error(error_type, "Constructor %s::%s cannot be static", clone->common.scope->name, clone->common.function_name);
|
||||
zend_error(error_type, "Constructor %s::%s() cannot be static", clone->common.scope->name, clone->common.function_name);
|
||||
}
|
||||
clone->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC;
|
||||
}
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@ END_EXTERN_C()
|
||||
|
||||
#define ZVAL_EMPTY_STRING(z) { \
|
||||
(z)->value.str.len = 0; \
|
||||
(z)->value.str.val = empty_string; \
|
||||
(z)->value.str.val = STR_EMPTY_ALLOC(); \
|
||||
(z)->type = IS_STRING; \
|
||||
}
|
||||
|
||||
|
||||
+49
-35
@@ -163,7 +163,6 @@ ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
AG(cache_stats)[CACHE_INDEX][1]++;
|
||||
memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long));
|
||||
#endif
|
||||
p->cached = 0;
|
||||
p->size = size;
|
||||
return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING);
|
||||
} else {
|
||||
@@ -196,7 +195,6 @@ ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
return (void *)p;
|
||||
}
|
||||
p->cached = 0;
|
||||
ADD_POINTER_TO_LIST(p);
|
||||
p->size = size; /* Save real size for correct cache output */
|
||||
#if ZEND_DEBUG
|
||||
@@ -243,6 +241,30 @@ ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset)
|
||||
{
|
||||
|
||||
if (nmemb < LONG_MAX
|
||||
&& size < LONG_MAX
|
||||
&& offset < LONG_MAX
|
||||
&& nmemb >= 0
|
||||
&& size >= 0
|
||||
&& offset >= 0) {
|
||||
long lval;
|
||||
double dval;
|
||||
int use_dval;
|
||||
|
||||
ZEND_SIGNED_MULTIPLY_LONG(nmemb, size, lval, dval, use_dval);
|
||||
|
||||
if (!use_dval
|
||||
&& lval < (long) (LONG_MAX - offset)) {
|
||||
return pemalloc(lval + offset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
zend_error(E_ERROR, "Possible integer overflow in memory allocation (%zd * %zd + %zd)", nmemb, size, offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
@@ -270,7 +292,6 @@ ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
|
||||
#if !ZEND_DISABLE_MEMORY_CACHE
|
||||
if ((CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] < MAX_CACHED_ENTRIES)) {
|
||||
AG(cache)[CACHE_INDEX][AG(cache_count)[CACHE_INDEX]++] = p;
|
||||
p->cached = 1;
|
||||
#if ZEND_DEBUG
|
||||
p->magic = MEM_BLOCK_CACHED_MAGIC;
|
||||
#endif
|
||||
@@ -481,7 +502,7 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
|
||||
unsigned int i, j;
|
||||
zend_mem_header *ptr;
|
||||
|
||||
for (i=1; i<MAX_CACHED_MEMORY; i++) {
|
||||
for (i=0; i<MAX_CACHED_MEMORY; i++) {
|
||||
for (j=0; j<AG(cache_count)[i]; j++) {
|
||||
ptr = (zend_mem_header *) AG(cache)[i][j];
|
||||
# if MEMORY_LIMIT
|
||||
@@ -530,42 +551,36 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown TSRMLS_DC)
|
||||
p = AG(head);
|
||||
t = AG(head);
|
||||
while (t) {
|
||||
if (!t->cached) {
|
||||
#if ZEND_DEBUG
|
||||
if (!t->reported) {
|
||||
zend_mem_header *iterator;
|
||||
int total_leak=0, total_leak_count=0;
|
||||
if (!t->reported) {
|
||||
zend_mem_header *iterator;
|
||||
int total_leak=0, total_leak_count=0;
|
||||
|
||||
grand_total_leaks++;
|
||||
if (!silent) {
|
||||
zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, t);
|
||||
}
|
||||
t->reported = 1;
|
||||
for (iterator=t->pNext; iterator; iterator=iterator->pNext) {
|
||||
if (!iterator->cached
|
||||
&& iterator->filename==t->filename
|
||||
&& iterator->lineno==t->lineno) {
|
||||
total_leak += iterator->size;
|
||||
total_leak_count++;
|
||||
iterator->reported = 1;
|
||||
}
|
||||
}
|
||||
if (!silent && total_leak_count>0) {
|
||||
zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *) (long) (total_leak_count));
|
||||
}
|
||||
grand_total_leaks += total_leak_count;
|
||||
grand_total_leaks++;
|
||||
if (!silent) {
|
||||
zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, t);
|
||||
}
|
||||
t->reported = 1;
|
||||
for (iterator=t->pNext; iterator; iterator=iterator->pNext) {
|
||||
if (iterator->filename==t->filename && iterator->lineno==t->lineno) {
|
||||
total_leak += iterator->size;
|
||||
total_leak_count++;
|
||||
iterator->reported = 1;
|
||||
}
|
||||
}
|
||||
if (!silent && total_leak_count>0) {
|
||||
zend_message_dispatcher(ZMSG_MEMORY_LEAK_REPEATED, (void *) (long) (total_leak_count));
|
||||
}
|
||||
grand_total_leaks += total_leak_count;
|
||||
}
|
||||
#endif
|
||||
#if MEMORY_LIMIT
|
||||
AG(allocated_memory) -= REAL_SIZE(t->size);
|
||||
AG(allocated_memory) -= REAL_SIZE(t->size);
|
||||
#endif
|
||||
p = t->pNext;
|
||||
REMOVE_POINTER_FROM_LIST(t);
|
||||
ZEND_DO_FREE(t);
|
||||
t = p;
|
||||
} else {
|
||||
t = t->pNext;
|
||||
}
|
||||
p = t->pNext;
|
||||
REMOVE_POINTER_FROM_LIST(t);
|
||||
ZEND_DO_FREE(t);
|
||||
t = p;
|
||||
}
|
||||
|
||||
#if ZEND_DEBUG
|
||||
@@ -785,7 +800,6 @@ ZEND_API void _full_mem_check(int silent ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_D
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* tab-width: 4
|
||||
|
||||
+56
-5
@@ -50,8 +50,7 @@ typedef struct _zend_mem_header {
|
||||
struct _zend_mem_header *pNext;
|
||||
struct _zend_mem_header *pLast;
|
||||
#endif
|
||||
unsigned int size:31;
|
||||
unsigned int cached:1;
|
||||
unsigned int size;
|
||||
} zend_mem_header;
|
||||
|
||||
typedef union _align_test {
|
||||
@@ -79,12 +78,17 @@ ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_M
|
||||
|
||||
ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
|
||||
ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
|
||||
ZEND_API void *_safe_malloc(size_t nmemb, size_t size, size_t offset) ZEND_ATTRIBUTE_MALLOC;
|
||||
ZEND_API void _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
||||
ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
|
||||
ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
|
||||
ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
|
||||
ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
|
||||
|
||||
#define USE_ZEND_ALLOC 1
|
||||
|
||||
#if USE_ZEND_ALLOC
|
||||
|
||||
/* Standard wrapper macros */
|
||||
#define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
|
||||
#define safe_emalloc(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
|
||||
@@ -107,6 +111,7 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
|
||||
|
||||
/* Selective persistent/non persistent allocation macros */
|
||||
#define pemalloc(size, persistent) ((persistent)?malloc(size):emalloc(size))
|
||||
#define safe_pemalloc(nmemb, size, offset, persistent) ((persistent)?_safe_malloc(nmemb, size, offset):safe_emalloc(nmemb, size, offset))
|
||||
#define pefree(ptr, persistent) ((persistent)?free(ptr):efree(ptr))
|
||||
#define pecalloc(nmemb, size, persistent) ((persistent)?calloc((nmemb), (size)):ecalloc((nmemb), (size)))
|
||||
#define perealloc(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc((ptr), (size)))
|
||||
@@ -120,8 +125,55 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
|
||||
#define perealloc_recoverable_rel(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable_rel((ptr), (size)))
|
||||
#define pestrdup_rel(s, persistent) ((persistent)?strdup(s):estrdup_rel(s))
|
||||
|
||||
#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):(empty_string))
|
||||
#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):(empty_string))
|
||||
#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):STR_EMPTY_ALLOC())
|
||||
#define safe_estrndup(ptr, len) ((ptr)?(estrndup((ptr), (len))):STR_EMPTY_ALLOC())
|
||||
|
||||
#else
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
/* Standard wrapper macros */
|
||||
#define emalloc(size) malloc(size)
|
||||
#define safe_emalloc(nmemb, size, offset) malloc((nmemb) * (size) + (offset))
|
||||
#define efree(ptr) free(ptr)
|
||||
#define ecalloc(nmemb, size) calloc((nmemb), (size))
|
||||
#define erealloc(ptr, size) realloc((ptr), (size))
|
||||
#define erealloc_recoverable(ptr, size) realloc((ptr), (size))
|
||||
#define estrdup(s) strdup(s)
|
||||
#define estrndup(s, length) strndup((s), (length))
|
||||
|
||||
/* Relay wrapper macros */
|
||||
#define emalloc_rel(size) malloc(size)
|
||||
#define safe_emalloc_rel(nmemb, size, offset) malloc((nmemb) * (size) + (offset))
|
||||
#define efree_rel(ptr) free(ptr)
|
||||
#define ecalloc_rel(nmemb, size) calloc((nmemb), (size))
|
||||
#define erealloc_rel(ptr, size) realloc((ptr), (size))
|
||||
#define erealloc_recoverable_rel(ptr, size) realloc((ptr), (size))
|
||||
#define estrdup_rel(s) strdup(s)
|
||||
#define estrndup_rel(s, length) strndup((s), (length))
|
||||
|
||||
/* Selective persistent/non persistent allocation macros */
|
||||
#define pemalloc(size, persistent) malloc(size)
|
||||
#define safe_pemalloc(nmemb, size, offset, persistent) malloc((nmemb) * (size) + (offset))
|
||||
#define pefree(ptr, persistent) free(ptr)
|
||||
#define pecalloc(nmemb, size, persistent) calloc((nmemb), (size))
|
||||
#define perealloc(ptr, size, persistent) realloc((ptr), (size))
|
||||
#define perealloc_recoverable(ptr, size, persistent) realloc((ptr), (size))
|
||||
#define pestrdup(s, persistent) strdup(s)
|
||||
|
||||
#define pemalloc_rel(size, persistent) malloc(size)
|
||||
#define pefree_rel(ptr, persistent) free(ptr)
|
||||
#define pecalloc_rel(nmemb, size, persistent) calloc((nmemb), (size))
|
||||
#define perealloc_rel(ptr, size, persistent) realloc((ptr), (size))
|
||||
#define perealloc_recoverable_rel(ptr, size, persistent) realloc((ptr), (size))
|
||||
#define pestrdup_rel(s, persistent) strdup(s)
|
||||
|
||||
#define safe_estrdup(ptr) ((ptr)?(strdup(ptr)):(empty_string))
|
||||
#define safe_estrndup(ptr, len) ((ptr)?(strndup((ptr), (len))):(empty_string))
|
||||
|
||||
#endif
|
||||
|
||||
ZEND_API int zend_set_memory_limit(unsigned int memory_limit);
|
||||
|
||||
@@ -139,7 +191,6 @@ void zend_debug_alloc_output(char *format, ...);
|
||||
#define full_mem_check(silent)
|
||||
#endif
|
||||
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,6 +44,7 @@ static ZEND_FUNCTION(get_class);
|
||||
static ZEND_FUNCTION(get_parent_class);
|
||||
static ZEND_FUNCTION(method_exists);
|
||||
static ZEND_FUNCTION(class_exists);
|
||||
static ZEND_FUNCTION(interface_exists);
|
||||
static ZEND_FUNCTION(function_exists);
|
||||
#if ZEND_DEBUG
|
||||
static ZEND_FUNCTION(leak);
|
||||
@@ -102,6 +103,7 @@ static zend_function_entry builtin_functions[] = {
|
||||
ZEND_FE(get_parent_class, NULL)
|
||||
ZEND_FE(method_exists, NULL)
|
||||
ZEND_FE(class_exists, NULL)
|
||||
ZEND_FE(interface_exists, NULL)
|
||||
ZEND_FE(function_exists, NULL)
|
||||
#if ZEND_DEBUG
|
||||
ZEND_FE(leak, NULL)
|
||||
@@ -661,7 +663,6 @@ ZEND_FUNCTION(get_class_vars)
|
||||
{
|
||||
zval **class_name;
|
||||
zend_class_entry *ce, **pce;
|
||||
zval *tmp;
|
||||
|
||||
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class_name)==FAILURE) {
|
||||
ZEND_WRONG_PARAM_COUNT();
|
||||
@@ -674,11 +675,41 @@ ZEND_FUNCTION(get_class_vars)
|
||||
} else {
|
||||
ce = *pce;
|
||||
array_init(return_value);
|
||||
if (!ce->constants_updated) {
|
||||
zend_hash_apply_with_argument(&ce->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC);
|
||||
ce->constants_updated = 1;
|
||||
|
||||
if (zend_hash_num_elements(&ce->default_properties) > 0) {
|
||||
HashPosition pos;
|
||||
zval **prop;
|
||||
|
||||
zend_hash_internal_pointer_reset_ex(&ce->default_properties, &pos);
|
||||
while (zend_hash_get_current_data_ex(&ce->default_properties, (void **) &prop, &pos) == SUCCESS) {
|
||||
char *key, *class_name, *prop_name;
|
||||
uint key_len;
|
||||
ulong num_index;
|
||||
zval *prop_copy;
|
||||
|
||||
zend_hash_get_current_key_ex(&ce->default_properties, &key, &key_len, &num_index, 0, &pos);
|
||||
zend_hash_move_forward_ex(&ce->default_properties, &pos);
|
||||
zend_unmangle_property_name(key, &class_name, &prop_name);
|
||||
if (class_name && class_name[0] != '*' && strcmp(class_name, ce->name)) {
|
||||
/* filter privates from base classes */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* copy: enforce read only access */
|
||||
ALLOC_ZVAL(prop_copy);
|
||||
*prop_copy = **prop;
|
||||
zval_copy_ctor(prop_copy);
|
||||
INIT_PZVAL(prop_copy);
|
||||
|
||||
/* this is necessary to make it able to work with default array
|
||||
* properties, returned to user */
|
||||
if (Z_TYPE_P(prop_copy) == IS_CONSTANT_ARRAY || Z_TYPE_P(prop_copy) == IS_CONSTANT) {
|
||||
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
add_assoc_zval(return_value, prop_name, prop_copy);
|
||||
}
|
||||
}
|
||||
zend_hash_copy(return_value->value.ht, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -819,11 +850,42 @@ ZEND_FUNCTION(class_exists)
|
||||
|
||||
found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
|
||||
free_alloca(lc_name);
|
||||
RETURN_BOOL(found == SUCCESS);
|
||||
RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
|
||||
}
|
||||
|
||||
if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
|
||||
RETURN_TRUE;
|
||||
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto bool interface_exists(string classname [, bool autoload])
|
||||
Checks if the class exists */
|
||||
ZEND_FUNCTION(interface_exists)
|
||||
{
|
||||
char *iface_name, *lc_name;
|
||||
zend_class_entry **ce;
|
||||
int iface_name_len;
|
||||
zend_bool autoload = 1;
|
||||
int found;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!autoload) {
|
||||
lc_name = do_alloca(iface_name_len + 1);
|
||||
zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
|
||||
|
||||
found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce);
|
||||
free_alloca(lc_name);
|
||||
RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
|
||||
}
|
||||
|
||||
if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
|
||||
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
|
||||
} else {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -1655,6 +1717,11 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML
|
||||
/* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */
|
||||
zend_bool build_filename_arg = 1;
|
||||
|
||||
if (!ptr->opline) {
|
||||
/* can happen when calling eval from a custom sapi */
|
||||
function_name = "unknown";
|
||||
build_filename_arg = 0;
|
||||
} else
|
||||
switch (ptr->opline->op2.u.constant.value.lval) {
|
||||
case ZEND_EVAL:
|
||||
function_name = "eval";
|
||||
|
||||
+104
-101
@@ -708,7 +708,7 @@ void zend_do_if_end(TSRMLS_D)
|
||||
void zend_check_writable_variable(znode *variable)
|
||||
{
|
||||
zend_uint type = variable->u.EA.type;
|
||||
|
||||
|
||||
if (type & ZEND_PARSED_METHOD_CALL) {
|
||||
zend_error(E_COMPILE_ERROR, "Can't use method return value in write context");
|
||||
}
|
||||
@@ -744,6 +744,8 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
|
||||
|
||||
le = fetch_list_ptr->head;
|
||||
|
||||
/* TODO: $foo->x->y->z = 1 should fetch "x" and "y" for R or RW, not just W */
|
||||
|
||||
while (le) {
|
||||
opline_ptr = (zend_op *)le->data;
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
@@ -761,6 +763,9 @@ void zend_do_end_variable_parse(int type, int arg_offset TSRMLS_DC)
|
||||
opline->opcode += 3;
|
||||
break;
|
||||
case BP_VAR_IS:
|
||||
if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot use [] for reading");
|
||||
}
|
||||
opline->opcode += 6; /* 3+3 */
|
||||
break;
|
||||
case BP_VAR_FUNC_ARG:
|
||||
@@ -992,35 +997,37 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
|
||||
fn_flags |= ZEND_ACC_PUBLIC;
|
||||
}
|
||||
|
||||
short_class_name = do_alloca(short_class_name_length + 1);
|
||||
zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length);
|
||||
/* Improve after RC: cache the lowercase class name */
|
||||
if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
|
||||
short_class_name = do_alloca(short_class_name_length + 1);
|
||||
zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length);
|
||||
/* Improve after RC: cache the lowercase class name */
|
||||
|
||||
if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) {
|
||||
if (CG(active_class_entry)->constructor) {
|
||||
zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
|
||||
} else {
|
||||
if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) {
|
||||
if (CG(active_class_entry)->constructor) {
|
||||
zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
|
||||
} else {
|
||||
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
|
||||
}
|
||||
} else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
|
||||
if (CG(active_class_entry)->constructor) {
|
||||
zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
|
||||
}
|
||||
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
|
||||
} else if (!(fn_flags & ZEND_ACC_STATIC)) {
|
||||
CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
|
||||
}
|
||||
} else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
|
||||
if (CG(active_class_entry)->constructor) {
|
||||
zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
|
||||
}
|
||||
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
|
||||
} else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
|
||||
CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
|
||||
} else if (!(fn_flags & ZEND_ACC_STATIC)) {
|
||||
CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
|
||||
free_alloca(short_class_name);
|
||||
}
|
||||
free_alloca(short_class_name);
|
||||
|
||||
efree(lcname);
|
||||
} else {
|
||||
@@ -1087,16 +1094,37 @@ void zend_do_handle_exception(TSRMLS_D)
|
||||
|
||||
void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
|
||||
{
|
||||
char lcname[16];
|
||||
int name_len;
|
||||
|
||||
zend_do_extended_info(TSRMLS_C);
|
||||
zend_do_return(NULL, 0 TSRMLS_CC);
|
||||
zend_do_handle_exception(TSRMLS_C);
|
||||
|
||||
pass_two(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
if (CG(active_class_entry)
|
||||
&& !strcmp(CG(active_op_array)->function_name, ZEND_CLONE_FUNC_NAME)
|
||||
&& CG(active_op_array)->num_args != 0) {
|
||||
zend_error(E_COMPILE_ERROR, "The clone method cannot accept any arguments");
|
||||
/* we don't care if the function name is longer, in fact lowercasing only
|
||||
* the beginning of the name speeds up the check process */
|
||||
name_len = strlen(CG(active_op_array)->function_name);
|
||||
zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
|
||||
lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
|
||||
|
||||
if (CG(active_class_entry)) {
|
||||
if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && CG(active_op_array)->num_args != 0) {
|
||||
zend_error(E_COMPILE_ERROR, "Destuctor %s::%s() cannot take arguments", CG(active_class_entry)->name, ZEND_DESTRUCTOR_FUNC_NAME);
|
||||
} else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && CG(active_op_array)->num_args != 0) {
|
||||
zend_error(E_COMPILE_ERROR, "Method %s::%s() cannot accept any arguments", CG(active_class_entry)->name, ZEND_CLONE_FUNC_NAME);
|
||||
} else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
|
||||
zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 1 argument", CG(active_class_entry)->name, ZEND_GET_FUNC_NAME);
|
||||
} else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && CG(active_op_array)->num_args != 2) {
|
||||
zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 2 arguments", CG(active_class_entry)->name, ZEND_SET_FUNC_NAME);
|
||||
} else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && CG(active_op_array)->num_args != 2) {
|
||||
zend_error(E_COMPILE_ERROR, "Method %s::%s() must take exactly 2 arguments", CG(active_class_entry)->name, ZEND_CALL_FUNC_NAME);
|
||||
}
|
||||
} else {
|
||||
if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
|
||||
zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
|
||||
@@ -1114,10 +1142,6 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
zend_arg_info *cur_arg_info;
|
||||
|
||||
if (CG(active_class_entry) && CG(active_class_entry)->destructor == (zend_function *) CG(active_op_array))
|
||||
{
|
||||
zend_error(E_COMPILE_ERROR, "Destuctor %s::%s() cannot take arguments", CG(active_class_entry)->name, CG(active_op_array)->function_name);
|
||||
}
|
||||
CG(active_op_array)->num_args++;
|
||||
opline->opcode = op;
|
||||
opline->result = *var;
|
||||
@@ -1675,9 +1699,11 @@ static void do_inherit_parent_constructor(zend_class_entry *ce)
|
||||
if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
|
||||
lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
|
||||
if (zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
|
||||
/* inherit parent's constructor */
|
||||
zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL);
|
||||
function_add_ref(function);
|
||||
if (function->common.fn_flags & ZEND_ACC_CTOR) {
|
||||
/* inherit parent's constructor */
|
||||
zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL);
|
||||
function_add_ref(function);
|
||||
}
|
||||
}
|
||||
efree(lc_parent_class_name);
|
||||
}
|
||||
@@ -1993,6 +2019,8 @@ void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce TSRML
|
||||
zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0);
|
||||
zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, ce);
|
||||
do_inherit_parent_constructor(ce);
|
||||
|
||||
zend_verify_abstract_class(ce TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
@@ -2100,6 +2128,10 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
|
||||
ce = *pce;
|
||||
}
|
||||
|
||||
if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
|
||||
}
|
||||
|
||||
zend_do_inheritance(ce, parent_ce TSRMLS_CC);
|
||||
|
||||
ce->refcount++;
|
||||
@@ -2307,22 +2339,10 @@ void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC)
|
||||
void zend_do_switch_cond(znode *cond TSRMLS_DC)
|
||||
{
|
||||
zend_switch_entry switch_entry;
|
||||
zend_op *opline;
|
||||
|
||||
/* Initialize the conditional value */
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_BOOL;
|
||||
opline->result.u.var = get_temporary_variable(CG(active_op_array));
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
opline->op1.u.constant.type = IS_BOOL;
|
||||
opline->op1.u.constant.value.lval = 0;
|
||||
INIT_PZVAL(&opline->op1.u.constant);
|
||||
SET_UNUSED(opline->op2);
|
||||
|
||||
switch_entry.cond = *cond;
|
||||
switch_entry.default_case = -1;
|
||||
switch_entry.control_var = opline->result.u.var;
|
||||
switch_entry.control_var = -1;
|
||||
zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
|
||||
|
||||
do_begin_loop(TSRMLS_C);
|
||||
@@ -2345,17 +2365,6 @@ void zend_do_switch_end(znode *case_list TSRMLS_DC)
|
||||
CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
|
||||
}
|
||||
|
||||
/* add code to jmp to default case */
|
||||
if (switch_entry_ptr->default_case != -1) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_JMPZ;
|
||||
opline->op1.op_type = IS_TMP_VAR;
|
||||
opline->op1.u.var = switch_entry_ptr->control_var;
|
||||
opline->op2.u.opline_num = switch_entry_ptr->default_case;
|
||||
SET_UNUSED(opline->op2);
|
||||
}
|
||||
|
||||
|
||||
/* remember break/continue loop information */
|
||||
CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
|
||||
CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
|
||||
@@ -2386,6 +2395,9 @@ void zend_do_case_before_statement(znode *case_list, znode *case_token, znode *c
|
||||
|
||||
zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
|
||||
|
||||
if (switch_entry_ptr->control_var == -1) {
|
||||
switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array));
|
||||
}
|
||||
opline->opcode = ZEND_CASE;
|
||||
opline->result.u.var = switch_entry_ptr->control_var;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
@@ -2421,13 +2433,8 @@ void zend_do_case_after_statement(znode *result, znode *case_token TSRMLS_DC)
|
||||
SET_UNUSED(opline->op2);
|
||||
result->u.opline_num = next_op_number;
|
||||
|
||||
switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) {
|
||||
case ZEND_JMP:
|
||||
CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array));
|
||||
break;
|
||||
case ZEND_JMPZ:
|
||||
CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
|
||||
break;
|
||||
if (case_token->u.opline_num != -1) {
|
||||
CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2436,32 +2443,16 @@ void zend_do_case_after_statement(znode *result, znode *case_token TSRMLS_DC)
|
||||
void zend_do_default_before_statement(znode *case_list, znode *default_token TSRMLS_DC)
|
||||
{
|
||||
int next_op_number = get_next_op_number(CG(active_op_array));
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
zend_switch_entry *switch_entry_ptr;
|
||||
|
||||
zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr);
|
||||
|
||||
opline->opcode = ZEND_JMP;
|
||||
SET_UNUSED(opline->op1);
|
||||
SET_UNUSED(opline->op2);
|
||||
default_token->u.opline_num = next_op_number;
|
||||
|
||||
next_op_number = get_next_op_number(CG(active_op_array));
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_BOOL;
|
||||
opline->result.u.var = switch_entry_ptr->control_var;
|
||||
opline->result.op_type = IS_TMP_VAR;
|
||||
opline->op1.op_type = IS_CONST;
|
||||
opline->op1.u.constant.type = IS_BOOL;
|
||||
opline->op1.u.constant.value.lval = 1;
|
||||
INIT_PZVAL(&opline->op1.u.constant);
|
||||
SET_UNUSED(opline->op2);
|
||||
default_token->u.opline_num = -1;
|
||||
switch_entry_ptr->default_case = next_op_number;
|
||||
|
||||
if (case_list->op_type==IS_UNUSED) {
|
||||
return;
|
||||
}
|
||||
next_op_number = get_next_op_number(CG(active_op_array));
|
||||
CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number;
|
||||
}
|
||||
|
||||
@@ -3321,7 +3312,7 @@ void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brack
|
||||
|
||||
void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *foreach_token TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
zend_op *opline;
|
||||
znode result_value, result_key, dummy;
|
||||
zend_bool assign_by_ref=0;
|
||||
|
||||
@@ -3332,6 +3323,9 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
|
||||
tmp = key;
|
||||
key = value;
|
||||
value = tmp;
|
||||
|
||||
/* Mark extended_value in case both key and value are being used */
|
||||
CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_FETCH_WITH_KEY;
|
||||
}
|
||||
|
||||
if ((key->op_type != IS_UNUSED) && (key->u.EA.type & ZEND_PARSED_REFERENCE_VARIABLE)) {
|
||||
@@ -3343,21 +3337,23 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
|
||||
if (!CG(active_op_array)->opcodes[foreach_token->u.opline_num-1].extended_value) {
|
||||
zend_error(E_COMPILE_ERROR, "Cannot create references to elements of a temporary array expression");
|
||||
}
|
||||
CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value = 1;
|
||||
/* Mark extended_value for assign-by-reference */
|
||||
CG(active_op_array)->opcodes[foreach_token->u.opline_num].extended_value |= ZEND_FE_FETCH_BYREF;
|
||||
}
|
||||
|
||||
opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
|
||||
opline->result.op_type = IS_VAR;
|
||||
opline->result.u.EA.type = 0;
|
||||
opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
|
||||
opline->op1 = *as_token;
|
||||
opline->op2.op_type = IS_CONST;
|
||||
opline->op2.u.constant.type = IS_LONG;
|
||||
opline->op2.u.constant.value.lval = 0;
|
||||
opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
|
||||
result_value = opline->result;
|
||||
|
||||
if (key->op_type != IS_UNUSED) {
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
|
||||
opline->result.op_type = IS_VAR;
|
||||
opline->result.u.EA.type = 0;
|
||||
opline->result.u.opline_num = get_temporary_variable(CG(active_op_array));
|
||||
opline->op1 = *as_token;
|
||||
opline->op2.op_type = IS_CONST;
|
||||
opline->op2.u.constant.type = IS_LONG;
|
||||
opline->op2.u.constant.value.lval = 0;
|
||||
opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
|
||||
result_value = opline->result;
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
opline->opcode = ZEND_FETCH_DIM_TMP_VAR;
|
||||
opline->result.op_type = IS_VAR;
|
||||
@@ -3369,10 +3365,18 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
|
||||
opline->op2.u.constant.value.lval = 1;
|
||||
opline->extended_value = ZEND_FETCH_STANDARD; /* ignored in fetch_dim_tmp_var, but what the hell. */
|
||||
result_key = opline->result;
|
||||
} else {
|
||||
result_value = CG(active_op_array)->opcodes[foreach_token->u.opline_num].result;
|
||||
}
|
||||
|
||||
if (assign_by_ref) {
|
||||
zend_do_assign_ref(&dummy, value, &result_value TSRMLS_CC);
|
||||
if (key->op_type == IS_UNUSED) {
|
||||
/* Mark FE_FETCH as IS_VAR as it holds the data directly as a value */
|
||||
CG(active_op_array)->opcodes[foreach_token->u.opline_num].result.op_type = IS_VAR;
|
||||
zend_do_assign_ref(NULL, value, &CG(active_op_array)->opcodes[foreach_token->u.opline_num].result TSRMLS_CC);
|
||||
} else {
|
||||
zend_do_assign_ref(NULL, value, &result_value TSRMLS_CC);
|
||||
}
|
||||
} else {
|
||||
zend_do_assign(&dummy, value, &result_value TSRMLS_CC);
|
||||
}
|
||||
@@ -3380,8 +3384,8 @@ void zend_do_foreach_cont(znode *value, znode *key, znode *as_token, znode *fore
|
||||
if (key->op_type != IS_UNUSED) {
|
||||
zend_do_assign(&dummy, key, &result_key TSRMLS_CC);
|
||||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED;
|
||||
zend_do_free(as_token TSRMLS_CC);
|
||||
}
|
||||
zend_do_free(as_token TSRMLS_CC);
|
||||
|
||||
do_begin_loop(TSRMLS_C);
|
||||
INC_BPC(CG(active_op_array));
|
||||
@@ -3495,7 +3499,6 @@ void zend_do_exit(znode *result, znode *message TSRMLS_DC)
|
||||
result->u.constant.value.lval = 1;
|
||||
}
|
||||
|
||||
|
||||
void zend_do_begin_silence(znode *strudel_token TSRMLS_DC)
|
||||
{
|
||||
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
+6
-11
@@ -33,7 +33,6 @@
|
||||
#define DEBUG_ZEND 0
|
||||
|
||||
#define FREE_PNODE(znode) zval_dtor(&znode->u.constant);
|
||||
#define FREE_OP(Ts, op, should_free) if (should_free) zval_dtor(should_free);
|
||||
|
||||
#define SET_UNUSED(op) (op).op_type = IS_UNUSED
|
||||
|
||||
@@ -68,8 +67,8 @@ typedef struct _znode {
|
||||
|
||||
typedef struct _zend_execute_data zend_execute_data;
|
||||
|
||||
#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data, zend_op *opline, zend_op_array *op_array TSRMLS_DC
|
||||
#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data, opline, op_array TSRMLS_CC
|
||||
#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data TSRMLS_DC
|
||||
#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data TSRMLS_CC
|
||||
|
||||
typedef int (*opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);
|
||||
|
||||
@@ -794,19 +793,14 @@ int zendlex(znode *zendlval TSRMLS_DC);
|
||||
#define ZEND_FETCH_STANDARD 0
|
||||
#define ZEND_FETCH_ADD_LOCK 1
|
||||
|
||||
#define ZEND_FE_FETCH_BYREF 1
|
||||
#define ZEND_FE_FETCH_WITH_KEY 2
|
||||
|
||||
#define ZEND_MEMBER_FUNC_CALL 1<<0
|
||||
|
||||
#define ZEND_ARG_SEND_BY_REF (1<<0)
|
||||
#define ZEND_ARG_COMPILE_TIME_BOUND (1<<1)
|
||||
|
||||
#define AI_USE_PTR(ai) \
|
||||
if ((ai).ptr_ptr) { \
|
||||
(ai).ptr = *((ai).ptr_ptr); \
|
||||
(ai).ptr_ptr = &((ai).ptr); \
|
||||
} else { \
|
||||
(ai).ptr = NULL; \
|
||||
}
|
||||
|
||||
/* Lost In Stupid Parentheses */
|
||||
#define ARG_SHOULD_BE_SENT_BY_REF(zf, arg_num) \
|
||||
( \
|
||||
@@ -840,6 +834,7 @@ END_EXTERN_C()
|
||||
#define ZEND_GET_FUNC_NAME "__get"
|
||||
#define ZEND_SET_FUNC_NAME "__set"
|
||||
#define ZEND_CALL_FUNC_NAME "__call"
|
||||
#define ZEND_AUTOLOAD_FUNC_NAME "__autoload"
|
||||
|
||||
#endif /* ZEND_COMPILE_H */
|
||||
|
||||
|
||||
+146
-15
@@ -26,10 +26,11 @@
|
||||
#include "zend_reflection_api.h"
|
||||
#include "zend_builtin_functions.h"
|
||||
#include "zend_interfaces.h"
|
||||
#include "zend_exceptions.h"
|
||||
|
||||
zend_class_entry *default_exception_ce;
|
||||
zend_class_entry *error_exception_ce;
|
||||
static zend_object_handlers default_exception_handlers;
|
||||
ZEND_API void zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC);
|
||||
ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
|
||||
|
||||
|
||||
@@ -74,7 +75,7 @@ ZEND_API void zend_clear_exception(TSRMLS_D)
|
||||
#endif
|
||||
}
|
||||
|
||||
static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC)
|
||||
static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_type, int skip_top_traces TSRMLS_DC)
|
||||
{
|
||||
zval tmp, obj;
|
||||
zend_object *object;
|
||||
@@ -90,7 +91,7 @@ static zend_object_value zend_default_exception_new(zend_class_entry *class_type
|
||||
ALLOC_ZVAL(trace);
|
||||
trace->is_ref = 0;
|
||||
trace->refcount = 0;
|
||||
zend_fetch_debug_backtrace(trace, 0 TSRMLS_CC);
|
||||
zend_fetch_debug_backtrace(trace, skip_top_traces TSRMLS_CC);
|
||||
|
||||
zend_update_property_string(default_exception_ce, &obj, "file", sizeof("file")-1, zend_get_executed_filename(TSRMLS_C) TSRMLS_CC);
|
||||
zend_update_property_long(default_exception_ce, &obj, "line", sizeof("line")-1, zend_get_executed_lineno(TSRMLS_C) TSRMLS_CC);
|
||||
@@ -99,12 +100,29 @@ static zend_object_value zend_default_exception_new(zend_class_entry *class_type
|
||||
return obj.value.obj;
|
||||
}
|
||||
|
||||
static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC)
|
||||
{
|
||||
return zend_default_exception_new_ex(class_type, 0 TSRMLS_CC);
|
||||
}
|
||||
|
||||
static zend_object_value zend_error_exception_new(zend_class_entry *class_type TSRMLS_DC)
|
||||
{
|
||||
return zend_default_exception_new_ex(class_type, 2 TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto Exception Exception::__clone()
|
||||
Clone the exception object */
|
||||
ZEND_METHOD(exception, __clone)
|
||||
{
|
||||
/* Should never be executable */
|
||||
zend_throw_exception(NULL, "Cannot clone object using __clone()", 0 TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto Exception::__construct(string message, int code)
|
||||
Exception constructor */
|
||||
ZEND_METHOD(exception, __construct)
|
||||
{
|
||||
char *message = NULL;
|
||||
@@ -126,6 +144,43 @@ ZEND_METHOD(exception, __construct)
|
||||
zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto ErrorException::__construct(string message, int code, int severity [, $filename [, $lineno]])
|
||||
ErrorException constructor */
|
||||
ZEND_METHOD(error_exception, __construct)
|
||||
{
|
||||
char *message = NULL, *filename = NULL;
|
||||
long code = 0, severity = E_ERROR, lineno;
|
||||
zval *object;
|
||||
int argc = ZEND_NUM_ARGS(), message_len, filename_len;
|
||||
|
||||
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC, "|sllsl", &message, &message_len, &code, &severity, &filename, &filename_len, &lineno) == FAILURE) {
|
||||
zend_error(E_CORE_ERROR, "Wrong parameter count for exception([string $exception [, long $code ]])");
|
||||
}
|
||||
|
||||
object = getThis();
|
||||
|
||||
if (message) {
|
||||
zend_update_property_string(default_exception_ce, object, "message", sizeof("message")-1, message TSRMLS_CC);
|
||||
}
|
||||
|
||||
if (code) {
|
||||
zend_update_property_long(default_exception_ce, object, "code", sizeof("code")-1, code TSRMLS_CC);
|
||||
}
|
||||
|
||||
zend_update_property_long(default_exception_ce, object, "severity", sizeof("severity")-1, severity TSRMLS_CC);
|
||||
|
||||
if (argc >= 4) {
|
||||
zend_update_property_string(default_exception_ce, object, "file", sizeof("file")-1, filename TSRMLS_CC);
|
||||
if (argc < 5) {
|
||||
lineno = 0; // invalidate lineno
|
||||
}
|
||||
zend_update_property_long(default_exception_ce, object, "line", sizeof("line")-1, lineno TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
#define DEFAULT_0_PARAMS \
|
||||
if (ZEND_NUM_ARGS() > 0) { \
|
||||
@@ -142,40 +197,71 @@ static void _default_exception_get_entry(zval *object, char *name, int name_len,
|
||||
zval_copy_ctor(return_value);
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto string Exception::getFile()
|
||||
Get the file in which the exception occurred */
|
||||
ZEND_METHOD(exception, getFile)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "file", sizeof("file")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto int Exception::getLine()
|
||||
Get the line in which the exception occurred */
|
||||
ZEND_METHOD(exception, getLine)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "line", sizeof("line")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto string Exception::getMessage()
|
||||
Get the exception message */
|
||||
ZEND_METHOD(exception, getMessage)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "message", sizeof("message")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto int Exception::getCode()
|
||||
Get the exception code */
|
||||
ZEND_METHOD(exception, getCode)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "code", sizeof("code")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto array Exception::getTrace()
|
||||
Get the stack trace for the location in which the exception occurred */
|
||||
ZEND_METHOD(exception, getTrace)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "trace", sizeof("trace")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
||||
/* {{{ proto int ErrorException::getSeverity()
|
||||
Get the exception severity */
|
||||
ZEND_METHOD(error_exception, getSeverity)
|
||||
{
|
||||
DEFAULT_0_PARAMS;
|
||||
|
||||
_default_exception_get_entry(getThis(), "severity", sizeof("severity")-1, return_value TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ ZEND_METHOD(exception, gettraceasstring) */
|
||||
#define TRACE_APPEND_CHR(chr) \
|
||||
@@ -329,6 +415,9 @@ static int _build_trace_string(zval **frame, int num_args, va_list args, zend_ha
|
||||
return ZEND_HASH_APPLY_KEEP;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto string Exception::getTraceAsString()
|
||||
Obtain the backtrace for the exception as a string (instead of an array) */
|
||||
ZEND_METHOD(exception, getTraceAsString)
|
||||
{
|
||||
zval *trace;
|
||||
@@ -359,6 +448,9 @@ static int zend_spprintf(char **message, int max_len, char *format, ...)
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/* {{{ proto string Exception::__toString()
|
||||
Obtain the string representation of the Exception object */
|
||||
ZEND_METHOD(exception, __toString)
|
||||
{
|
||||
zval message, file, line, *trace;
|
||||
@@ -417,6 +509,7 @@ ZEND_METHOD(exception, __toString)
|
||||
|
||||
RETURN_STRINGL(str, len, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* All functions that may be used in uncaught exception handlers must be final
|
||||
* and must not throw exceptions. Otherwise we would need a facility to handle
|
||||
@@ -427,9 +520,15 @@ ZEND_METHOD(exception, __toString)
|
||||
* And never try to change the state of exceptions and never implement anything
|
||||
* that gives the user anything to accomplish this.
|
||||
*/
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO(arginfo_exception___construct, 0)
|
||||
ZEND_ARG_INFO(0, message)
|
||||
ZEND_ARG_INFO(0, code)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry default_exception_functions[] = {
|
||||
ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, __construct, NULL, 0)
|
||||
ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
@@ -440,6 +539,21 @@ static zend_function_entry default_exception_functions[] = {
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_error_exception___construct, 0, 0, 3)
|
||||
ZEND_ARG_INFO(0, message)
|
||||
ZEND_ARG_INFO(0, code)
|
||||
ZEND_ARG_INFO(0, severity)
|
||||
ZEND_ARG_INFO(0, filename)
|
||||
ZEND_ARG_INFO(0, lineno)
|
||||
ZEND_END_ARG_INFO();
|
||||
|
||||
static zend_function_entry error_exception_functions[] = {
|
||||
ZEND_ME(error_exception, __construct, arginfo_error_exception___construct, ZEND_ACC_PUBLIC)
|
||||
ZEND_ME(error_exception, getSeverity, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
void zend_register_default_exception(TSRMLS_D)
|
||||
{
|
||||
zend_class_entry ce;
|
||||
@@ -456,6 +570,11 @@ void zend_register_default_exception(TSRMLS_D)
|
||||
zend_declare_property_null(default_exception_ce, "file", sizeof("file")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||||
zend_declare_property_null(default_exception_ce, "line", sizeof("line")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||||
zend_declare_property_null(default_exception_ce, "trace", sizeof("trace")-1, ZEND_ACC_PRIVATE TSRMLS_CC);
|
||||
|
||||
INIT_CLASS_ENTRY(ce, "ErrorException", error_exception_functions);
|
||||
error_exception_ce = zend_register_internal_class_ex(&ce, default_exception_ce, NULL TSRMLS_CC);
|
||||
error_exception_ce->create_object = zend_error_exception_new;
|
||||
zend_declare_property_long(error_exception_ce, "severity", sizeof("severity")-1, E_ERROR, ZEND_ACC_PROTECTED TSRMLS_CC);
|
||||
}
|
||||
|
||||
ZEND_API zend_class_entry *zend_exception_get_default(void)
|
||||
@@ -463,15 +582,15 @@ ZEND_API zend_class_entry *zend_exception_get_default(void)
|
||||
return default_exception_ce;
|
||||
}
|
||||
|
||||
ZEND_API void zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...)
|
||||
ZEND_API zend_class_entry *zend_get_error_exception(void)
|
||||
{
|
||||
return error_exception_ce;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC)
|
||||
{
|
||||
zval *ex;
|
||||
va_list arg;
|
||||
char *message;
|
||||
|
||||
va_start(arg, format);
|
||||
zend_vspprintf(&message, 0, format, arg);
|
||||
va_end(arg);
|
||||
|
||||
MAKE_STD_ZVAL(ex);
|
||||
if (exception_ce) {
|
||||
@@ -492,18 +611,30 @@ ZEND_API void zend_throw_exception_ex(zend_class_entry *exception_ce, long code
|
||||
zend_update_property_long(default_exception_ce, ex, "code", sizeof("code")-1, code TSRMLS_CC);
|
||||
}
|
||||
|
||||
efree(message);
|
||||
|
||||
zend_throw_exception_internal(ex TSRMLS_CC);
|
||||
return ex;
|
||||
}
|
||||
|
||||
|
||||
ZEND_API void zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC)
|
||||
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...)
|
||||
{
|
||||
zend_throw_exception_ex(exception_ce, code TSRMLS_CC, "%s", message);
|
||||
va_list arg;
|
||||
char *message;
|
||||
|
||||
va_start(arg, format);
|
||||
zend_vspprintf(&message, 0, format, arg);
|
||||
va_end(arg);
|
||||
return zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
}
|
||||
|
||||
|
||||
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC)
|
||||
{
|
||||
zval *ex = zend_throw_exception(exception_ce, message, code TSRMLS_CC);
|
||||
zend_update_property_long(default_exception_ce, ex, "severity", sizeof("severity")-1, severity TSRMLS_CC);
|
||||
return ex;
|
||||
}
|
||||
|
||||
static void zend_error_va(int type, const char *file, uint lineno, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@@ -31,15 +31,18 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC);
|
||||
void zend_register_default_exception(TSRMLS_D);
|
||||
|
||||
ZEND_API zend_class_entry *zend_exception_get_default(void);
|
||||
ZEND_API zend_class_entry *zend_get_error_exception(void);
|
||||
ZEND_API void zend_register_default_classes(TSRMLS_D);
|
||||
|
||||
/* exception_ce NULL or zend_exception_get_default() or a derived class
|
||||
* message NULL or the message of the exception */
|
||||
ZEND_API void zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC);
|
||||
ZEND_API void zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...);
|
||||
ZEND_API zval * zend_throw_exception(zend_class_entry *exception_ce, char *message, long code TSRMLS_DC);
|
||||
ZEND_API zval * zend_throw_exception_ex(zend_class_entry *exception_ce, long code TSRMLS_DC, char *format, ...);
|
||||
ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC);
|
||||
ZEND_API void zend_clear_exception(TSRMLS_D);
|
||||
|
||||
ZEND_API zval * zend_throw_error_exception(zend_class_entry *exception_ce, char *message, long code, int severity TSRMLS_DC);
|
||||
|
||||
extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
|
||||
|
||||
/* show an exception using zend_error(E_ERROR,...) */
|
||||
|
||||
+831
-424
File diff suppressed because it is too large.
Load diff
@@ -49,6 +49,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
|
||||
|
||||
void init_executor(TSRMLS_D);
|
||||
void shutdown_executor(TSRMLS_D);
|
||||
void shutdown_destructors(TSRMLS_D);
|
||||
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC);
|
||||
ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
|
||||
ZEND_API int zend_is_true(zval *op);
|
||||
|
||||
+40
-27
@@ -138,6 +138,7 @@ void init_executor(TSRMLS_D)
|
||||
|
||||
EG(in_execution) = 0;
|
||||
EG(in_autoload) = NULL;
|
||||
EG(autoload_func) = NULL;
|
||||
|
||||
zend_ptr_stack_init(&EG(argument_stack));
|
||||
zend_ptr_stack_push(&EG(argument_stack), (void *) NULL);
|
||||
@@ -157,7 +158,6 @@ void init_executor(TSRMLS_D)
|
||||
|
||||
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_activator TSRMLS_CC);
|
||||
EG(opline_ptr) = NULL;
|
||||
EG(garbage_ptr) = 0;
|
||||
|
||||
zend_hash_init(&EG(included_files), 5, NULL, NULL, 0);
|
||||
|
||||
@@ -187,6 +187,12 @@ void init_executor(TSRMLS_D)
|
||||
EG(float_separator)[0] = '.';
|
||||
}
|
||||
|
||||
void shutdown_destructors(TSRMLS_D) {
|
||||
zend_try {
|
||||
zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC);
|
||||
} zend_end_try();
|
||||
}
|
||||
|
||||
void shutdown_executor(TSRMLS_D)
|
||||
{
|
||||
zend_try {
|
||||
@@ -206,7 +212,6 @@ void shutdown_executor(TSRMLS_D)
|
||||
}
|
||||
*/
|
||||
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC);
|
||||
zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC);
|
||||
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
|
||||
} zend_end_try();
|
||||
|
||||
@@ -247,12 +252,6 @@ void shutdown_executor(TSRMLS_D)
|
||||
zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
|
||||
zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
|
||||
|
||||
while (EG(garbage_ptr)) {
|
||||
if (EG(garbage)[--EG(garbage_ptr)]->refcount==1) {
|
||||
zval_ptr_dtor(&EG(garbage)[EG(garbage_ptr)]);
|
||||
}
|
||||
}
|
||||
|
||||
zend_ptr_stack_destroy(&EG(argument_stack));
|
||||
|
||||
/* Destroy all op arrays */
|
||||
@@ -514,13 +513,18 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
|
||||
|
||||
int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC)
|
||||
{
|
||||
zval ***params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
|
||||
zval ***params_array;
|
||||
zend_uint i;
|
||||
int ex_retval;
|
||||
zval *local_retval_ptr;
|
||||
|
||||
for (i=0; i<param_count; i++) {
|
||||
params_array[i] = ¶ms[i];
|
||||
if (param_count) {
|
||||
params_array = (zval ***) emalloc(sizeof(zval **)*param_count);
|
||||
for (i=0; i<param_count; i++) {
|
||||
params_array[i] = ¶ms[i];
|
||||
}
|
||||
} else {
|
||||
params_array = NULL;
|
||||
}
|
||||
ex_retval = call_user_function_ex(function_table, object_pp, function_name, &local_retval_ptr, param_count, params_array, 1, NULL TSRMLS_CC);
|
||||
if (local_retval_ptr) {
|
||||
@@ -528,7 +532,9 @@ int call_user_function(HashTable *function_table, zval **object_pp, zval *functi
|
||||
} else {
|
||||
INIT_ZVAL(*retval_ptr);
|
||||
}
|
||||
efree(params_array);
|
||||
if (params_array) {
|
||||
efree(params_array);
|
||||
}
|
||||
return ex_retval;
|
||||
}
|
||||
|
||||
@@ -559,9 +565,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
zend_function_state *original_function_state_ptr;
|
||||
zend_op_array *original_op_array;
|
||||
zend_op **original_opline_ptr;
|
||||
zval *orig_free_op1, *orig_free_op2;
|
||||
int (*orig_unary_op)(zval *result, zval *op1);
|
||||
int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
zend_class_entry *current_scope;
|
||||
zend_class_entry *calling_scope = NULL;
|
||||
zval *current_this;
|
||||
@@ -769,7 +772,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
fci->param_count = 2;
|
||||
}
|
||||
|
||||
zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) fci->param_count, NULL);
|
||||
zend_ptr_stack_2_push(&EG(argument_stack), (void *) (long) fci->param_count, NULL);
|
||||
|
||||
original_function_state_ptr = EG(function_state_ptr);
|
||||
EG(function_state_ptr) = &EX(function_state);
|
||||
@@ -828,10 +831,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
EG(return_value_ptr_ptr) = fci->retval_ptr_ptr;
|
||||
EG(active_op_array) = (zend_op_array *) EX(function_state).function;
|
||||
original_opline_ptr = EG(opline_ptr);
|
||||
orig_free_op1 = EG(free_op1);
|
||||
orig_free_op2 = EG(free_op2);
|
||||
orig_unary_op = EG(unary_op);
|
||||
orig_binary_op = EG(binary_op);
|
||||
zend_execute(EG(active_op_array) TSRMLS_CC);
|
||||
if (!fci->symbol_table) {
|
||||
zend_hash_destroy(EG(active_symbol_table));
|
||||
@@ -841,10 +840,6 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
|
||||
EG(active_op_array) = original_op_array;
|
||||
EG(return_value_ptr_ptr)=original_return_value;
|
||||
EG(opline_ptr) = original_opline_ptr;
|
||||
EG(free_op1) = orig_free_op1;
|
||||
EG(free_op2) = orig_free_op2;
|
||||
EG(unary_op) = orig_unary_op;
|
||||
EG(binary_op) = orig_binary_op;
|
||||
} else {
|
||||
ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr);
|
||||
if (EX(function_state).function->common.scope) {
|
||||
@@ -884,6 +879,8 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
|
||||
char *lc_name;
|
||||
zval *exception;
|
||||
char dummy = 1;
|
||||
zend_fcall_info fcall_info;
|
||||
zend_fcall_info_cache fcall_cache;
|
||||
|
||||
lc_name = do_alloca(name_length + 1);
|
||||
zend_str_tolower_copy(lc_name, name, name_length);
|
||||
@@ -911,16 +908,32 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
ZVAL_STRINGL(&autoload_function, "__autoload", sizeof("__autoload")-1, 0);
|
||||
ZVAL_STRINGL(&autoload_function, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1, 0);
|
||||
|
||||
INIT_PZVAL(class_name_ptr);
|
||||
ZVAL_STRINGL(class_name_ptr, name, name_length, 0);
|
||||
|
||||
args[0] = &class_name_ptr;
|
||||
|
||||
fcall_info.size = sizeof(fcall_info);
|
||||
fcall_info.function_table = EG(function_table);
|
||||
fcall_info.function_name = &autoload_function;
|
||||
fcall_info.symbol_table = NULL;
|
||||
fcall_info.retval_ptr_ptr = &retval_ptr;
|
||||
fcall_info.param_count = 1;
|
||||
fcall_info.params = args;
|
||||
fcall_info.object_pp = NULL;
|
||||
fcall_info.no_separation = 1;
|
||||
|
||||
fcall_cache.initialized = EG(autoload_func) ? 1 : 0;
|
||||
fcall_cache.function_handler = EG(autoload_func);
|
||||
fcall_cache.calling_scope = NULL;
|
||||
fcall_cache.object_pp = NULL;
|
||||
|
||||
exception = EG(exception);
|
||||
EG(exception) = NULL;
|
||||
retval = call_user_function_ex(EG(function_table), NULL, &autoload_function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC);
|
||||
retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
|
||||
EG(autoload_func) = fcall_cache.function_handler;
|
||||
|
||||
zend_hash_del(EG(in_autoload), lc_name, name_length+1);
|
||||
|
||||
@@ -932,7 +945,7 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
|
||||
|
||||
if (EG(exception)) {
|
||||
free_alloca(lc_name);
|
||||
zend_error(E_ERROR, "__autoload(%s) threw an exception of type '%s'", name, Z_OBJCE_P(EG(exception))->name);
|
||||
zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
|
||||
return FAILURE;
|
||||
}
|
||||
EG(exception) = exception;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
/* The first number is the engine version and the rest is the date.
|
||||
* This way engine 2 API no. is always greater than engine 1 API no..
|
||||
*/
|
||||
#define ZEND_EXTENSION_API_NO 220040412
|
||||
#define ZEND_EXTENSION_API_NO 220040718
|
||||
|
||||
typedef struct _zend_extension_version_info {
|
||||
int zend_extension_api_no;
|
||||
|
||||
@@ -104,7 +104,6 @@ typedef struct _zend_fast_cache_list_entry {
|
||||
|
||||
|
||||
|
||||
|
||||
/* fast cache for zval's */
|
||||
#define ALLOC_ZVAL(z) \
|
||||
ZEND_FAST_ALLOC(z, zval, ZVAL_CACHE_LIST)
|
||||
|
||||
+1
-6
@@ -192,6 +192,7 @@ struct _zend_executor_globals {
|
||||
|
||||
zend_bool in_execution;
|
||||
HashTable *in_autoload;
|
||||
zend_function *autoload_func;
|
||||
zend_bool bailout_set;
|
||||
zend_bool full_tables_cleanup;
|
||||
zend_bool ze1_compatibility_mode;
|
||||
@@ -207,12 +208,6 @@ struct _zend_executor_globals {
|
||||
HashTable persistent_list;
|
||||
|
||||
zend_ptr_stack argument_stack;
|
||||
zval *free_op1, *free_op2;
|
||||
int (*unary_op)(zval *result, zval *op1);
|
||||
int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC);
|
||||
|
||||
zval *garbage[2];
|
||||
int garbage_ptr;
|
||||
|
||||
int user_error_handler_error_reporting;
|
||||
zval *user_error_handler;
|
||||
|
||||
+14
-8
@@ -1138,14 +1138,20 @@ ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func,
|
||||
ht->pListTail = NULL;
|
||||
ht->pInternalPointer = ht->pListHead;
|
||||
|
||||
for (j = 0; j < i; j++) {
|
||||
if (ht->pListTail) {
|
||||
ht->pListTail->pListNext = arTmp[j];
|
||||
}
|
||||
arTmp[j]->pListLast = ht->pListTail;
|
||||
arTmp[j]->pListNext = NULL;
|
||||
ht->pListTail = arTmp[j];
|
||||
}
|
||||
arTmp[0]->pListLast = NULL;
|
||||
if (i > 1) {
|
||||
arTmp[0]->pListNext = arTmp[1];
|
||||
for (j = 1; j < i-1; j++) {
|
||||
arTmp[j]->pListLast = arTmp[j-1];
|
||||
arTmp[j]->pListNext = arTmp[j+1];
|
||||
}
|
||||
arTmp[j]->pListLast = ht->pListTail;
|
||||
arTmp[j]->pListNext = NULL;
|
||||
} else {
|
||||
arTmp[0]->pListNext = NULL;
|
||||
}
|
||||
ht->pListTail = arTmp[i-1];
|
||||
|
||||
pefree(arTmp, ht->persistent);
|
||||
HANDLE_UNBLOCK_INTERRUPTIONS();
|
||||
|
||||
|
||||
+10
-4
@@ -159,6 +159,12 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
|
||||
switch (token_type) {
|
||||
case T_END_HEREDOC:
|
||||
zend_html_puts(token.value.str.val, token.value.str.len TSRMLS_CC);
|
||||
{
|
||||
char *ptr = LANG_SCNG(yy_text);
|
||||
if (ptr[LANG_SCNG(yy_leng) - 1] != ';') {
|
||||
zend_html_putc('\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC);
|
||||
@@ -203,7 +209,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
switch (token_type) {
|
||||
case T_WHITESPACE:
|
||||
if (!prev_space) {
|
||||
putchar(' ');
|
||||
zend_write(" ", sizeof(" ") - 1);
|
||||
prev_space = 1;
|
||||
}
|
||||
/* lack of break; is intentional */
|
||||
@@ -215,9 +221,9 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
case T_END_HEREDOC: {
|
||||
char *ptr = LANG_SCNG(yy_text);
|
||||
|
||||
fwrite(ptr, LANG_SCNG(yy_leng) - 1, 1, stdout);
|
||||
zend_write(ptr, LANG_SCNG(yy_leng) - 1);
|
||||
/* The ensure that we only write one ; and that it followed by the required newline */
|
||||
putchar('\n');
|
||||
zend_write("\n", sizeof("\n") - 1);
|
||||
if (ptr[LANG_SCNG(yy_leng) - 1] == ';') {
|
||||
lex_scan(&token TSRMLS_CC);
|
||||
}
|
||||
@@ -226,7 +232,7 @@ ZEND_API void zend_strip(TSRMLS_D)
|
||||
break;
|
||||
|
||||
default:
|
||||
fwrite(LANG_SCNG(yy_text), LANG_SCNG(yy_leng), 1, stdout);
|
||||
zend_write(LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+16
-1
@@ -147,10 +147,25 @@ ZEND_API int zend_register_ini_entries(zend_ini_entry *ini_entry, int module_num
|
||||
zend_ini_entry *p = ini_entry;
|
||||
zend_ini_entry *hashed_ini_entry;
|
||||
zval default_value;
|
||||
HashTable *directives = registered_zend_ini_directives;
|
||||
|
||||
#ifdef ZTS
|
||||
/* if we are called during the request, eg: from dl(),
|
||||
* then we should not touch the global directives table,
|
||||
* and should update the per-(request|thread) version instead.
|
||||
* This solves two problems: one is that ini entries for dl()'d
|
||||
* extensions will now work, and the second is that updating the
|
||||
* global hash here from dl() is not mutex protected and can
|
||||
* lead to death.
|
||||
*/
|
||||
if (directives != EG(ini_directives)) {
|
||||
directives = EG(ini_directives);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (p->name) {
|
||||
p->module_number = module_number;
|
||||
if (zend_hash_add(registered_zend_ini_directives, p->name, p->name_length, p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry)==FAILURE) {
|
||||
if (zend_hash_add(directives, p->name, p->name_length, p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry)==FAILURE) {
|
||||
zend_unregister_ini_entries(module_number TSRMLS_CC);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ END_EXTERN_C()
|
||||
/* INI parsing engine */
|
||||
typedef void (*zend_ini_parser_cb_t)(zval *arg1, zval *arg2, int callback_type, void *arg);
|
||||
BEGIN_EXTERN_C()
|
||||
int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg);
|
||||
ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_INI_PARSER_ENTRY 1
|
||||
|
||||
+53
-4
@@ -92,6 +92,24 @@ void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
result->type = IS_STRING;
|
||||
}
|
||||
|
||||
void zend_ini_init_string(zval *result)
|
||||
{
|
||||
result->value.str.val = malloc(1);
|
||||
result->value.str.val[0] = 0;
|
||||
result->value.str.len = 0;
|
||||
result->type = IS_STRING;
|
||||
}
|
||||
|
||||
void zend_ini_add_string(zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int length = op1->value.str.len + op2->value.str.len;
|
||||
|
||||
result->value.str.val = (char *) realloc(op1->value.str.val, length+1);
|
||||
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
|
||||
result->value.str.val[length] = 0;
|
||||
result->value.str.len = length;
|
||||
result->type = IS_STRING;
|
||||
}
|
||||
|
||||
void zend_ini_get_constant(zval *result, zval *name)
|
||||
{
|
||||
@@ -112,6 +130,24 @@ void zend_ini_get_constant(zval *result, zval *name)
|
||||
}
|
||||
}
|
||||
|
||||
void zend_ini_get_var(zval *result, zval *name)
|
||||
{
|
||||
zval curval;
|
||||
char *envvar;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
if (zend_get_configuration_directive(name->value.str.val, name->value.str.len+1, &curval) == SUCCESS) {
|
||||
result->value.str.val = zend_strndup(curval.value.str.val, curval.value.str.len);
|
||||
result->value.str.len = curval.value.str.len;
|
||||
} else if ((envvar = zend_getenv(name->value.str.val, name->value.str.len TSRMLS_CC)) != NULL ||
|
||||
(envvar = getenv(name->value.str.val)) != NULL) {
|
||||
result->value.str.val = strdup(envvar);
|
||||
result->value.str.len = strlen(envvar);
|
||||
} else {
|
||||
zend_ini_init_string(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ini_error(char *str)
|
||||
{
|
||||
@@ -139,7 +175,7 @@ static void ini_error(char *str)
|
||||
}
|
||||
|
||||
|
||||
int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg)
|
||||
ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg)
|
||||
{
|
||||
int retval;
|
||||
zend_ini_parser_param ini_parser_param;
|
||||
@@ -175,6 +211,7 @@ int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_
|
||||
%token SECTION
|
||||
%token CFG_TRUE
|
||||
%token CFG_FALSE
|
||||
%token TC_DOLLAR_CURLY
|
||||
%left '|' '&'
|
||||
%right '~' '!'
|
||||
|
||||
@@ -210,11 +247,23 @@ statement:
|
||||
|
||||
string_or_value:
|
||||
expr { $$ = $1; }
|
||||
| TC_ENCAPSULATED_STRING { $$ = $1; }
|
||||
| CFG_TRUE { $$ = $1; }
|
||||
| CFG_FALSE { $$ = $1; }
|
||||
| '\n' { $$.value.str.val = strdup(""); $$.value.str.len=0; $$.type = IS_STRING; }
|
||||
| /* empty */ { $$.value.str.val = strdup(""); $$.value.str.len=0; $$.type = IS_STRING; }
|
||||
| var_string_list { $$ = $1; }
|
||||
| '\n' { zend_ini_init_string(&$$); }
|
||||
| /* empty */ { zend_ini_init_string(&$$); }
|
||||
;
|
||||
|
||||
|
||||
var_string_list:
|
||||
var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free($2.value.str.val); }
|
||||
| var_string_list TC_ENCAPSULATED_STRING { zend_ini_add_string(&$$, &$1, &$2); }
|
||||
| var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); }
|
||||
| /* empty */ { zend_ini_init_string(&$$); }
|
||||
;
|
||||
|
||||
cfg_var_ref:
|
||||
TC_DOLLAR_CURLY TC_STRING '}' { zend_ini_get_var(&$$, &$2); }
|
||||
;
|
||||
|
||||
expr:
|
||||
|
||||
+10
-4
@@ -153,12 +153,20 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
return TC_ENCAPSULATED_STRING;
|
||||
}
|
||||
|
||||
<INITIAL>[&|~()!] {
|
||||
<INITIAL>[&|~$(){}!] {
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
<INITIAL>"${" {
|
||||
return TC_DOLLAR_CURLY;
|
||||
}
|
||||
|
||||
<INITIAL>[^=\n\r\t;|&~()!"\[]+ {
|
||||
<INITIAL>"}" {
|
||||
ini_lval->value.lval = (long) yytext[0];
|
||||
return yytext[0];
|
||||
}
|
||||
|
||||
<INITIAL>[^=\n\r\t;|&$~(){}!"\[]+ {
|
||||
/* STRING */
|
||||
register int i;
|
||||
|
||||
@@ -190,8 +198,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
<INITIAL>[=\n] {
|
||||
if (yytext[0] == '\n') {
|
||||
SCNG(lineno)++;
|
||||
|
||||
@@ -272,7 +272,7 @@ static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce,
|
||||
|
||||
zend_class_entry *ce_it = Z_TYPE_P(iterator) == IS_OBJECT ? Z_OBJCE_P(iterator) : NULL;
|
||||
|
||||
if (!ce || !ce_it || !ce_it->get_iterator) {
|
||||
if (!ce || !ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
|
||||
zend_error(E_WARNING, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name);
|
||||
zval_ptr_dtor(&iterator);
|
||||
return NULL;
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#include "zend_constants.h"
|
||||
#include "zend_variables.h"
|
||||
#include "zend_operators.h"
|
||||
#include "zend_API.h"
|
||||
|
||||
#ifdef HAVE_STDARG_H
|
||||
# include <stdarg.h>
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ extern struct _zend_arg_info third_arg_force_ref[4];
|
||||
extern struct _zend_arg_info fourth_arg_force_ref[5];
|
||||
extern struct _zend_arg_info all_args_by_ref[1];
|
||||
|
||||
#define ZEND_MODULE_API_NO 20040412
|
||||
#define ZEND_MODULE_API_NO 20040718
|
||||
#ifdef ZTS
|
||||
#define USING_ZTS 1
|
||||
#else
|
||||
|
||||
+14
-15
@@ -161,13 +161,7 @@ static int zend_verify_property_access(zend_property_info *property_info, zend_c
|
||||
case ZEND_ACC_PUBLIC:
|
||||
return 1;
|
||||
case ZEND_ACC_PROTECTED:
|
||||
while (ce) {
|
||||
if (ce==EG(scope)) {
|
||||
return 1;
|
||||
}
|
||||
ce = ce->parent;
|
||||
}
|
||||
return 0;
|
||||
return zend_check_protected(ce, EG(scope));
|
||||
case ZEND_ACC_PRIVATE:
|
||||
if (ce==EG(scope) && EG(scope)) {
|
||||
return 1;
|
||||
@@ -269,9 +263,11 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
|
||||
zval *rv = NULL;
|
||||
zend_property_info *property_info;
|
||||
int silent;
|
||||
zend_bool use_get;
|
||||
|
||||
silent = (type == BP_VAR_IS);
|
||||
zobj = Z_OBJ_P(object);
|
||||
use_get = (zobj->ce->__get && !zobj->in_get);
|
||||
|
||||
if (member->type != IS_STRING) {
|
||||
tmp_member = *member;
|
||||
@@ -284,10 +280,11 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
|
||||
fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member));
|
||||
#endif
|
||||
|
||||
property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC);
|
||||
/* make zend_get_property_info silent if we have getter - we may want to use it */
|
||||
property_info = zend_get_property_info(zobj, member, use_get TSRMLS_CC);
|
||||
|
||||
if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
|
||||
if (zobj->ce->__get && !zobj->in_get) {
|
||||
if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
|
||||
if (use_get) {
|
||||
/* have getter - try with it! */
|
||||
zobj->in_get = 1; /* prevent circular getting */
|
||||
rv = zend_std_call_getter(object, member TSRMLS_CC);
|
||||
@@ -319,8 +316,10 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
|
||||
zval **variable_ptr;
|
||||
int setter_done = 0;
|
||||
zend_property_info *property_info;
|
||||
|
||||
zend_bool use_set;
|
||||
|
||||
zobj = Z_OBJ_P(object);
|
||||
use_set = (zobj->ce->__set && !zobj->in_set);
|
||||
|
||||
if (member->type != IS_STRING) {
|
||||
tmp_member = *member;
|
||||
@@ -329,9 +328,9 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
|
||||
member = &tmp_member;
|
||||
}
|
||||
|
||||
property_info = zend_get_property_info(zobj, member, 0 TSRMLS_CC);
|
||||
property_info = zend_get_property_info(zobj, member, use_set TSRMLS_CC);
|
||||
|
||||
if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
|
||||
if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
|
||||
if (*variable_ptr == value) {
|
||||
/* if we already have this value there, we don't actually need to do anything */
|
||||
setter_done = 1;
|
||||
@@ -350,7 +349,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (zobj->ce->__set && !zobj->in_set) {
|
||||
if (use_set) {
|
||||
zobj->in_set = 1; /* prevent circular setting */
|
||||
if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) {
|
||||
/* for now, just ignore it - __set should take care of warnings, etc. */
|
||||
@@ -939,7 +938,7 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
|
||||
}
|
||||
} else {
|
||||
MAKE_STD_ZVAL(retval);
|
||||
ZVAL_STRINGL(retval, empty_string, 0, 0);
|
||||
ZVAL_STRINGL(retval, "", 0, 1);
|
||||
}
|
||||
*writeobj = *retval;
|
||||
zval_copy_ctor(writeobj);
|
||||
|
||||
+6
-3
@@ -76,10 +76,13 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
|
||||
old_exception = EG(exception);
|
||||
EG(exception) = NULL;
|
||||
zend_call_method_with_0_params(&obj, object->ce, NULL, "__destruct", NULL);
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(&EG(exception));
|
||||
if (old_exception) {
|
||||
if (EG(exception)) {
|
||||
zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active", object->ce->name);
|
||||
zval_ptr_dtor(&EG(exception));
|
||||
}
|
||||
EG(exception) = old_exception;
|
||||
}
|
||||
EG(exception) = old_exception;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,6 +207,15 @@ ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC
|
||||
}
|
||||
|
||||
|
||||
/* Called when the ctor was terminated by an exception */
|
||||
ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(zobject);
|
||||
|
||||
EG(objects_store).object_buckets[handle].destructor_called = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Proxy objects workings */
|
||||
typedef struct _zend_proxy_object {
|
||||
zval *object;
|
||||
|
||||
@@ -68,6 +68,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC);
|
||||
ZEND_API void *zend_object_store_get_object(zval *object TSRMLS_DC);
|
||||
/* See comment in zend_objects_API.c before you use this */
|
||||
ZEND_API void zend_object_store_set_object(zval *zobject, void *object TSRMLS_DC);
|
||||
ZEND_API void zend_object_store_ctor_failed(zval *zobject TSRMLS_DC);
|
||||
|
||||
ZEND_API void zend_objects_store_free_object_storage(zend_objects_store *objects TSRMLS_DC);
|
||||
|
||||
|
||||
@@ -223,6 +223,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
|
||||
opline++;
|
||||
}
|
||||
efree(op_array->opcodes);
|
||||
|
||||
if (op_array->function_name) {
|
||||
efree(op_array->function_name);
|
||||
}
|
||||
|
||||
+6
-13
@@ -510,7 +510,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
||||
|
||||
switch (op->type) {
|
||||
case IS_NULL:
|
||||
op->value.str.val = empty_string;
|
||||
op->value.str.val = STR_EMPTY_ALLOC();
|
||||
op->value.str.len = 0;
|
||||
break;
|
||||
case IS_STRING:
|
||||
@@ -520,7 +520,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
||||
op->value.str.val = estrndup_rel("1", 1);
|
||||
op->value.str.len = 1;
|
||||
} else {
|
||||
op->value.str.val = empty_string;
|
||||
op->value.str.val = STR_EMPTY_ALLOC();
|
||||
op->value.str.len = 0;
|
||||
}
|
||||
break;
|
||||
@@ -1130,11 +1130,8 @@ ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
|
||||
ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2)
|
||||
{
|
||||
int length = op1->value.str.len + op2->value.str.len;
|
||||
if (op1->value.str.val == empty_string) {
|
||||
result->value.str.val = (char *) emalloc(length+1);
|
||||
} else {
|
||||
result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
|
||||
}
|
||||
|
||||
result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
|
||||
memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
|
||||
result->value.str.val[length] = 0;
|
||||
result->value.str.len = length;
|
||||
@@ -1167,12 +1164,8 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
|
||||
if (result==op1) { /* special case, perform operations on result */
|
||||
uint res_len = op1->value.str.len + op2->value.str.len;
|
||||
|
||||
if (result->value.str.len == 0) { /* handle empty_string */
|
||||
STR_FREE(result->value.str.val);
|
||||
result->value.str.val = emalloc(res_len+1);
|
||||
} else {
|
||||
result->value.str.val = erealloc(result->value.str.val, res_len+1);
|
||||
}
|
||||
result->value.str.val = erealloc(result->value.str.val, res_len+1);
|
||||
|
||||
memcpy(result->value.str.val+result->value.str.len, op2->value.str.val, op2->value.str.len);
|
||||
result->value.str.val[res_len]=0;
|
||||
result->value.str.len = res_len;
|
||||
|
||||
@@ -87,6 +87,8 @@ static inline zend_bool is_numeric_string(char *str, int length, long *lval, dou
|
||||
*lval = local_lval;
|
||||
}
|
||||
return IS_LONG;
|
||||
} else if (end_ptr_long == str && *end_ptr_long != '\0') { /* ignore partial string matches */
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
end_ptr_long=NULL;
|
||||
|
||||
@@ -38,12 +38,8 @@ ZEND_API void zend_ptr_stack_n_push(zend_ptr_stack *stack, int count, ...)
|
||||
va_list ptr;
|
||||
void *elem;
|
||||
|
||||
if (stack->top+count > stack->max) { /* we need to allocate more memory */
|
||||
stack->max *= 2;
|
||||
stack->max += count;
|
||||
stack->elements = (void **) erealloc(stack->elements, (sizeof(void *) * (stack->max)));
|
||||
stack->top_element = stack->elements+stack->top;
|
||||
}
|
||||
ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, count)
|
||||
|
||||
va_start(ptr, count);
|
||||
while (count>0) {
|
||||
elem = va_arg(ptr, void *);
|
||||
|
||||
+48
-4
@@ -41,12 +41,56 @@ ZEND_API void zend_ptr_stack_clean(zend_ptr_stack *stack, void (*func)(void *),
|
||||
ZEND_API int zend_ptr_stack_num_elements(zend_ptr_stack *stack);
|
||||
END_EXTERN_C()
|
||||
|
||||
#define ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, count) \
|
||||
if (stack->top+count > stack->max) { \
|
||||
/* we need to allocate more memory */ \
|
||||
stack->max *= 2; \
|
||||
stack->max += count; \
|
||||
stack->elements = (void **) erealloc(stack->elements, (sizeof(void *) * (stack->max))); \
|
||||
stack->top_element = stack->elements+stack->top; \
|
||||
}
|
||||
|
||||
/* Not doing this with a macro because of the loop unrolling in the element assignment.
|
||||
Just using a macro for 3 in the body for readability sake. */
|
||||
static inline void zend_ptr_stack_3_push(zend_ptr_stack *stack, void *a, void *b, void *c)
|
||||
{
|
||||
#define ZEND_PTR_STACK_NUM_ARGS 3
|
||||
|
||||
ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, ZEND_PTR_STACK_NUM_ARGS)
|
||||
|
||||
stack->top += ZEND_PTR_STACK_NUM_ARGS;
|
||||
*(stack->top_element++) = a;
|
||||
*(stack->top_element++) = b;
|
||||
*(stack->top_element++) = c;
|
||||
|
||||
#undef ZEND_PTR_STACK_NUM_ARGS
|
||||
}
|
||||
|
||||
static inline void zend_ptr_stack_2_push(zend_ptr_stack *stack, void *a, void *b)
|
||||
{
|
||||
#define ZEND_PTR_STACK_NUM_ARGS 2
|
||||
|
||||
ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, ZEND_PTR_STACK_NUM_ARGS)
|
||||
|
||||
stack->top += ZEND_PTR_STACK_NUM_ARGS;
|
||||
*(stack->top_element++) = a;
|
||||
*(stack->top_element++) = b;
|
||||
|
||||
#undef ZEND_PTR_STACK_NUM_ARGS
|
||||
}
|
||||
|
||||
static inline void zend_ptr_stack_3_pop(zend_ptr_stack *stack, void **a, void **b, void **c)
|
||||
{
|
||||
*a = *(--stack->top_element);
|
||||
*b = *(--stack->top_element);
|
||||
*c = *(--stack->top_element);
|
||||
stack->top -= 3;;
|
||||
}
|
||||
|
||||
static inline void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr)
|
||||
{
|
||||
if (stack->top >= stack->max) { /* we need to allocate more memory */
|
||||
stack->elements = (void **) erealloc(stack->elements, (sizeof(void *) * (stack->max *= 2 )));
|
||||
stack->top_element = stack->elements+stack->top;
|
||||
}
|
||||
ZEND_PTR_STACK_RESIZE_IF_NEEDED(stack, 1)
|
||||
|
||||
stack->top++;
|
||||
*(stack->top_element++) = ptr;
|
||||
}
|
||||
|
||||
+175
-21
@@ -146,7 +146,9 @@ typedef struct _property_reference {
|
||||
/* Struct for parameters */
|
||||
typedef struct _parameter_reference {
|
||||
int offset;
|
||||
int required;
|
||||
struct _zend_arg_info *arg_info;
|
||||
zend_function *fptr;
|
||||
} parameter_reference;
|
||||
|
||||
/* Struct for reflection objects */
|
||||
@@ -501,9 +503,14 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _parameter_string */
|
||||
static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int offset, char* indent TSRMLS_DC)
|
||||
static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, int offset, int required, char* indent TSRMLS_DC)
|
||||
{
|
||||
string_printf(str, "Parameter #%d [ ", offset);
|
||||
if (offset >= required) {
|
||||
string_printf(str, "<optional> ");
|
||||
} else {
|
||||
string_printf(str, "<required> ");
|
||||
}
|
||||
if (arg_info->class_name) {
|
||||
string_printf(str, "%s ", arg_info->class_name);
|
||||
if (arg_info->allow_null) {
|
||||
@@ -518,6 +525,32 @@ static void _parameter_string(string *str, struct _zend_arg_info *arg_info, int
|
||||
} else {
|
||||
string_printf(str, "$param%d", offset);
|
||||
}
|
||||
if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
|
||||
zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1];
|
||||
if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
|
||||
zval *zv, zv_copy;
|
||||
int use_copy;
|
||||
string_write(str, " = ", sizeof(" = ")-1);
|
||||
zv_copy = precv->op2.u.constant;
|
||||
zv = &zv_copy;
|
||||
zval_update_constant(&zv, (void*)1 TSRMLS_CC);
|
||||
if (Z_TYPE_P(zv) == IS_NULL) {
|
||||
string_write(str, "NULL", sizeof("NULL")-1);
|
||||
} else if (Z_TYPE_P(zv) == IS_STRING) {
|
||||
string_write(str, "'", sizeof("'")-1);
|
||||
string_write(str, Z_STRVAL_P(zv), MIN(Z_STRLEN_P(zv), 15));
|
||||
if (Z_STRLEN_P(zv) > 15) {
|
||||
string_write(str, "...", sizeof("...")-1);
|
||||
}
|
||||
string_write(str, "'", sizeof("'")-1);
|
||||
} else {
|
||||
zend_make_printable_zval(zv, &zv_copy, &use_copy);
|
||||
string_write(str, Z_STRVAL(zv_copy), Z_STRLEN(zv_copy));
|
||||
zval_dtor(&zv_copy);
|
||||
}
|
||||
zval_ptr_dtor(&zv);
|
||||
}
|
||||
}
|
||||
string_write(str, " ]", sizeof(" ]")-1);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -527,6 +560,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
|
||||
{
|
||||
zend_uint i;
|
||||
struct _zend_arg_info *arg_info = fptr->common.arg_info;
|
||||
int required = fptr->common.required_num_args;
|
||||
|
||||
if (!arg_info) {
|
||||
return;
|
||||
@@ -536,7 +570,7 @@ static void _function_parameter_string(string *str, zend_function *fptr, char* i
|
||||
string_printf(str, "%s- Parameters [%d] {\n", indent, fptr->common.num_args);
|
||||
for (i = 0; i < fptr->common.num_args; i++) {
|
||||
string_printf(str, "%s ", indent);
|
||||
_parameter_string(str, arg_info, i, indent TSRMLS_CC);
|
||||
_parameter_string(str, fptr, arg_info, i, required, indent TSRMLS_CC);
|
||||
string_write(str, "\n", sizeof("\n")-1);
|
||||
arg_info++;
|
||||
}
|
||||
@@ -586,6 +620,9 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
|
||||
case ZEND_ACC_PROTECTED:
|
||||
string_printf(str, "protected ");
|
||||
break;
|
||||
default:
|
||||
string_printf(str, "<visibilty error> ");
|
||||
break;
|
||||
}
|
||||
|
||||
string_printf(str, fptr->common.scope ? "method " : "function ");
|
||||
@@ -823,7 +860,7 @@ static void reflection_extension_factory(zval *object, char *name_str TSRMLS_DC)
|
||||
/* }}} */
|
||||
|
||||
/* {{{ reflection_parameter_factory */
|
||||
static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int offset, zval *object TSRMLS_DC)
|
||||
static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_info *arg_info, int offset, int required, zval *object TSRMLS_DC)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *reference;
|
||||
@@ -840,6 +877,8 @@ static void reflection_parameter_factory(struct _zend_arg_info *arg_info, int of
|
||||
reference = (parameter_reference*) emalloc(sizeof(parameter_reference));
|
||||
reference->arg_info = arg_info;
|
||||
reference->offset = offset;
|
||||
reference->required = required;
|
||||
reference->fptr = fptr;
|
||||
intern->ptr = reference;
|
||||
intern->free_ptr = 1;
|
||||
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
|
||||
@@ -1356,6 +1395,34 @@ ZEND_METHOD(reflection_function, returnsReference)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionFunction::getNumberOfParameters()
|
||||
Gets the number of required parameters */
|
||||
ZEND_METHOD(reflection_function, getNumberOfParameters)
|
||||
{
|
||||
reflection_object *intern;
|
||||
zend_function *fptr;
|
||||
|
||||
METHOD_NOTSTATIC;
|
||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
||||
|
||||
RETURN_LONG(fptr->common.num_args);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionFunction::getNumberOfRequiredParameters()
|
||||
Gets the number of required parameters */
|
||||
ZEND_METHOD(reflection_function, getNumberOfRequiredParameters)
|
||||
{
|
||||
reflection_object *intern;
|
||||
zend_function *fptr;
|
||||
|
||||
METHOD_NOTSTATIC;
|
||||
GET_REFLECTION_OBJECT_PTR(fptr);
|
||||
|
||||
RETURN_LONG(fptr->common.required_num_args);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionParameter[] Reflection_Function::getParameters()
|
||||
Returns an array of parameter objects for this function */
|
||||
ZEND_METHOD(reflection_function, getParameters)
|
||||
@@ -1375,7 +1442,7 @@ ZEND_METHOD(reflection_function, getParameters)
|
||||
zval *parameter;
|
||||
|
||||
ALLOC_ZVAL(parameter);
|
||||
reflection_parameter_factory(arg_info, i, parameter TSRMLS_CC);
|
||||
reflection_parameter_factory(fptr, arg_info, i, fptr->common.required_num_args, parameter TSRMLS_CC);
|
||||
add_next_index_zval(return_value, parameter);
|
||||
|
||||
arg_info++;
|
||||
@@ -1511,6 +1578,8 @@ ZEND_METHOD(reflection_parameter, __construct)
|
||||
ref = (parameter_reference*) emalloc(sizeof(parameter_reference));
|
||||
ref->arg_info = &arg_info[position];
|
||||
ref->offset = position;
|
||||
ref->required = fptr->common.required_num_args;
|
||||
ref->fptr = fptr;
|
||||
intern->ptr = ref;
|
||||
intern->free_ptr = 1;
|
||||
}
|
||||
@@ -1527,7 +1596,7 @@ ZEND_METHOD(reflection_parameter, __toString)
|
||||
METHOD_NOTSTATIC_NUMPARAMS(0);
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
string_init(&str);
|
||||
_parameter_string(&str, param->arg_info, param->offset, "" TSRMLS_CC);
|
||||
_parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "" TSRMLS_CC);
|
||||
RETURN_STRINGL(str.string, str.len - 1, 0);
|
||||
}
|
||||
/* }}} */
|
||||
@@ -1541,7 +1610,7 @@ ZEND_METHOD(reflection_parameter, getName)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionClass Reflection_Parameter::getClass()
|
||||
/* {{{ proto public ReflectionClass ReflectionParameter::getClass()
|
||||
Returns this parameters's class hint or NULL if there is none */
|
||||
ZEND_METHOD(reflection_parameter, getClass)
|
||||
{
|
||||
@@ -1597,6 +1666,80 @@ ZEND_METHOD(reflection_parameter, isPassedByReference)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isOptional()
|
||||
Returns whether this parameter is an optional parameter */
|
||||
ZEND_METHOD(reflection_parameter, isOptional)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
|
||||
METHOD_NOTSTATIC_NUMPARAMS(0);
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
RETVAL_BOOL(param->offset >= param->required);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::isDefaultValueAvailable()
|
||||
Returns whether the default value of this parameter is available */
|
||||
ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
zend_op *precv;
|
||||
|
||||
METHOD_NOTSTATIC_NUMPARAMS(0);
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
if (param->fptr->type != ZEND_USER_FUNCTION)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (param->offset < param->required) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
|
||||
if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public bool ReflectionParameter::getDefaultValue()
|
||||
Returns the default value of this parameter or throws an exception */
|
||||
ZEND_METHOD(reflection_parameter, getDefaultValue)
|
||||
{
|
||||
reflection_object *intern;
|
||||
parameter_reference *param;
|
||||
zend_op *precv;
|
||||
zval *zv, zv_copy;
|
||||
|
||||
METHOD_NOTSTATIC_NUMPARAMS(0);
|
||||
GET_REFLECTION_OBJECT_PTR(param);
|
||||
|
||||
if (param->fptr->type != ZEND_USER_FUNCTION)
|
||||
{
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Cannot determine default value for internal functions");
|
||||
return;
|
||||
}
|
||||
if (param->offset < param->required) {
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional");
|
||||
return;
|
||||
}
|
||||
precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
|
||||
if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error");
|
||||
return;
|
||||
}
|
||||
|
||||
zv_copy = precv->op2.u.constant;
|
||||
zv = &zv_copy;
|
||||
zval_update_constant(&zv, (void*)1 TSRMLS_CC);
|
||||
RETURN_ZVAL(zv, 1, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name, [, bool return]) throws ReflectionException
|
||||
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
|
||||
ZEND_METHOD(reflection_method, export)
|
||||
@@ -1879,7 +2022,7 @@ ZEND_METHOD(reflection_method, getModifiers)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionClass Reflection_Method::getDeclaringClass()
|
||||
/* {{{ proto public ReflectionClass ReflectionMethod::getDeclaringClass()
|
||||
Get the declaring class */
|
||||
ZEND_METHOD(reflection_method, getDeclaringClass)
|
||||
{
|
||||
@@ -2134,7 +2277,7 @@ ZEND_METHOD(reflection_class, getDocComment)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionMethod Reflection_Class::getConstructor()
|
||||
/* {{{ proto public ReflectionMethod ReflectionClass::getConstructor()
|
||||
Returns the class' constructor if there is one, NULL otherwise */
|
||||
ZEND_METHOD(reflection_class, getConstructor)
|
||||
{
|
||||
@@ -2152,7 +2295,7 @@ ZEND_METHOD(reflection_class, getConstructor)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionMethod Reflection_Class::getMethod(string name)
|
||||
/* {{{ proto public ReflectionMethod ReflectionClass::getMethod(string name) throws ReflectionException
|
||||
Returns the class' method specified by it's name */
|
||||
ZEND_METHOD(reflection_class, getMethod)
|
||||
{
|
||||
@@ -2172,7 +2315,9 @@ ZEND_METHOD(reflection_class, getMethod)
|
||||
if (zend_hash_find(&ce->function_table, name, name_len + 1, (void**) &mptr) == SUCCESS) {
|
||||
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
|
||||
} else {
|
||||
RETURN_NULL();
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||
"Method %s does not exist", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2195,7 +2340,7 @@ static int _addmethod(zend_function *mptr, int num_args, va_list args, zend_hash
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionMethod[] Reflection_Class::getMethods()
|
||||
/* {{{ proto public ReflectionMethod[] ReflectionClass::getMethods()
|
||||
Returns an array of this class' methods */
|
||||
ZEND_METHOD(reflection_class, getMethods)
|
||||
{
|
||||
@@ -2221,7 +2366,7 @@ ZEND_METHOD(reflection_class, getMethods)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionProperty Reflection_Class::getProperty(string name)
|
||||
/* {{{ proto public ReflectionProperty ReflectionClass::getProperty(string name) throws ReflectionException
|
||||
Returns the class' property specified by it's name */
|
||||
ZEND_METHOD(reflection_class, getProperty)
|
||||
{
|
||||
@@ -2240,7 +2385,9 @@ ZEND_METHOD(reflection_class, getProperty)
|
||||
if (zend_hash_find(&ce->properties_info, name, name_len + 1, (void**) &property_info) == SUCCESS) {
|
||||
reflection_property_factory(ce, property_info, return_value TSRMLS_CC);
|
||||
} else {
|
||||
RETURN_NULL();
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||
"Property %s does not exist", name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2263,7 +2410,7 @@ static int _addproperty(zend_property_info *pptr, int num_args, va_list args, ze
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionProperty[] Reflection_Class::getProperties()
|
||||
/* {{{ proto public ReflectionProperty[] ReflectionClass::getProperties()
|
||||
Returns an array of this class' properties */
|
||||
ZEND_METHOD(reflection_class, getProperties)
|
||||
{
|
||||
@@ -2300,6 +2447,7 @@ ZEND_METHOD(reflection_class, getConstants)
|
||||
METHOD_NOTSTATIC_NUMPARAMS(0);
|
||||
GET_REFLECTION_OBJECT_PTR(ce);
|
||||
array_init(return_value);
|
||||
zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
|
||||
zend_hash_copy(Z_ARRVAL_P(return_value), &ce->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *));
|
||||
}
|
||||
/* }}} */
|
||||
@@ -2320,6 +2468,7 @@ ZEND_METHOD(reflection_class, getConstant)
|
||||
}
|
||||
|
||||
GET_REFLECTION_OBJECT_PTR(ce);
|
||||
zend_hash_apply_with_argument(&ce->constants_table, (apply_func_arg_t) zval_update_constant, (void*)1 TSRMLS_CC);
|
||||
if (zend_hash_find(&ce->constants_table, name, name_len + 1, (void **) &value) == FAILURE) {
|
||||
RETURN_FALSE;
|
||||
}
|
||||
@@ -2383,7 +2532,7 @@ ZEND_METHOD(reflection_class, isFinal)
|
||||
Returns whether this class is abstract */
|
||||
ZEND_METHOD(reflection_class, isAbstract)
|
||||
{
|
||||
_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS);
|
||||
_class_check_flag(INTERNAL_FUNCTION_PARAM_PASSTHRU, ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@@ -2478,7 +2627,7 @@ ZEND_METHOD(reflection_class, newInstance)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionClass[] Reflection_Class::getInterfaces()
|
||||
/* {{{ proto public ReflectionClass[] ReflectionClass::getInterfaces()
|
||||
Returns an array of interfaces this class implements */
|
||||
ZEND_METHOD(reflection_class, getInterfaces)
|
||||
{
|
||||
@@ -2504,7 +2653,7 @@ ZEND_METHOD(reflection_class, getInterfaces)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionClass Reflection_Class::getParentClass()
|
||||
/* {{{ proto public ReflectionClass ReflectionClass::getParentClass()
|
||||
Returns the class' parent class, or, if none exists, FALSE */
|
||||
ZEND_METHOD(reflection_class, getParentClass)
|
||||
{
|
||||
@@ -2541,7 +2690,7 @@ ZEND_METHOD(reflection_class, isSubclassOf)
|
||||
case IS_STRING:
|
||||
if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||
"Interface %s doesn't exist", Z_STRVAL_P(class_name));
|
||||
"Interface %s does not exist", Z_STRVAL_P(class_name));
|
||||
return;
|
||||
}
|
||||
class_ce = *pce;
|
||||
@@ -2587,7 +2736,7 @@ ZEND_METHOD(reflection_class, implementsInterface)
|
||||
case IS_STRING:
|
||||
if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
|
||||
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
|
||||
"Interface %s doesn't exist", Z_STRVAL_P(interface));
|
||||
"Interface %s does not exist", Z_STRVAL_P(interface));
|
||||
return;
|
||||
}
|
||||
interface_ce = *pce;
|
||||
@@ -2953,7 +3102,7 @@ ZEND_METHOD(reflection_property, setValue)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionClass Reflection_Property::getDeclaringClass()
|
||||
/* {{{ proto public ReflectionClass ReflectionProperty::getDeclaringClass()
|
||||
Get the declaring class */
|
||||
ZEND_METHOD(reflection_property, getDeclaringClass)
|
||||
{
|
||||
@@ -3056,7 +3205,7 @@ ZEND_METHOD(reflection_extension, getVersion)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto public ReflectionFunction[] Reflection_Extension::getFunctions()
|
||||
/* {{{ proto public ReflectionFunction[] ReflectionExtension::getFunctions()
|
||||
Returns an array of this extension's fuctions */
|
||||
ZEND_METHOD(reflection_extension, getFunctions)
|
||||
{
|
||||
@@ -3235,6 +3384,8 @@ static zend_function_entry reflection_function_functions[] = {
|
||||
ZEND_ME(reflection_function, invoke, NULL, 0)
|
||||
ZEND_ME(reflection_function, returnsReference, NULL, 0)
|
||||
ZEND_ME(reflection_function, getParameters, NULL, 0)
|
||||
ZEND_ME(reflection_function, getNumberOfParameters, NULL, 0)
|
||||
ZEND_ME(reflection_function, getNumberOfRequiredParameters, NULL, 0)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -3327,6 +3478,9 @@ static zend_function_entry reflection_parameter_functions[] = {
|
||||
ZEND_ME(reflection_parameter, isPassedByReference, NULL, 0)
|
||||
ZEND_ME(reflection_parameter, getClass, NULL, 0)
|
||||
ZEND_ME(reflection_parameter, allowsNull, NULL, 0)
|
||||
ZEND_ME(reflection_parameter, isOptional, NULL, 0)
|
||||
ZEND_ME(reflection_parameter, isDefaultValueAvailable, NULL, 0)
|
||||
ZEND_ME(reflection_parameter, getDefaultValue, NULL, 0)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
+1
-15
@@ -26,12 +26,6 @@
|
||||
#include "zend_constants.h"
|
||||
#include "zend_list.h"
|
||||
|
||||
ZEND_API char *empty_string = ""; /* in order to save emalloc() and efree() time for
|
||||
* empty strings (usually used to denote empty
|
||||
* return values in failed functions).
|
||||
* The macro STR_FREE() will not efree() it.
|
||||
*/
|
||||
|
||||
|
||||
ZEND_API void _zval_dtor(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
{
|
||||
@@ -86,9 +80,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
case IS_STRING:
|
||||
case IS_CONSTANT:
|
||||
CHECK_ZVAL_STRING_REL(zvalue);
|
||||
if (zvalue->value.str.val != empty_string) {
|
||||
free(zvalue->value.str.val);
|
||||
}
|
||||
free(zvalue->value.str.val);
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
case IS_CONSTANT_ARRAY:
|
||||
@@ -127,12 +119,6 @@ ZEND_API int _zval_copy_ctor(zval *zvalue ZEND_FILE_LINE_DC)
|
||||
break;
|
||||
case IS_CONSTANT:
|
||||
case IS_STRING:
|
||||
if (zvalue->value.str.val) {
|
||||
if (zvalue->value.str.len==0) {
|
||||
zvalue->value.str.val = empty_string;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
CHECK_ZVAL_STRING_REL(zvalue);
|
||||
zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
|
||||
break;
|
||||
|
||||
Loaded 100 of 3605 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user