8caa319cf7310aa8d7e5dd32652572ee2e5fc126
[m6w6/ext-http] / php_http_misc.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-2010, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id $ */
14
15 #include "php_http.h"
16
17 #include <ext/standard/php_lcg.h>
18 #include <ext/standard/php_string.h>
19 #include <Zend/zend_exceptions.h>
20
21 /* SLEEP */
22
23 PHP_HTTP_API void php_http_sleep(double s)
24 {
25 #if defined(PHP_WIN32)
26 Sleep((DWORD) PHP_HTTP_MSEC(s));
27 #elif defined(HAVE_USLEEP)
28 usleep(PHP_HTTP_USEC(s));
29 #elif defined(HAVE_NANOSLEEP)
30 struct timespec req, rem;
31
32 req.tv_sec = (time_t) s;
33 req.tv_nsec = PHP_HTTP_NSEC(s) % PHP_HTTP_NANOSEC;
34
35 while (nanosleep(&req, &rem) && (errno == EINTR) && (PHP_HTTP_NSEC(rem.tv_sec) + rem.tv_nsec) > PHP_HTTP_NSEC(PHP_HTTP_DIFFSEC))) {
36 req.tv_sec = rem.tv_sec;
37 req.tv_nsec = rem.tv_nsec;
38 }
39 #else
40 struct timeval timeout;
41
42 timeout.tv.sec = (time_t) s;
43 timeout.tv_usec = PHP_HTTP_USEC(s) % PHP_HTTP_MCROSEC;
44
45 select(0, NULL, NULL, NULL, &timeout);
46 #endif
47 }
48
49
50 /* STRING UTILITIES */
51
52 int php_http_match(const char *haystack_str, const char *needle_str, int flags)
53 {
54 int result = 0;
55
56 if (flags & PHP_HTTP_MATCH_FULL) {
57 if (flags & PHP_HTTP_MATCH_CASE) {
58 result = !strcmp(haystack_str, needle_str);
59 } else {
60 result = !strcasecmp(haystack_str, needle_str);
61 }
62 } else {
63 char *found, *haystack = estrdup(haystack_str), *needle = estrdup(needle_str);
64
65 if (flags & PHP_HTTP_MATCH_CASE) {
66 found = zend_memnstr(haystack, needle, strlen(needle), haystack+strlen(haystack));
67 } else {
68 found = php_stristr(haystack, needle, strlen(haystack), strlen(needle));
69 }
70
71 if (found) {
72 if (!(flags & PHP_HTTP_MATCH_WORD)
73 || ( (found == haystack || !PHP_HTTP_IS_CTYPE(alnum, *(found - 1)))
74 && (!*(found + strlen(needle)) || !PHP_HTTP_IS_CTYPE(alnum, *(found + strlen(needle))))
75 )
76 ) {
77 result = 1;
78 }
79 }
80
81 STR_FREE(haystack);
82 STR_FREE(needle);
83 }
84
85 return result;
86 }
87
88 char *php_http_pretty_key(char *key, size_t key_len, zend_bool uctitle, zend_bool xhyphen)
89 {
90 size_t i;
91 int wasalpha;
92
93 if (key && key_len) {
94 if ((wasalpha = PHP_HTTP_IS_CTYPE(alpha, key[0]))) {
95 key[0] = (char) (uctitle ? PHP_HTTP_TO_CTYPE(upper, key[0]) : PHP_HTTP_TO_CTYPE(lower, key[0]));
96 }
97 for (i = 1; i < key_len; i++) {
98 if (PHP_HTTP_IS_CTYPE(alpha, key[i])) {
99 key[i] = (char) (((!wasalpha) && uctitle) ? PHP_HTTP_TO_CTYPE(upper, key[i]) : PHP_HTTP_TO_CTYPE(lower, key[i]));
100 wasalpha = 1;
101 } else {
102 if (xhyphen && (key[i] == '_')) {
103 key[i] = '-';
104 }
105 wasalpha = 0;
106 }
107 }
108 }
109 return key;
110 }
111
112
113 size_t php_http_boundary(char *buf, size_t buf_len TSRMLS_DC)
114 {
115 return snprintf(buf, buf_len, "%15.15F", PHP_HTTP_G->env.request.time * php_combined_lcg(TSRMLS_C));
116 }
117
118 /* ARRAYS */
119
120 int php_http_array_apply_append_func(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
121 {
122 int flags;
123 char *key = NULL;
124 HashTable *dst;
125 zval **data = NULL, **value = (zval **) pDest;
126
127 dst = va_arg(args, HashTable *);
128 flags = va_arg(args, int);
129
130 if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
131 if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
132 key = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
133 zend_hash_find(dst, key, hash_key->nKeyLength, (void *) &data);
134 } else {
135 zend_hash_quick_find(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) &data);
136 }
137
138 Z_ADDREF_P(*value);
139 if (data) {
140 if (Z_TYPE_PP(data) != IS_ARRAY) {
141 convert_to_array(*data);
142 }
143 add_next_index_zval(*data, *value);
144 } else if (key) {
145 zend_hash_add(dst, key, hash_key->nKeyLength, value, sizeof(zval *), NULL);
146 } else {
147 zend_hash_quick_add(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, value, sizeof(zval *), NULL);
148 }
149
150 if (key) {
151 efree(key);
152 }
153 }
154
155 return ZEND_HASH_APPLY_KEEP;
156 }
157
158 int php_http_array_apply_merge_func(void *pDest TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
159 {
160 int flags;
161 char *key = NULL;
162 HashTable *dst;
163 zval **value = (zval **) pDest;
164
165 dst = va_arg(args, HashTable *);
166 flags = va_arg(args, int);
167
168 if ((!(flags & ARRAY_JOIN_STRONLY)) || hash_key->nKeyLength) {
169 Z_ADDREF_P(*value);
170 if ((flags & ARRAY_JOIN_PRETTIFY) && hash_key->nKeyLength) {
171 key = php_http_pretty_key(estrndup(hash_key->arKey, hash_key->nKeyLength - 1), hash_key->nKeyLength - 1, 1, 1);
172 zend_hash_update(dst, key, hash_key->nKeyLength, (void *) value, sizeof(zval *), NULL);
173 efree(key);
174 } else {
175 zend_hash_quick_update(dst, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void *) value, sizeof(zval *), NULL);
176 }
177 }
178
179 return ZEND_HASH_APPLY_KEEP;
180 }
181
182 /* PASS CALLBACK */
183
184 PHP_HTTP_API size_t php_http_pass_wrapper(php_http_pass_callback_arg_t *cb, const char *str, size_t len)
185 {
186 TSRMLS_FETCH();
187 return cb->cb_zts(cb->cb_arg, str, len TSRMLS_CC);
188 }
189
190 /* ERROR */
191
192 static inline int scope_error_handling(long type TSRMLS_DC)
193 {
194 if ((type == E_THROW) || (EG(error_handling) == EH_THROW)) {
195 return EH_THROW;
196 }
197
198 if (EG(This) && instanceof_function(Z_OBJCE_P(EG(This)), php_http_object_class_entry)) {
199 return php_http_object_get_error_handling(EG(This) TSRMLS_CC);
200 }
201
202 return EH_NORMAL;
203 }
204
205 void php_http_error(long type TSRMLS_DC, long code, const char *format, ...)
206 {
207 va_list args;
208
209 va_start(args, format);
210 switch (scope_error_handling(type TSRMLS_CC)) {
211 case EH_THROW: {
212 char *message;
213 zend_class_entry *ce = php_http_exception_class_entry;
214
215 if (0&& EG(exception_class) && instanceof_function(EG(exception_class), php_http_exception_class_entry)) {
216 ce = EG(exception_class);
217 }
218
219 vspprintf(&message, 0, format, args);
220 zend_throw_exception(ce, message, code TSRMLS_CC);
221 efree(message);
222 break;
223 }
224 case EH_NORMAL:
225 php_verror(NULL, "", type, format, args TSRMLS_CC);
226 break;
227 case EH_SUPPRESS:
228 break;
229 }
230 va_end(args);
231 }
232
233 /*
234 * Local variables:
235 * tab-width: 4
236 * c-basic-offset: 4
237 * End:
238 * vim600: noet sw=4 ts=4 fdm=marker
239 * vim<600: noet sw=4 ts=4
240 */