2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
15 #define HTTP_WANT_CURL
18 #include "php_http_api.h"
19 #include "php_http_request_api.h"
20 #include "php_http_request_method_api.h"
22 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
23 # include "php_http_request_object.h"
26 /* {{{ char *http_request_methods[] */
27 static const char *const http_request_methods
[] = {
38 /* WebDAV - RFC 2518 */
46 /* WebDAV Versioning - RFC 3253 */
58 /* WebDAV Access Control - RFC 3744 */
65 PHP_MINIT_FUNCTION(http_request_method
)
68 HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET
);
69 HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD
);
70 HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST
);
71 HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT
);
72 HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE
);
73 HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS
);
74 HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE
);
75 HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT
);
76 /* WebDAV - RFC 2518 */
77 HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND
);
78 HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH
);
79 HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL
);
80 HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY
);
81 HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE
);
82 HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK
);
83 HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK
);
84 /* WebDAV Versioning - RFC 3253 */
85 HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL
);
86 HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT
);
87 HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT
);
88 HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN
);
89 HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT
);
90 HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE
);
91 HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE
);
92 HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL
);
93 HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE
);
94 HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL
);
95 HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY
);
96 /* WebDAV Access Control - RFC 3744 */
97 HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL
);
102 static void free_method(void *el
)
107 static void unregister_method(const char *name TSRMLS_DC
)
109 char *ptr
, tmp
[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN
] = "HTTP_METH_";
111 strlcpy(tmp
+ lenof("HTTP_METH_"), name
, HTTP_REQUEST_METHOD_MAXLEN
);
112 for (ptr
= tmp
+ lenof("HTTP_METH_"); *ptr
; ++ptr
) {
118 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
119 if (SUCCESS
!= zend_hash_del(&http_request_object_ce
->constants_table
, tmp
+ lenof("HTTP_"), strlen(tmp
+ lenof("HTTP_")) + 1)) {
120 http_error_ex(HE_NOTICE
, HTTP_E_REQUEST_METHOD
, "Could not unregister request method: HttpRequest::%s", tmp
+ lenof("HTTP_"));
123 if (SUCCESS
!= zend_hash_del(EG(zend_constants
), tmp
, strlen(tmp
) + 1)) {
124 http_error_ex(HE_NOTICE
, HTTP_E_REQUEST_METHOD
, "Could not unregister request method: %s", tmp
);
128 PHP_RINIT_FUNCTION(http_request_method
)
132 zend_hash_init(&HTTP_G
->request
.methods
.registered
, 0, NULL
, free_method
, 0);
133 #define HTTP_METH_REG(m) \
135 char *_m=estrdup(m); \
136 zend_hash_next_index_insert(&HTTP_G->request.methods.registered, (void *) &_m, sizeof(char *), NULL); \
138 HTTP_METH_REG("UNKNOWN");
140 HTTP_METH_REG("GET");
141 HTTP_METH_REG("HEAD");
142 HTTP_METH_REG("POST");
143 HTTP_METH_REG("PUT");
144 HTTP_METH_REG("DELETE");
145 HTTP_METH_REG("OPTIONS");
146 HTTP_METH_REG("TRACE");
147 HTTP_METH_REG("CONNECT");
148 /* WebDAV - RFC 2518 */
149 HTTP_METH_REG("PROPFIND");
150 HTTP_METH_REG("PROPPATCH");
151 HTTP_METH_REG("MKCOL");
152 HTTP_METH_REG("COPY");
153 HTTP_METH_REG("MOVE");
154 HTTP_METH_REG("LOCK");
155 HTTP_METH_REG("UNLOCK");
156 /* WebDAV Versioning - RFC 3253 */
157 HTTP_METH_REG("VERSION-CONTROL");
158 HTTP_METH_REG("REPORT");
159 HTTP_METH_REG("CHECKOUT");
160 HTTP_METH_REG("CHECKIN");
161 HTTP_METH_REG("UNCHECKOUT");
162 HTTP_METH_REG("MKWORKSPACE");
163 HTTP_METH_REG("UPDATE");
164 HTTP_METH_REG("LABEL");
165 HTTP_METH_REG("MERGE");
166 HTTP_METH_REG("BASELINE-CONTROL");
167 HTTP_METH_REG("MKACTIVITY");
168 /* WebDAV Access Control - RFC 3744 */
169 HTTP_METH_REG("ACL");
171 zend_hash_init(&ht
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
172 if (*HTTP_G
->request
.methods
.custom
&& SUCCESS
== http_parse_params(HTTP_G
->request
.methods
.custom
, HTTP_PARAMS_DEFAULT
, &ht
)) {
176 FOREACH_HASH_VAL(pos
, &ht
, val
) {
177 if (Z_TYPE_PP(val
) == IS_STRING
) {
178 http_request_method_register(Z_STRVAL_PP(val
), Z_STRLEN_PP(val
));
182 zend_hash_destroy(&ht
);
187 PHP_RSHUTDOWN_FUNCTION(http_request_method
)
190 int i
, c
= zend_hash_next_free_element(&HTTP_G
->request
.methods
.registered
);
192 for (i
= HTTP_MAX_REQUEST_METHOD
; i
< c
; ++i
) {
193 if (SUCCESS
== zend_hash_index_find(&HTTP_G
->request
.methods
.registered
, i
, (void *) &name
)) {
194 unregister_method(*name TSRMLS_CC
);
198 zend_hash_destroy(&HTTP_G
->request
.methods
.registered
);
202 #define http_request_method_cncl(m, c) _http_request_method_cncl_ex((m), strlen(m), (c) TSRMLS_CC)
203 #define http_request_method_cncl_ex(m, l, c) _http_request_method_cncl_ex((m), (l), (c) TSRMLS_CC)
204 static STATUS
_http_request_method_cncl_ex(const char *method_name
, int method_name_len
, char **cnst TSRMLS_DC
)
209 if (method_name_len
>= HTTP_REQUEST_METHOD_MAXLEN
) {
210 http_error_ex(HE_WARNING
, HTTP_E_REQUEST_METHOD
, "Request method too long (%s)", method_name
);
212 cncl
= emalloc(method_name_len
+ 1);
214 for (i
= 0; i
< method_name_len
; ++i
) {
215 switch (method_name
[i
]) {
218 cncl
[i
] = method_name
[i
];
222 if (!HTTP_IS_CTYPE(alnum
, method_name
[i
])) {
224 http_error_ex(HE_WARNING
, HTTP_E_REQUEST_METHOD
, "Request method contains illegal characters (%s)", method_name
);
227 cncl
[i
] = HTTP_TO_CTYPE(upper
, method_name
[i
]);
231 cncl
[method_name_len
] = '\0';
237 PHP_HTTP_API
const char *_http_request_method_name(http_request_method m TSRMLS_DC
)
241 if (SUCCESS
== zend_hash_index_find(&HTTP_G
->request
.methods
.registered
, m
, (void *) &name
)) {
247 PHP_HTTP_API
int _http_request_method_exists(int by_name
, http_request_method id_num
, const char *id_str TSRMLS_DC
)
251 if (by_name
&& (SUCCESS
== http_request_method_cncl(id_str
, &id_dup
))) {
254 HashKey key
= initHashKey(0);
256 FOREACH_HASH_KEYVAL(pos
, &HTTP_G
->request
.methods
.registered
, key
, name
) {
257 if (key
.type
== HASH_KEY_IS_LONG
&& !strcmp(*name
, id_dup
)) {
263 } else if (zend_hash_index_exists(&HTTP_G
->request
.methods
.registered
, id_num
)){
269 PHP_HTTP_API
int _http_request_method_register(const char *method_str
, int method_len TSRMLS_DC
)
271 char *method_dup
, *ptr
, tmp
[sizeof("HTTP_METH_") + HTTP_REQUEST_METHOD_MAXLEN
] = "HTTP_METH_";
272 int method_num
= http_request_method_exists(1, 0, method_str
);
274 if (!method_num
&& (SUCCESS
== http_request_method_cncl_ex(method_str
, method_len
, &method_dup
))) {
275 method_num
= zend_hash_next_free_element(&HTTP_G
->request
.methods
.registered
);
276 zend_hash_index_update(&HTTP_G
->request
.methods
.registered
, method_num
, (void *) &method_dup
, sizeof(char *), NULL
);
278 strlcpy(tmp
+ lenof("HTTP_METH_"), method_dup
, HTTP_REQUEST_METHOD_MAXLEN
);
279 for (ptr
= tmp
+ lenof("HTTP_METH_"); *ptr
; ++ptr
) {
285 zend_register_long_constant(tmp
, strlen(tmp
) + 1, method_num
, CONST_CS
, http_module_number TSRMLS_CC
);
286 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
287 zend_declare_class_constant_long(http_request_object_ce
, tmp
+ lenof("HTTP_"), strlen(tmp
+ lenof("HTTP_")), method_num TSRMLS_CC
);
294 PHP_HTTP_API STATUS
_http_request_method_unregister(int method TSRMLS_DC
)
298 if (HTTP_STD_REQUEST_METHOD(method
)) {
299 http_error_ex(HE_WARNING
, HTTP_E_REQUEST_METHOD
, "Standard request methods cannot be unregistered");
303 if (SUCCESS
!= zend_hash_index_find(&HTTP_G
->request
.methods
.registered
, method
, (void *) &name
)) {
304 http_error_ex(HE_NOTICE
, HTTP_E_REQUEST_METHOD
, "Custom request method with id %d does not exist", method
);
308 unregister_method(*name TSRMLS_CC
);
310 zend_hash_index_del(&HTTP_G
->request
.methods
.registered
, method
);
319 * vim600: noet sw=4 ts=4 fdm=marker
320 * vim<600: noet sw=4 ts=4