nicer MINFO
[m6w6/ext-apfd] / php_apfd.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: apfd |
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) 2015, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #ifdef HAVE_CONFIG_H
14 #include "config.h"
15 #endif
16
17 #include "php.h"
18 #include "php_ini.h"
19 #include "ext/standard/info.h"
20 #include "SAPI.h"
21 #include "rfc1867.h"
22 #include "php_content_types.h"
23 #include "php_apfd.h"
24
25 typedef void (*apfd_enumerate_post_entry_fn)(sapi_post_entry *);
26
27 #if PHP_VERSION_ID >= 70000
28
29 struct apfd {
30 zval post;
31 zval files;
32 };
33
34 #define APFD_SG(t) &PG(http_globals)[t]
35 static inline sapi_post_entry *apfd_get_post_entry(const char *ct_str, size_t ct_len)
36 {
37 return zend_hash_str_find_ptr(&SG(known_post_content_types), ct_str, ct_len);
38 }
39
40 static inline void apfd_enumerate_post_entries(apfd_enumerate_post_entry_fn fn)
41 {
42 sapi_post_entry *pe;
43
44 ZEND_HASH_FOREACH_PTR(&SG(known_post_content_types), pe)
45 {
46 fn(pe);
47 }
48 ZEND_HASH_FOREACH_END();
49 }
50
51 static inline void apfd_backup(struct apfd *apfd)
52 {
53 if (SG(rfc1867_uploaded_files)) {
54 destroy_uploaded_files_hash();
55 }
56
57 zval_ptr_dtor(APFD_SG(TRACK_VARS_POST));
58 array_init(&apfd->post);
59 ZVAL_COPY_VALUE(APFD_SG(TRACK_VARS_POST), &apfd->post);
60
61 zval_ptr_dtor(APFD_SG(TRACK_VARS_FILES));
62 array_init(&apfd->files);
63 ZVAL_COPY_VALUE(APFD_SG(TRACK_VARS_FILES), &apfd->files);
64 }
65
66 static inline void apfd_update(struct apfd *apfd)
67 {
68 zend_hash_str_update(&EG(symbol_table), "_POST", sizeof("_POST")-1, APFD_SG(TRACK_VARS_POST));
69 Z_TRY_ADDREF_P(APFD_SG(TRACK_VARS_POST));
70
71 zend_hash_str_update(&EG(symbol_table), "_FILES", sizeof("_FILES")-1, APFD_SG(TRACK_VARS_FILES));
72 Z_TRY_ADDREF_P(APFD_SG(TRACK_VARS_FILES));
73 }
74
75 #else
76
77 struct apfd {
78 zval *post;
79 zval *files;
80 };
81
82 #define APFD_SG(t) PG(http_globals)[t]
83 static inline sapi_post_entry *apfd_get_post_entry(const char *ct_str, size_t ct_len TSRMLS_DC)
84 {
85 sapi_post_entry *post_entry;
86
87 if (SUCCESS == zend_hash_find(&SG(known_post_content_types), ct_str, ct_len+1, (void *) &post_entry)) {
88 return post_entry;
89 }
90 return NULL;
91 }
92
93 static inline void apfd_enumerate_post_entries(apfd_enumerate_post_entry_fn fn TSRMLS_DC)
94 {
95 HashPosition pos;
96 HashTable *ht = &SG(known_post_content_types);
97 sapi_post_entry *pe;
98
99 for (
100 zend_hash_internal_pointer_reset_ex(ht, &pos);
101 zend_hash_get_current_data_ex(ht, (void **) &pe, &pos) == SUCCESS;
102 zend_hash_move_forward_ex(ht, &pos)
103 ) {
104 fn(pe);
105 }
106 }
107
108 static inline void apfd_backup(struct apfd *apfd TSRMLS_DC)
109 {
110 apfd->post = APFD_SG(TRACK_VARS_POST);
111 apfd->files = APFD_SG(TRACK_VARS_FILES);
112 }
113
114 static inline void apfd_update(struct apfd *apfd TSRMLS_DC)
115 {
116 if (apfd->files != APFD_SG(TRACK_VARS_FILES) && APFD_SG(TRACK_VARS_FILES)) {
117 Z_ADDREF_P(APFD_SG(TRACK_VARS_FILES));
118 zend_hash_update(&EG(symbol_table), "_FILES", sizeof("_FILES"), &APFD_SG(TRACK_VARS_FILES), sizeof(zval *), NULL);
119 if (apfd->files) {
120 zval_ptr_dtor(&apfd->files);
121 }
122 }
123 }
124 #endif
125
126 PHP_RINIT_FUNCTION(apfd)
127 {
128 #ifndef TSRMLS_C
129 # define TSRMLS_C
130 # define TSRMLS_CC
131 #endif
132
133 sapi_request_info *req = &SG(request_info);
134
135 /* populate form data on non-POST requests */
136 if (req->request_method && strcasecmp(req->request_method, "POST") && req->content_type && *req->content_type) {
137 char *ct_str, *ct_dup = estrdup(req->content_type);
138 size_t ct_end = strcspn(ct_dup, ";, ");
139 sapi_post_entry *post_entry = NULL;
140
141 req->content_type_dup = ct_dup;
142
143 ct_str = zend_str_tolower_dup(ct_dup, ct_end);
144 if ((post_entry = apfd_get_post_entry(ct_str, ct_end TSRMLS_CC))) {
145 struct apfd apfd;
146
147 apfd_backup(&apfd TSRMLS_CC);
148
149 req->post_entry = post_entry;
150
151 if (post_entry->post_reader) {
152 post_entry->post_reader(TSRMLS_C);
153 }
154
155 if (sapi_module.default_post_reader) {
156 sapi_module.default_post_reader(TSRMLS_C);
157 }
158
159 sapi_handle_post(APFD_SG(TRACK_VARS_POST) TSRMLS_CC);
160
161 apfd_update(&apfd TSRMLS_CC);
162 }
163 efree(ct_str);
164
165 if (req->content_type_dup) {
166 efree(req->content_type_dup);
167 req->content_type_dup = NULL;
168 }
169 }
170
171 return SUCCESS;
172 }
173
174 #define CUSTOM_OR_DEFAULT(ptr, def) ((ptr) && ((ptr) != (def)) ? "custom" : "default")
175 static void apfd_enumerate_post_entry(sapi_post_entry *pe)
176 {
177 php_info_print_table_row(3, pe->content_type,
178 CUSTOM_OR_DEFAULT(pe->post_reader, sapi_read_standard_form_data),
179 CUSTOM_OR_DEFAULT(pe->post_handler, php_std_post_handler)
180 );
181 }
182
183 PHP_MINFO_FUNCTION(apfd)
184 {
185 php_info_print_table_start();
186 php_info_print_table_header(2, "APFD Support", "enabled");
187 php_info_print_table_row(2, "Extension Version", PHP_APFD_VERSION);
188 php_info_print_table_end();
189 php_info_print_table_start();
190 php_info_print_table_header(3, "Content type", "Reader", "Handler");
191 apfd_enumerate_post_entries(apfd_enumerate_post_entry);
192 php_info_print_table_end();
193 }
194
195 const zend_function_entry apfd_functions[] = {
196 {0}
197 };
198
199 zend_module_entry apfd_module_entry = {
200 STANDARD_MODULE_HEADER,
201 "apfd",
202 apfd_functions,
203 NULL,
204 NULL,
205 PHP_RINIT(apfd),
206 NULL,
207 PHP_MINFO(apfd),
208 PHP_APFD_VERSION,
209 STANDARD_MODULE_PROPERTIES
210 };
211
212 #ifdef COMPILE_DL_APFD
213 ZEND_GET_MODULE(apfd)
214 #endif
215
216 /*
217 * Local variables:
218 * tab-width: 4
219 * c-basic-offset: 4
220 * End:
221 * vim600: noet sw=4 ts=4 fdm=marker
222 * vim<600: noet sw=4 ts=4
223 */