3480c3be0dad4d453b3975b5f64402c9d846e8c3
[m6w6/ext-http] / http_request_method_api.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
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-2005, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id$ */
14
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
18
19 #define HTTP_WANT_CURL
20 #include "php_http.h"
21
22 #include "php_http_api.h"
23 #include "php_http_request_api.h"
24 #include "php_http_request_method_api.h"
25
26 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
27 # include "php_http_request_object.h"
28 #endif
29
30 /* {{{ char *http_request_methods[] */
31 static const char *const http_request_methods[] = {
32 "UNKNOWN",
33 /* HTTP/1.1 */
34 "GET",
35 "HEAD",
36 "POST",
37 "PUT",
38 "DELETE",
39 "OPTIONS",
40 "TRACE",
41 "CONNECT",
42 /* WebDAV - RFC 2518 */
43 "PROPFIND",
44 "PROPPATCH",
45 "MKCOL",
46 "COPY",
47 "MOVE",
48 "LOCK",
49 "UNLOCK",
50 /* WebDAV Versioning - RFC 3253 */
51 "VERSION-CONTROL",
52 "REPORT",
53 "CHECKOUT",
54 "CHECKIN",
55 "UNCHECKOUT",
56 "MKWORKSPACE",
57 "UPDATE",
58 "LABEL",
59 "MERGE",
60 "BASELINE-CONTROL",
61 "MKACTIVITY",
62 /* WebDAV Access Control - RFC 3744 */
63 "ACL",
64 NULL
65 };
66 /* }}} */
67
68 PHP_MINIT_FUNCTION(http_request_method)
69 {
70 /* HTTP/1.1 */
71 HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET);
72 HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD);
73 HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST);
74 HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT);
75 HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE);
76 HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS);
77 HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE);
78 HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT);
79 /* WebDAV - RFC 2518 */
80 HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND);
81 HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH);
82 HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL);
83 HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY);
84 HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE);
85 HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK);
86 HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK);
87 /* WebDAV Versioning - RFC 3253 */
88 HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
89 HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT);
90 HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT);
91 HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN);
92 HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT);
93 HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE);
94 HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE);
95 HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL);
96 HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE);
97 HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
98 HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY);
99 /* WebDAV Access Control - RFC 3744 */
100 HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL);
101
102 return SUCCESS;
103 }
104
105 PHP_RINIT_FUNCTION(http_request_method)
106 {
107 HTTP_G(request).methods.custom.entries = ecalloc(1, sizeof(http_request_method_entry *));
108
109 return SUCCESS;
110 }
111
112 PHP_RSHUTDOWN_FUNCTION(http_request_method)
113 {
114 int i;
115 getGlobals(G);
116 http_request_method_entry **ptr = G->request.methods.custom.entries;
117
118 for (i = 0; i < G->request.methods.custom.count; ++i) {
119 if (ptr[i]) {
120 http_request_method_unregister(HTTP_CUSTOM_REQUEST_METHOD_START + i);
121 }
122 }
123 efree(G->request.methods.custom.entries);
124
125 return SUCCESS;
126 }
127
128 /* {{{ char *http_request_method_name(http_request_method) */
129 PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
130 {
131 getGlobals(G);
132 http_request_method_entry **ptr = G->request.methods.custom.entries;
133
134 if (HTTP_STD_REQUEST_METHOD(m)) {
135 return http_request_methods[m];
136 }
137
138 if ( (HTTP_CUSTOM_REQUEST_METHOD(m) >= 0) &&
139 (HTTP_CUSTOM_REQUEST_METHOD(m) < G->request.methods.custom.count) &&
140 (ptr[HTTP_CUSTOM_REQUEST_METHOD(m)])) {
141 return ptr[HTTP_CUSTOM_REQUEST_METHOD(m)]->name;
142 }
143
144 return http_request_methods[0];
145 }
146 /* }}} */
147
148 /* {{{ int http_request_method_exists(zend_bool, ulong, char *) */
149 PHP_HTTP_API int _http_request_method_exists(zend_bool by_name, http_request_method id, const char *name TSRMLS_DC)
150 {
151 int i;
152 getGlobals(G);
153 http_request_method_entry **ptr = G->request.methods.custom.entries;
154
155 if (by_name) {
156 for (i = HTTP_MIN_REQUEST_METHOD; i < HTTP_MAX_REQUEST_METHOD; ++i) {
157 if (!strcasecmp(name, http_request_methods[i])) {
158 return i;
159 }
160 }
161 for (i = 0; i < G->request.methods.custom.count; ++i) {
162 if (ptr[i] && !strcasecmp(name, ptr[i]->name)) {
163 return HTTP_CUSTOM_REQUEST_METHOD_START + i;
164 }
165 }
166 } else if (HTTP_STD_REQUEST_METHOD(id)) {
167 return id;
168 } else if ( (HTTP_CUSTOM_REQUEST_METHOD(id) >= 0) &&
169 (HTTP_CUSTOM_REQUEST_METHOD(id) < G->request.methods.custom.count) &&
170 (ptr[HTTP_CUSTOM_REQUEST_METHOD(id)])) {
171 return id;
172 }
173
174 return 0;
175 }
176 /* }}} */
177
178 /* {{{ int http_request_method_register(char *) */
179 PHP_HTTP_API int _http_request_method_register(const char *method_name, int method_name_len TSRMLS_DC)
180 {
181 int i, meth_num;
182 char *http_method, *method, *mconst;
183 getGlobals(G);
184 http_request_method_entry **ptr = G->request.methods.custom.entries;
185
186 if (!isalpha(*method_name)) {
187 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method does not start with a character (%s)", method_name);
188 return 0;
189 }
190
191 if (http_request_method_exists(1, 0, method_name)) {
192 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method does already exist (%s)", method_name);
193 return 0;
194 }
195
196 method = emalloc(method_name_len + 1);
197 mconst = emalloc(method_name_len + 1);
198 for (i = 0; i < method_name_len; ++i) {
199 switch (method_name[i])
200 {
201 case '-':
202 method[i] = '-';
203 mconst[i] = '_';
204 break;
205
206 default:
207 if (!isalnum(method_name[i])) {
208 efree(method);
209 efree(mconst);
210 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name);
211 return 0;
212 }
213 mconst[i] = method[i] = toupper(method_name[i]);
214 break;
215 }
216 }
217 method[method_name_len] = '\0';
218 mconst[method_name_len] = '\0';
219
220 ptr = erealloc(ptr, sizeof(http_request_method_entry *) * (G->request.methods.custom.count + 1));
221 G->request.methods.custom.entries = ptr;
222 ptr[G->request.methods.custom.count] = emalloc(sizeof(http_request_method_entry));
223 ptr[G->request.methods.custom.count]->name = method;
224 ptr[G->request.methods.custom.count]->cnst = mconst;
225 meth_num = HTTP_CUSTOM_REQUEST_METHOD_START + G->request.methods.custom.count++;
226
227 method_name_len = spprintf(&http_method, 0, "HTTP_METH_%s", mconst);
228 zend_register_long_constant(http_method, method_name_len + 1, meth_num, CONST_CS, http_module_number TSRMLS_CC);
229 efree(http_method);
230
231 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
232 method_name_len = spprintf(&http_method, 0, "METH_%s", mconst);
233 zend_declare_class_constant_long(http_request_object_ce, http_method, method_name_len, meth_num TSRMLS_CC);
234 efree(http_method);
235 #endif
236
237 return meth_num;
238 }
239 /* }}} */
240
241 /* {{{ STATUS http_request_method_unregister(int) */
242 PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC)
243 {
244 char *http_method;
245 int method_len;
246 getGlobals(G);
247 http_request_method_entry **ptr = G->request.methods.custom.entries;
248
249 if (HTTP_STD_REQUEST_METHOD(method)) {
250 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered");
251 return FAILURE;
252 }
253
254 if ( (HTTP_CUSTOM_REQUEST_METHOD(method) < 0) ||
255 (HTTP_CUSTOM_REQUEST_METHOD(method) > G->request.methods.custom.count) ||
256 (!ptr[HTTP_CUSTOM_REQUEST_METHOD(method)])) {
257 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %lu does not exist", method);
258 return FAILURE;
259 }
260
261 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
262 method_len = spprintf(&http_method, 0, "METH_%s", ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
263 if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, http_method, method_len + 1)) {
264 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", http_method);
265 efree(http_method);
266 return FAILURE;
267 }
268 efree(http_method);
269 #endif
270
271 method_len = spprintf(&http_method, 0, "HTTP_METH_%s", ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
272 if (SUCCESS != zend_hash_del(EG(zend_constants), http_method, method_len + 1)) {
273 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", http_method);
274 efree(http_method);
275 return FAILURE;
276 }
277 efree(http_method);
278
279 efree(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->name);
280 efree(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
281 STR_SET(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)], NULL);
282
283 return SUCCESS;
284 }
285 /* }}} */
286
287 /*
288 * Local variables:
289 * tab-width: 4
290 * c-basic-offset: 4
291 * End:
292 * vim600: noet sw=4 ts=4 fdm=marker
293 * vim<600: noet sw=4 ts=4
294 */
295