root/eaccelerator/branches/0.9.5/content.c

Revision 228, 21.9 kB (checked in by bart, 2 years ago)

Use some more zval macro's to cleanup things a bit

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