root/eaccelerator/tags/start/content.c

Revision 5, 21.1 kB (checked in by anonymous, 4 years ago)

This commit was manufactured by cvs2svn to create branch 'eAccelerator'.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2    +----------------------------------------------------------------------+
3    | Turck MMCache for PHP Version 4                                      |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 2002-2003 TurckSoft, St. Petersburg                    |
6    | http://www.turcksoft.com                                             |
7    +----------------------------------------------------------------------+
8    | This program is free software; you can redistribute it and/or        |
9    | modify it under the terms of the GNU General Public License          |
10    | as published by the Free Software Foundation; either version 2       |
11    | of the License, or (at your option) any later version.               |
12    |                                                                      |
13    | This program is distributed in the hope that it will be useful,      |
14    | but WITHOUT ANY WARRANTY; without even the implied warranty of       |
15    | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        |
16    | GNU General Public License for more details.                         |
17    |                                                                      |
18    | You should have received a copy of the GNU General Public License    |
19    | along with this program; if not, write to the Free Software          |
20    | Foundation, Inc., 59 Temple Place - Suite 330, Boston,               |
21    | MA  02111-1307, USA.                                                 |
22    |                                                                      |
23    | A copy is availble at http://www.gnu.org/copyleft/gpl.txt            |
24    +----------------------------------------------------------------------+
25    | Author: Dmitry Stogov <mmcache@turckware.ru>                         |
26    +----------------------------------------------------------------------+
27    $Id$
28 */
29
30 #include "eaccelerator.h"
31
32 #ifdef HAVE_EACCELERATOR
33 #ifdef WITH_EACCELERATOR_CONTENT_CACHING
34
35 #include "SAPI.h"
36
37 #define EACCELERATOR_COMPRESS_MIN 128
38
39 static int (*eaccelerator_old_header_handler)(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC);
40
41 static int eaccelerator_check_compression(sapi_header_struct *sapi_header TSRMLS_DC) {
42   if (strstr(sapi_header->header, "Content-Type") == sapi_header->header) {
43     char *ch = sapi_header->header + sizeof("Content-Type") - 1;
44     while (*ch != '\0' && *ch != ':') {ch++;}
45     if (*ch == ':') {ch++;}
46     while (*ch == ' ') {ch++;}
47     if (strstr(ch, "text") != ch) {
48       MMCG(compress_content) = 0;
49       return 0;
50     }
51   } else if (strstr(sapi_header->header, "Content-Encoding") == sapi_header->header) {
52     MMCG(compress_content) = 0;
53     return 0;
54   }
55   return 1;
56 }
57
58 static void eaccelerator_free_header(sapi_header_struct *sapi_header) {
59   efree(sapi_header->header);
60 }
61
62 static int eaccelerator_header_handler(sapi_header_struct *sapi_header, sapi_headers_struct *sapi_headers TSRMLS_DC) {
63   if (MMCG(content_headers) != NULL) {
64     sapi_header_struct x;
65     memcpy(&x, sapi_header, sizeof(sapi_header_struct));
66     x.header = estrndup(sapi_header->header, sapi_header->header_len);
67     zend_llist_add_element(MMCG(content_headers), &x);
68   }
69   eaccelerator_check_compression(sapi_header TSRMLS_CC);
70   if (eaccelerator_old_header_handler) {
71     return eaccelerator_old_header_handler(sapi_header, sapi_headers TSRMLS_CC);
72   } else {
73     return SAPI_HEADER_ADD;
74   }
75 }
76
77 void eaccelerator_content_cache_startup() {
78   if (eaccelerator_content_cache_place != eaccelerator_none) {
79     eaccelerator_old_header_handler = sapi_module.header_handler;
80     sapi_module.header_handler = eaccelerator_header_handler;
81   }
82 }
83
84 void eaccelerator_content_cache_shutdown() {
85   if (eaccelerator_content_cache_place != eaccelerator_none) {
86     sapi_module.header_handler = eaccelerator_old_header_handler;
87   }
88 }
89
90 static int eaccelerator_is_not_modified(zval* return_value TSRMLS_DC) {
91   char  etag[256];
92   zval  **server_vars, **match;
93
94   if (!SG(headers_sent)) {
95     sprintf(etag,"ETag: eaccelerator-%u",eaccelerator_crc32(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value)));
96     sapi_add_header(etag, strlen(etag), 1);
97     if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
98         Z_TYPE_PP(server_vars) == IS_ARRAY &&
99         zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_IF_NONE_MATCH", sizeof("HTTP_IF_NONE_MATCH"), (void **) &match)==SUCCESS &&
100         Z_TYPE_PP(match) == IS_STRING) {
101       if (strcmp(etag+6,Z_STRVAL_PP(match)) == 0 &&
102           sapi_add_header("HTTP/1.0 304", sizeof("HTTP/1.0 304") - 1, 1) == SUCCESS &&
103           sapi_add_header("Status: 304 Not Modified", sizeof("Status: 304 Not Modified") - 1, 1) == SUCCESS) {
104         zval_dtor(return_value);
105         return_value->value.str.val = empty_string;
106         return_value->value.str.len = 0;
107         /*fprintf(stderr,"\nnot-modified\n");*/
108         return 1;
109       }
110     }
111   }
112   return 0;
113 }
114
115 static void eaccelerator_put_page(const char* key, int key_len, zval* content, time_t ttl  TSRMLS_DC) {
116   zval cache_array;
117   zval *cache_content;
118   INIT_ZVAL(cache_array);
119   array_init(&cache_array);
120   MAKE_STD_ZVAL(cache_content);
121   if (MMCG(content_headers) && (MMCG(content_headers)->count > 0)) {
122     zend_llist_element *p = MMCG(content_headers)->head;
123     zval *headers;
124     MAKE_STD_ZVAL(headers);
125     array_init(headers);
126     while (p != NULL) {
127       sapi_header_struct* h = (sapi_header_struct*)&p->data;
128       char* s = emalloc(h->header_len+2);
129       s[0] = h->replace?'1':'0';
130       memcpy(s+1, h->header, h->header_len+1);
131       add_next_index_stringl(headers, s, h->header_len+1, 0);
132       p = p->next;
133     }
134     add_assoc_zval(&cache_array, "headers", headers);
135   }
136   memcpy(cache_content, content, sizeof(zval));
137   zval_copy_ctor(cache_content);
138   cache_content->is_ref = 0;
139   cache_content->refcount = 1;
140   add_assoc_zval(&cache_array, "content", cache_content);
141   eaccelerator_put(key, key_len , &cache_array, ttl, eaccelerator_content_cache_place TSRMLS_CC);
142   zval_dtor(&cache_array);
143 }
144
145 static int eaccelerator_send_header(zval **header TSRMLS_DC) {
146   sapi_add_header_ex(Z_STRVAL_PP(header)+1, Z_STRLEN_PP(header)-1, 1,
147                      (zend_bool)((Z_STRVAL_PP(header)[0] == '0')?0:1) TSRMLS_CC);
148   return SUCCESS;
149 }
150
151 static int eaccelerator_get_page(const char* key, int key_len, zval* return_value TSRMLS_DC) {
152   int   ret = 0;
153   zval cache_array;
154   zval **headers;
155   zval **content;
156   if (eaccelerator_get(key, key_len, &cache_array, eaccelerator_content_cache_place TSRMLS_CC)) {
157     if (Z_TYPE(cache_array) == IS_ARRAY) {
158       if (zend_hash_find(Z_ARRVAL(cache_array),"content",sizeof("content"),(void**)&content) == SUCCESS &&
159          Z_TYPE_PP(content) == IS_STRING) {
160         if (zend_hash_find(Z_ARRVAL(cache_array),"headers",sizeof("headers"),(void**)&headers) == SUCCESS &&
161            Z_TYPE_PP(headers) == IS_ARRAY) {
162           zend_hash_apply(Z_ARRVAL_PP(headers), (apply_func_t)eaccelerator_send_header TSRMLS_CC);
163         }
164         memcpy(return_value,*content, sizeof(zval));
165         zval_copy_ctor(return_value);
166         ret = 1;
167       }
168     }
169     zval_dtor(&cache_array);
170   }
171   return ret;
172 }
173
174 static void eaccelerator_compress(char* key, int key_len, zval* return_value, time_t ttl TSRMLS_DC) {
175   zval  **server_vars, **encoding;
176
177   if (MMCG(compression_enabled) &&
178       MMCG(compress_content) &&
179       !SG(headers_sent) &&
180       zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
181       Z_TYPE_PP(server_vars) == IS_ARRAY &&
182       zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &encoding)==SUCCESS &&
183       Z_TYPE_PP(encoding) == IS_STRING &&
184       Z_TYPE_P(return_value) == IS_STRING &&
185       Z_STRLEN_P(return_value) >= EACCELERATOR_COMPRESS_MIN) {
186     char* zkey = NULL;
187     int   zkey_len;
188     char* enc;
189     zval  func;
190     zval* params[2];
191     zval  gzstring;
192     int   gzip = 0;
193     zval  level;
194
195     zend_llist_element *p = SG(sapi_headers).headers.head;
196     while (p != NULL) {
197       sapi_header_struct* h = (sapi_header_struct*)&p->data;
198       if (!eaccelerator_check_compression(h TSRMLS_CC)) {
199         eaccelerator_is_not_modified(return_value TSRMLS_CC);
200         return;
201       }
202       p = p->next;
203     }
204
205     if (strstr(Z_STRVAL_PP(encoding),"x-gzip")) {
206       zkey_len = sizeof("gzip_") + key_len - 1;
207       zkey = emalloc(zkey_len+1);
208       memcpy(zkey,"gzip_",sizeof("gzip_")-1);
209       memcpy(zkey+sizeof("gzip_")-1,key,key_len+1);
210       ZVAL_STRING(&func, "gzcompress", 0);
211       enc = "Content-Encoding: x-gzip";
212       params[0] = return_value;
213       gzip = 1;
214     } else if (strstr(Z_STRVAL_PP(encoding),"gzip")) {
215       zkey_len = sizeof("gzip_") + key_len - 1;
216       zkey = emalloc(zkey_len+1);
217       memcpy(zkey,"gzip_",sizeof("gzip_")-1);
218       memcpy(zkey+sizeof("gzip_")-1,key,key_len+1);
219       ZVAL_STRING(&func, "gzcompress", 0);
220       enc = "Content-Encoding: gzip";
221       params[0] = return_value;
222       gzip = 1;
223     } else if (strstr(Z_STRVAL_PP(encoding),"deflate")) {
224       zkey_len = sizeof("deflate_") + key_len - 1;
225       zkey = emalloc(zkey_len+1);
226       memcpy(zkey,"deflate_",sizeof("deflate_")-1);
227       memcpy(zkey+sizeof("deflate_")-1,key,key_len+1);
228       ZVAL_STRING(&func, "gzdeflate", 0);
229       enc = "Content-Encoding: deflate";
230       params[0] = return_value;
231     } else {
232       eaccelerator_is_not_modified(return_value TSRMLS_CC);
233       return;
234     }
235     INIT_ZVAL(level);
236     ZVAL_LONG(&level,MMCG(compress_level));
237     params[1] = &level;
238     if (zkey != NULL &&
239         zend_hash_exists(EG(function_table), Z_STRVAL(func), Z_STRLEN(func)+1) &&
240         call_user_function(CG(function_table), (zval**)NULL, &func, &gzstring, 2, params TSRMLS_CC) == SUCCESS &&
241         gzstring.type == IS_STRING) {
242       if (gzip) {
243         char* ret = emalloc(gzstring.value.str.len+13);
244         unsigned long crc32 = eaccelerator_crc32(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
245         ret[0] = '\x1f';
246         ret[1] = '\x8b';
247         ret[2] = '\x08';
248         ret[3] = '\x00';
249         ret[4] = '\x00';
250         ret[5] = '\x00';
251         ret[6] = '\x00';
252         ret[7] = '\x00';
253         ret[8] = '\x00';
254         ret[9] = '\x03';
255         memcpy(ret+10,gzstring.value.str.val+2,gzstring.value.str.len-6);
256         ret[gzstring.value.str.len+4]  = (char)(crc32 & 0xff);
257         ret[gzstring.value.str.len+5]  = (char)((crc32 >> 8) & 0xff);
258         ret[gzstring.value.str.len+6]  = (char)((crc32 >> 16) & 0xff);
259         ret[gzstring.value.str.len+7]  = (char)((crc32 >> 24) & 0xff);
260         ret[gzstring.value.str.len+8]  = (char)(return_value->value.str.len & 0xff);
261         ret[gzstring.value.str.len+9]  = (char)((return_value->value.str.len >> 8) & 0xff);
262         ret[gzstring.value.str.len+10] = (char)((return_value->value.str.len >> 16) & 0xff);
263         ret[gzstring.value.str.len+11] = (char)((return_value->value.str.len >> 24) & 0xff);
264         ret[gzstring.value.str.len+12] = '\x00';
265         STR_FREE(gzstring.value.str.val);
266         gzstring.value.str.val = ret;
267         gzstring.value.str.len += 12;
268       }
269       eaccelerator_put_page(zkey, zkey_len, &gzstring, ttl TSRMLS_CC);
270       if (!eaccelerator_is_not_modified(&gzstring TSRMLS_CC) &&
271           sapi_add_header(enc, strlen(enc), 1) == SUCCESS &&
272           sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1) == SUCCESS) {
273       }
274       efree(zkey);
275       zval_dtor(return_value);
276       memcpy(return_value,&gzstring,sizeof(zval));
277       return;
278     }
279     if (zkey != NULL) {
280       efree(zkey);
281     }
282   }
283   eaccelerator_is_not_modified(return_value TSRMLS_CC);
284 }
285
286 static void eaccelerator_destroy_headers(TSRMLS_D) {
287   if (MMCG(content_headers) != NULL) {
288     zend_llist_destroy(MMCG(content_headers));
289     efree(MMCG(content_headers));
290     MMCG(content_headers) = NULL;
291   }
292 }
293
294 PHP_FUNCTION(_eaccelerator_output_handler) {
295   zval* content;
296   long  status;
297   char* s;
298   char* key;
299   int   key_len = 0;
300   time_t ttl = 0;
301
302   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
303                             "z|l", &content, &status) == FAILURE) {
304     eaccelerator_destroy_headers(TSRMLS_C);
305     return;
306   }
307   memcpy(return_value, content, sizeof(zval));
308   s = key = return_value->value.str.val;
309   if ((status & PHP_OUTPUT_HANDLER_START) != 0) {
310     while (*s) {++s;}
311     ttl = atoi(key);
312     s = key = s+1;
313     if (s - return_value->value.str.val > return_value->value.str.len) {
314       zval_copy_ctor(return_value);
315       eaccelerator_destroy_headers(TSRMLS_C);
316       return;
317     }
318     while (*s) {++s;}
319     key_len = atoi(key);
320     s = key = s+1;
321     if (s - return_value->value.str.val > return_value->value.str.len) {
322       zval_copy_ctor(return_value);
323       eaccelerator_destroy_headers(TSRMLS_C);
324       return;
325     }
326     while (*s) {++s;}
327     ++s;
328     if (s - return_value->value.str.val > return_value->value.str.len) {
329       zval_copy_ctor(return_value);
330       eaccelerator_destroy_headers(TSRMLS_C);
331       return;
332     }
333   }
334   return_value->value.str.len -= (s-return_value->value.str.val);
335   return_value->value.str.val = s;
336   zval_copy_ctor(return_value);
337   if ((status & PHP_OUTPUT_HANDLER_START) != 0 &&
338       (status & PHP_OUTPUT_HANDLER_END) != 0 &&
339       !(PG(connection_status) & PHP_CONNECTION_ABORTED) != 0) {
340     eaccelerator_put_page(key, key_len , return_value, ttl TSRMLS_CC);
341     eaccelerator_compress(key, key_len, return_value, ttl TSRMLS_CC);
342   }
343   eaccelerator_destroy_headers(TSRMLS_C);
344 }
345
346 PHP_FUNCTION(eaccelerator_cache_page) {
347   char* key;
348   int   key_len;
349   long  ttl = 0;
350   zval  **server_vars, **encoding;
351
352   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
353                           "s|l", &key, &key_len, &ttl) == FAILURE) {
354     RETURN_FALSE;
355   }
356   if (eaccelerator_content_cache_place == eaccelerator_none) {
357     RETURN_FALSE;
358   }
359   if (MMCG(content_headers) != NULL) {
360     RETURN_FALSE;
361   }
362   if (MMCG(compression_enabled) &&
363       MMCG(compress_content) &&
364       !SG(headers_sent) &&
365       zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
366       Z_TYPE_PP(server_vars) == IS_ARRAY &&
367       zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_ACCEPT_ENCODING", sizeof("HTTP_ACCEPT_ENCODING"), (void **) &encoding)==SUCCESS &&
368       Z_TYPE_PP(encoding) == IS_STRING) {
369     char* zkey = NULL;
370     char* enc = NULL;
371     int   zkey_len = 0;
372     if (strstr(Z_STRVAL_PP(encoding),"x-gzip")) {
373       zkey_len = sizeof("gzip_") + key_len - 1;
374       zkey = emalloc(zkey_len+1);
375       memcpy(zkey,"gzip_",sizeof("gzip_")-1);
376       memcpy(zkey+sizeof("gzip_")-1,key,key_len+1);
377       enc = "Content-Encoding: x-gzip";
378     } else if (strstr(Z_STRVAL_PP(encoding),"gzip")) {
379       zkey_len = sizeof("gzip_") + key_len - 1;
380       zkey = emalloc(zkey_len+1);
381       memcpy(zkey,"gzip_",sizeof("gzip_")-1);
382       memcpy(zkey+sizeof("gzip_")-1,key,key_len+1);
383       enc = "Content-Encoding: gzip";
384     } else if (strstr(Z_STRVAL_PP(encoding),"deflate")) {
385       zkey_len = sizeof("deflate_") + key_len - 1;
386       zkey = emalloc(zkey_len+1);
387       memcpy(zkey,"deflate_",sizeof("deflate_")-1);
388       memcpy(zkey+sizeof("deflate_")-1,key,key_len+1);
389       enc = "Content-Encoding: deflate";
390     }
391     if (zkey != NULL &&
392         eaccelerator_get_page(zkey, zkey_len, return_value TSRMLS_CC) &&
393         return_value->type == IS_STRING) {
394       if (!eaccelerator_is_not_modified(return_value TSRMLS_CC) &&
395           sapi_add_header(enc, strlen(enc), 1) == SUCCESS &&
396           sapi_add_header("Vary: Accept-Encoding", sizeof("Vary: Accept-Encoding") - 1, 1) == SUCCESS) {
397         ZEND_WRITE(return_value->value.str.val, return_value->value.str.len);
398       }
399       efree(zkey);
400       zend_bailout();
401       RETURN_TRUE;
402     }
403     if (zkey != NULL) {
404       efree(zkey);
405     }
406   }
407   if (eaccelerator_get_page(key, key_len, return_value TSRMLS_CC) &&
408       return_value->type == IS_STRING) {
409     /*  Output is cached. Print it. */
410     if (!(PG(connection_status) & PHP_CONNECTION_ABORTED)) {
411       eaccelerator_compress(key, key_len, return_value, ttl TSRMLS_CC);
412     }
413     ZEND_WRITE(return_value->value.str.val, return_value->value.str.len);
414     zend_bailout();
415     RETURN_TRUE;
416   } else {
417     /* Output is not cached. Install Handler. */
418     char ch = '\000';
419 #ifdef PHP_OUTPUT_HANDLER_USER
420 #if defined(PHP_MAJOR_VERSION) && defined(PHP_MINOR_VERSION) && \
421     ((PHP_MAJOR_VERSION == 4 && PHP_MINOR_VERSION >= 3) || \
422      (PHP_MAJOR_VERSION > 4))
423     /* PHP 4.3.0 and above */
424     zval handler;
425     ZVAL_STRING(&handler, "_eaccelerator_output_handler", 0);
426     php_start_ob_buffer(&handler, 0, 0 TSRMLS_CC);
427     if (OG(active_ob_buffer).handler_name == NULL ||
428         strcmp(OG(active_ob_buffer).handler_name,"_eaccelerator_output_handler") != 0) {
429 #else
430     /* PHP 4.2.* */
431     zval *handler;
432     ALLOC_INIT_ZVAL(handler);
433     ZVAL_STRING(handler, "_eaccelerator_output_handler", 1);
434     php_start_ob_buffer(handler, 0, 0 TSRMLS_CC);
435     if (OG(active_ob_buffer).handler_name == NULL ||
436         strcmp(OG(active_ob_buffer).handler_name,"_eaccelerator_output_handler") != 0) {
437 #endif
438 #else
439     /* PHP 4.1.2 and before */
440     zval *handler;
441     ALLOC_INIT_ZVAL(handler);
442     ZVAL_STRING(handler, "_eaccelerator_output_handler", 1);
443     if (php_start_ob_buffer(handler, 0 TSRMLS_CC) == FAILURE) {
444 #endif
445       RETURN_FALSE;
446     }
447     zend_printf("%ld",ttl);
448     ZEND_PUTC(ch);
449     zend_printf("%d",key_len);
450     ZEND_PUTC(ch);
451     zend_printf("%s",key);
452     ZEND_PUTC(ch);
453     /* Init headers cache */
454     MMCG(content_headers) = emalloc(sizeof(zend_llist));
455     zend_llist_init(MMCG(content_headers), sizeof(sapi_header_struct), (void (*)(void *))eaccelerator_free_header, 0);
456     RETURN_TRUE;
457   }
458   RETURN_FALSE;
459 }
460
461 PHP_FUNCTION(eaccelerator_rm_page) {
462   char* key;
463   int   key_len;
464   char* zkey;
465   int   zkey_len;
466
467   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
468                           "s", &key, &key_len) == FAILURE) {
469     return;
470   }
471   if (eaccelerator_content_cache_place == eaccelerator_none) {
472     RETURN_NULL();
473   }
474   zkey = do_alloca(key_len+16);
475   eaccelerator_rm(key, key_len, eaccelerator_content_cache_place TSRMLS_CC);
476   zkey_len = sizeof("gzip_") + key_len - 1;
477   memcpy(zkey,"gzip_",sizeof("gzip_")-1);
478   memcpy(zkey+sizeof("gzip_")-1,key,key_len+1);
479   eaccelerator_rm(zkey, zkey_len, eaccelerator_content_cache_place TSRMLS_CC);
480   zkey_len = sizeof("deflate_") + key_len - 1;
481   memcpy(zkey,"deflate_",sizeof("deflate_")-1);
482   memcpy(zkey+sizeof("deflate_")-1,key,key_len+1);
483   eaccelerator_rm(zkey, zkey_len, eaccelerator_content_cache_place TSRMLS_CC);
484   RETURN_NULL();
485 }
486
487 PHP_FUNCTION(eaccelerator_cache_output) {
488   char* key;
489   int   key_len;
490   char* code;
491   int   code_len;
492   long  ttl = 0;
493   char* eval_name;
494   int ret = 0;
495
496   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
497                           "ss|l", &key, &key_len, &code, &code_len, &ttl) == FAILURE) {
498     return;
499   }
500   if (eaccelerator_content_cache_place == eaccelerator_none) {
501     eval_name = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
502     zend_eval_string(code, NULL, eval_name TSRMLS_CC);
503     efree(eval_name);
504     RETURN_FALSE;
505   } else if (eaccelerator_get(key, key_len, return_value, eaccelerator_content_cache_place TSRMLS_CC) &&
506       return_value->type == IS_STRING) {
507     /*  Output is cached. Print it. */
508     ZEND_WRITE(return_value->value.str.val, return_value->value.str.len);
509     zval_dtor(return_value);
510     RETURN_TRUE;
511   } else {
512     /* Output is not cached. Generate it and print. */
513     eval_name = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
514 #ifdef PHP_OUTPUT_HANDLER_USER
515     /* PHP 4.2.0 and above */
516     if (php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) == FAILURE) {
517 #else
518     /* PHP 4.1.2 and before */
519     if (php_start_ob_buffer(NULL, 0 TSRMLS_CC) == FAILURE) {
520 #endif
521       zend_eval_string(code, NULL, eval_name TSRMLS_CC);
522       efree(eval_name);
523       RETURN_FALSE;
524     }
525     if (zend_eval_string(code, NULL, eval_name TSRMLS_CC) == SUCCESS) {
526       if (php_ob_get_buffer(return_value TSRMLS_CC) == SUCCESS) {
527         ret = eaccelerator_put(key, key_len, return_value, ttl, eaccelerator_content_cache_place TSRMLS_CC);
528         zval_dtor(return_value);
529       }
530     }
531     efree(eval_name);
532     php_end_ob_buffer(1, 0 TSRMLS_CC);
533     if (ret) {
534       RETURN_TRUE;
535     }
536   }
537   RETURN_FALSE;
538 }
539
540 PHP_FUNCTION(eaccelerator_cache_result) {
541   char* key;
542   int   key_len;
543   char* code;
544   int   code_len;
545   long  ttl = 0;
546   char* eval_name;
547
548   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
549                           "ss|l", &key, &key_len, &code, &code_len, &ttl) == FAILURE) {
550     return;
551   }
552   if ((eaccelerator_content_cache_place != eaccelerator_none) &&
553       eaccelerator_get(key, key_len, return_value, eaccelerator_content_cache_place TSRMLS_CC)) {
554     /*  Return value is cached. Return it. */
555     return;
556   } else {
557     /* Return value is not cached. Generate it and return. */
558     eval_name = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC);
559     if (zend_eval_string(code, return_value, eval_name TSRMLS_CC) == SUCCESS &&
560         eaccelerator_content_cache_place != eaccelerator_none) {
561
562       /* clean garbage */
563       while (EG(garbage_ptr)) {
564         zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]);
565       }
566
567       eaccelerator_put(key, key_len, return_value, ttl, eaccelerator_content_cache_place TSRMLS_CC);
568     }
569     efree(eval_name);
570     return;
571   }
572 }
573
574 #endif
575 #endif
Note: See TracBrowser for help on using the browser.