- happy new year
[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-2006, 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 /* {{{ */
69 PHP_MINIT_FUNCTION(http_request_method)
70 {
71 /* HTTP/1.1 */
72 HTTP_LONG_CONSTANT("HTTP_METH_GET", HTTP_GET);
73 HTTP_LONG_CONSTANT("HTTP_METH_HEAD", HTTP_HEAD);
74 HTTP_LONG_CONSTANT("HTTP_METH_POST", HTTP_POST);
75 HTTP_LONG_CONSTANT("HTTP_METH_PUT", HTTP_PUT);
76 HTTP_LONG_CONSTANT("HTTP_METH_DELETE", HTTP_DELETE);
77 HTTP_LONG_CONSTANT("HTTP_METH_OPTIONS", HTTP_OPTIONS);
78 HTTP_LONG_CONSTANT("HTTP_METH_TRACE", HTTP_TRACE);
79 HTTP_LONG_CONSTANT("HTTP_METH_CONNECT", HTTP_CONNECT);
80 /* WebDAV - RFC 2518 */
81 HTTP_LONG_CONSTANT("HTTP_METH_PROPFIND", HTTP_PROPFIND);
82 HTTP_LONG_CONSTANT("HTTP_METH_PROPPATCH", HTTP_PROPPATCH);
83 HTTP_LONG_CONSTANT("HTTP_METH_MKCOL", HTTP_MKCOL);
84 HTTP_LONG_CONSTANT("HTTP_METH_COPY", HTTP_COPY);
85 HTTP_LONG_CONSTANT("HTTP_METH_MOVE", HTTP_MOVE);
86 HTTP_LONG_CONSTANT("HTTP_METH_LOCK", HTTP_LOCK);
87 HTTP_LONG_CONSTANT("HTTP_METH_UNLOCK", HTTP_UNLOCK);
88 /* WebDAV Versioning - RFC 3253 */
89 HTTP_LONG_CONSTANT("HTTP_METH_VERSION_CONTROL", HTTP_VERSION_CONTROL);
90 HTTP_LONG_CONSTANT("HTTP_METH_REPORT", HTTP_REPORT);
91 HTTP_LONG_CONSTANT("HTTP_METH_CHECKOUT", HTTP_CHECKOUT);
92 HTTP_LONG_CONSTANT("HTTP_METH_CHECKIN", HTTP_CHECKIN);
93 HTTP_LONG_CONSTANT("HTTP_METH_UNCHECKOUT", HTTP_UNCHECKOUT);
94 HTTP_LONG_CONSTANT("HTTP_METH_MKWORKSPACE", HTTP_MKWORKSPACE);
95 HTTP_LONG_CONSTANT("HTTP_METH_UPDATE", HTTP_UPDATE);
96 HTTP_LONG_CONSTANT("HTTP_METH_LABEL", HTTP_LABEL);
97 HTTP_LONG_CONSTANT("HTTP_METH_MERGE", HTTP_MERGE);
98 HTTP_LONG_CONSTANT("HTTP_METH_BASELINE_CONTROL", HTTP_BASELINE_CONTROL);
99 HTTP_LONG_CONSTANT("HTTP_METH_MKACTIVITY", HTTP_MKACTIVITY);
100 /* WebDAV Access Control - RFC 3744 */
101 HTTP_LONG_CONSTANT("HTTP_METH_ACL", HTTP_ACL);
102
103 return SUCCESS;
104 }
105
106 PHP_RINIT_FUNCTION(http_request_method)
107 {
108 HTTP_G(request).methods.custom.entries = ecalloc(1, sizeof(http_request_method_entry *));
109
110 return SUCCESS;
111 }
112
113 PHP_RSHUTDOWN_FUNCTION(http_request_method)
114 {
115 int i;
116 getGlobals(G);
117 http_request_method_entry **ptr = G->request.methods.custom.entries;
118
119 for (i = 0; i < G->request.methods.custom.count; ++i) {
120 if (ptr[i]) {
121 http_request_method_unregister(HTTP_CUSTOM_REQUEST_METHOD_START + i);
122 }
123 }
124 efree(G->request.methods.custom.entries);
125
126 return SUCCESS;
127 }
128 /* }}} */
129
130 /* {{{ char *http_request_method_name(http_request_method) */
131 PHP_HTTP_API const char *_http_request_method_name(http_request_method m TSRMLS_DC)
132 {
133 getGlobals(G);
134 http_request_method_entry **ptr = G->request.methods.custom.entries;
135
136 if (HTTP_STD_REQUEST_METHOD(m)) {
137 return http_request_methods[m];
138 }
139
140 if ( (HTTP_CUSTOM_REQUEST_METHOD(m) >= 0) &&
141 (HTTP_CUSTOM_REQUEST_METHOD(m) < G->request.methods.custom.count) &&
142 (ptr[HTTP_CUSTOM_REQUEST_METHOD(m)])) {
143 return ptr[HTTP_CUSTOM_REQUEST_METHOD(m)]->name;
144 }
145
146 return http_request_methods[0];
147 }
148 /* }}} */
149
150 /* {{{ int http_request_method_exists(zend_bool, ulong, char *) */
151 PHP_HTTP_API int _http_request_method_exists(zend_bool by_name, http_request_method id, const char *name TSRMLS_DC)
152 {
153 int i;
154 getGlobals(G);
155 http_request_method_entry **ptr = G->request.methods.custom.entries;
156
157 if (by_name) {
158 for (i = HTTP_MIN_REQUEST_METHOD; i < HTTP_MAX_REQUEST_METHOD; ++i) {
159 if (!strcasecmp(name, http_request_methods[i])) {
160 return i;
161 }
162 }
163 for (i = 0; i < G->request.methods.custom.count; ++i) {
164 if (ptr[i] && !strcasecmp(name, ptr[i]->name)) {
165 return HTTP_CUSTOM_REQUEST_METHOD_START + i;
166 }
167 }
168 } else if (HTTP_STD_REQUEST_METHOD(id)) {
169 return id;
170 } else if ( (HTTP_CUSTOM_REQUEST_METHOD(id) >= 0) &&
171 (HTTP_CUSTOM_REQUEST_METHOD(id) < G->request.methods.custom.count) &&
172 (ptr[HTTP_CUSTOM_REQUEST_METHOD(id)])) {
173 return id;
174 }
175
176 return 0;
177 }
178 /* }}} */
179
180 /* {{{ int http_request_method_register(char *) */
181 PHP_HTTP_API int _http_request_method_register(const char *method_name, int method_name_len TSRMLS_DC)
182 {
183 int i, meth_num;
184 char *http_method, *method, *mconst;
185 getGlobals(G);
186 http_request_method_entry **ptr = G->request.methods.custom.entries;
187
188 if (!isalpha(*method_name)) {
189 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method does not start with a character (%s)", method_name);
190 return 0;
191 }
192
193 if (http_request_method_exists(1, 0, method_name)) {
194 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method does already exist (%s)", method_name);
195 return 0;
196 }
197
198 method = emalloc(method_name_len + 1);
199 mconst = emalloc(method_name_len + 1);
200 for (i = 0; i < method_name_len; ++i) {
201 switch (method_name[i])
202 {
203 case '-':
204 method[i] = '-';
205 mconst[i] = '_';
206 break;
207
208 default:
209 if (!isalnum(method_name[i])) {
210 efree(method);
211 efree(mconst);
212 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Request method contains illegal characters (%s)", method_name);
213 return 0;
214 }
215 mconst[i] = method[i] = toupper(method_name[i]);
216 break;
217 }
218 }
219 method[method_name_len] = '\0';
220 mconst[method_name_len] = '\0';
221
222 ptr = erealloc(ptr, sizeof(http_request_method_entry *) * (G->request.methods.custom.count + 1));
223 G->request.methods.custom.entries = ptr;
224 ptr[G->request.methods.custom.count] = emalloc(sizeof(http_request_method_entry));
225 ptr[G->request.methods.custom.count]->name = method;
226 ptr[G->request.methods.custom.count]->cnst = mconst;
227 meth_num = HTTP_CUSTOM_REQUEST_METHOD_START + G->request.methods.custom.count++;
228
229 method_name_len = spprintf(&http_method, 0, "HTTP_METH_%s", mconst);
230 zend_register_long_constant(http_method, method_name_len + 1, meth_num, CONST_CS, http_module_number TSRMLS_CC);
231 efree(http_method);
232
233 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
234 method_name_len = spprintf(&http_method, 0, "METH_%s", mconst);
235 zend_declare_class_constant_long(http_request_object_ce, http_method, method_name_len, meth_num TSRMLS_CC);
236 efree(http_method);
237 #endif
238
239 return meth_num;
240 }
241 /* }}} */
242
243 /* {{{ STATUS http_request_method_unregister(int) */
244 PHP_HTTP_API STATUS _http_request_method_unregister(int method TSRMLS_DC)
245 {
246 char *http_method;
247 int method_len;
248 getGlobals(G);
249 http_request_method_entry **ptr = G->request.methods.custom.entries;
250
251 if (HTTP_STD_REQUEST_METHOD(method)) {
252 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Standard request methods cannot be unregistered");
253 return FAILURE;
254 }
255
256 if ( (HTTP_CUSTOM_REQUEST_METHOD(method) < 0) ||
257 (HTTP_CUSTOM_REQUEST_METHOD(method) > G->request.methods.custom.count) ||
258 (!ptr[HTTP_CUSTOM_REQUEST_METHOD(method)])) {
259 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Custom request method with id %lu does not exist", method);
260 return FAILURE;
261 }
262
263 #if defined(ZEND_ENGINE_2) && defined(HTTP_HAVE_CURL) && !defined(WONKY)
264 method_len = spprintf(&http_method, 0, "METH_%s", ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
265 if (SUCCESS != zend_hash_del(&http_request_object_ce->constants_table, http_method, method_len + 1)) {
266 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: HttpRequest::%s", http_method);
267 efree(http_method);
268 return FAILURE;
269 }
270 efree(http_method);
271 #endif
272
273 method_len = spprintf(&http_method, 0, "HTTP_METH_%s", ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
274 if (SUCCESS != zend_hash_del(EG(zend_constants), http_method, method_len + 1)) {
275 http_error_ex(HE_NOTICE, HTTP_E_REQUEST_METHOD, "Could not unregister request method: %s", http_method);
276 efree(http_method);
277 return FAILURE;
278 }
279 efree(http_method);
280
281 efree(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->name);
282 efree(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)]->cnst);
283 STR_SET(ptr[HTTP_CUSTOM_REQUEST_METHOD(method)], NULL);
284
285 return SUCCESS;
286 }
287 /* }}} */
288
289 /*
290 * Local variables:
291 * tab-width: 4
292 * c-basic-offset: 4
293 * End:
294 * vim600: noet sw=4 ts=4 fdm=marker
295 * vim<600: noet sw=4 ts=4
296 */
297