OSDN Git Service

* updated for freebsd
[modchxj/mod_chxj.git] / include / mod_chxj.h
1 /*
2  * Copyright (C) 2005-2011 Atsushi Konno All rights reserved.
3  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 #ifndef __MOD_CHXJ_H__
18 #define __MOD_CHXJ_H__
19
20 #define CHXJ_TRUE    (1)
21 #define CHXJ_FALSE   (0)
22
23 /* #define DEBUG_FD(X,args...) {FILE*fp=fopen("/tmp/error.log", "ab");fprintf(fp, X, ##args);fflush(fp);fclose(fp);} */
24
25 #ifdef UNUSED
26 #elif defined(__GNUC__)
27 # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
28 #elif defined(__LCLINT__)
29 # define UNUSED(x) /*@unused@*/ x
30 #else
31 # define UNUSED(x) x
32 #endif
33
34
35 #include <string.h>
36
37 #include "chxj_apache.h"
38
39 #include "apr_strings.h"
40 #include "apr_buckets.h"
41 #include "apr_lib.h"
42 #include "apr_tables.h"
43 #include "apr_dso.h"
44 #include "apr_general.h"
45 #include "apr_pools.h"
46 #include "apr_hash.h"
47
48 #if defined(AP_NEED_SET_MUTEX_PERMS)
49 #  include "unixd.h"
50 #endif
51 #if !defined(AP_NEED_SET_MUTEX_PERMS)
52 #  if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
53 #    define AP_NEED_SET_MUTEX_PERMS
54 #  endif
55 #endif
56
57 #define STRCASEEQ(a,b,c,d) \
58   ((((a) == *(d))|| ((b) == *(d))) && strcasecmp((c),(d)) == 0)
59 #define STRNCASEEQ(a,b,c,d,e) \
60   ((((a) == *(d))|| ((b) == *(d))) && strncasecmp((c),(d),(e)) == 0)
61
62 #define CHXJ_QUERY_STRING_PARAM_PREFIX "_chxj_qs_"
63 #define CHXJ_QUERY_STRING_PARAM_PREFIX_ENC "%5Fchxj%5Fqs%5F"
64
65
66 #include "qs_ignore_sp.h"
67 #include "qs_log.h"
68 #include "qs_malloc.h"
69 #include "qs_parse_attr.h"
70 #include "qs_parse_file.h"
71 #include "qs_parse_string.h"
72 #include "qs_parse_tag.h"
73
74 #if defined(HAVE_AP_REGEX_H) && HAVE_AP_REGEX_H == 1
75 #  include "ap_regex.h"
76 #else
77 #  include "pcreposix.h"
78 #  include "pcre.h"
79 #  if !defined(AP_REG_ASSERT)
80 #    define AP_REG_ASSERT   REG_ASSERT
81 #  endif
82 #  if !defined(AP_REG_BADBR)
83 #    define AP_REG_BADBR    REG_BADBR
84 #  endif
85 #  if !defined(AP_REG_BADPAT)
86 #    define AP_REG_BADPAT   REG_BADPAT
87 #  endif
88 #  if !defined(AP_REG_BADRPT)
89 #    define AP_REG_BADRPT   REG_BADRPT
90 #  endif
91 #  if !defined(AP_REG_EBRACE)
92 #    define AP_REG_EBRACE   REG_EBRACE
93 #  endif
94 #  if !defined(AP_REG_EBRACK)
95 #    define AP_REG_EBRACK   REG_EBRACK
96 #  endif
97 #  if !defined(AP_REG_ECOLLATE)
98 #    define AP_REG_ECOLLATE REG_ECOLLATE
99 #  endif
100 #  if !defined(AP_REG_ECTYPE)
101 #    define AP_REG_ECTYPE   REG_ECTYPE
102 #  endif
103 #  if !defined(AP_REG_EESCAPE)
104 #    define AP_REG_EESCAPE  REG_EESCAPE
105 #  endif
106 #  if !defined(AP_REG_EMPTY)
107 #    define AP_REG_EMPTY    REG_EMPTY
108 #  endif
109 #  if !defined(AP_REG_EPAREN)
110 #    define AP_REG_EPAREN   REG_EPAREN
111 #  endif
112 #  if !defined(AP_REG_ERANGE)
113 #    define AP_REG_ERANGE   REG_ERANGE
114 #  endif
115 #  if !defined(AP_REG_ESIZE)
116 #    define AP_REG_ESIZE    REG_ESIZE
117 #  endif
118 #  if !defined(AP_REG_ESPACE)
119 #    define AP_REG_ESPACE   REG_ESPACE
120 #  endif
121 #  if !defined(AP_REG_ESUBREG)
122 #    define AP_REG_ESUBREG  REG_ESUBREG
123 #  endif
124 #  if !defined(AP_REG_INVARG)
125 #    define AP_REG_INVARG   REG_INVARG
126 #  endif
127 #  if !defined(AP_REG_NOMATCH)
128 #    define AP_REG_NOMATCH  REG_NOMATCH
129 #  endif
130
131 #  if !defined(AP_REG_ICASE)
132 #    define AP_REG_ICASE    REG_ICASE
133 #  endif
134 #  if !defined(AP_REG_NEWLINE)
135 #    define AP_REG_NEWLINE  REG_NEWLINE
136 #  endif
137 #  if !defined(AP_REG_NOTBOL)
138 #    define AP_REG_NOTBOL   REG_NOTBOL
139 #  endif
140 #  if !defined(AP_REG_NOTEOL)
141 #    define AP_REG_NOTEOL   REG_NOTEOL
142 #  endif
143
144 #  if !defined(AP_REG_EXTENDED)
145 #    define AP_REG_EXTENDED REG_EXTENDED
146 #  endif
147 #  if !defined(AP_REG_NOSUB)
148 #    define AP_REG_NOSUB    REG_NOSUB
149 #  endif
150
151 #  define ap_regex_t      regex_t
152 #  define ap_regmatch_t   regmatch_t
153 #endif
154
155
156
157
158 #ifdef HAVE_APR_GLOBAL_MUTEX_H
159 #  include "apr_global_mutex.h"
160 #endif
161
162 #ifdef HAVE_APR_SHM_H
163 #  include "apr_shm.h"
164 #endif
165
166
167 typedef struct imode_emoji_t imode_emoji_t;
168
169 struct imode_emoji_t {
170   char  hex1byte;
171   char  hex2byte;
172   char* string;
173   char* color;
174   char *description;
175 };
176
177 typedef struct ezweb_emoji_t ezweb_emoji_t;
178
179 struct ezweb_emoji_t {
180   char* typeA;
181   char* typeB;
182   char* typeC;
183   char* typeD;
184 };
185
186 typedef struct jphone_emoji_t jphone_emoji_t;
187
188 struct jphone_emoji_t {
189   char* string;
190 };
191
192 typedef struct iphone_emoji_t iphone_emoji_t;
193
194 struct iphone_emoji_t {
195   char* string;
196 };
197
198 typedef struct android_emoji_t android_emoji_t;
199
200 struct android_emoji_t {
201   char* string;
202 };
203
204 typedef struct emoji_t emoji_t;
205
206 struct emoji_t {
207   struct emoji_t*  next;
208   int              no;
209   imode_emoji_t*   imode;
210   ezweb_emoji_t*   ezweb;
211   jphone_emoji_t*  jphone;
212   iphone_emoji_t*  iphone;
213   android_emoji_t*  android;
214 };
215
216 typedef struct chxjconvrule_entry chxjconvrule_entry;
217
218 struct chxjconvrule_entry {
219   char         *pattern;
220   ap_regex_t   *regexp;
221   int          flags;
222   int          action;
223   char         *encoding;
224   int          pc_flag;
225   char         *user_agent;
226 };
227
228 typedef struct tag_handler tag_handler;
229
230 struct tag_handler {
231   char* (*start_tag_handler)(void* doc, Node* node); 
232   char* (*end_tag_handler)(void* doc, Node* node); 
233 };
234
235 #include "chxj_specified_device.h"
236
237 typedef struct {
238   spec_type    type; 
239   tag_handler* handler;
240 } tag_handlers;
241
242 typedef enum {
243   tagHTML = 0,
244   tagMETA,  
245   tagTEXTAREA,
246   tagP,
247   tagPRE,
248   tagUL,
249   tagLI,
250   tagOL,
251   tagH1,
252   tagH2,
253   tagH3,
254   tagH4,
255   tagH5,
256   tagH6,
257   tagHEAD,
258   tagTITLE,
259   tagBASE,
260   tagBODY,
261   tagA,
262   tagBR,
263   tagTABLE,
264   tagTR,
265   tagTD,
266   tagTBODY,
267   tagFONT,
268   tagFORM,
269   tagINPUT,
270   tagCENTER,
271   tagHR,
272   tagIMG,
273   tagSELECT,
274   tagOPTION,
275   tagDIV,
276   tagCHXJIF,  
277   tagCHXJRAW,  
278   tagNOBR,  
279   tagSMALL,  
280   tagSTYLE,  
281   tagSPAN,  
282   tagTEXT,  
283   tagTH,  
284   tagB,
285   tagFIELDSET,
286   tagDT,
287   tagLEGEND,
288   tagLABEL,
289   tagBLOCKQUOTE,
290   tagDIR,
291   tagDL,
292   tagDD,
293   tagMENU,
294   tagPLAINTEXT,
295   tagBLINK,
296   tagMARQUEE,
297   tagLINK,
298   tagNLMARK,      /* New Line Code */
299   tagOBJECT,
300   tagPARAM,
301   tagCAPTION,
302 } tag_type;
303
304 typedef struct mod_chxj_config mod_chxj_config;
305 typedef struct mod_chxj_req_config_t mod_chxj_req_config;
306
307 #if defined(USE_MYSQL_COOKIE)
308 #  include "chxj_mysql.h"
309 #endif
310 #if defined(USE_MEMCACHE_COOKIE)
311 #  include "chxj_memcache.h"
312 #endif
313
314 /* cookie store type */
315 #define CHXJ_COOKIE_STORE_TYPE_DBM      "dbm"
316 #define CHXJ_COOKIE_STORE_TYPE_MYSQL    "mysql"
317 #define CHXJ_COOKIE_STORE_TYPE_MEMCACHE "memcache"
318 typedef enum {
319   COOKIE_STORE_TYPE_NONE     = 0,
320   COOKIE_STORE_TYPE_DBM      = 1,
321   COOKIE_STORE_TYPE_MYSQL    = 2,
322   COOKIE_STORE_TYPE_MEMCACHE = 3, 
323 } cookie_store_type_t;
324
325 /* new line type */
326 #define CHXJ_NEW_LINE_TYPE_CRLF         "crlf"
327 #define CHXJ_NEW_LINE_TYPE_LF           "lf"
328 #define CHXJ_NEW_LINE_TYPE_CR           "cr"
329 #define CHXJ_NEW_LINE_TYPE_NONE         "none"
330 typedef enum {
331   NLTYPE_NIL  = 0,
332   NLTYPE_CRLF = 1,
333   NLTYPE_LF   = 2,
334   NLTYPE_CR   = 3,
335   NLTYPE_NONE = 4,
336 } chxj_new_line_type_t;
337 #define IS_NLTYPE_CRLF(X)   ((X)->new_line_type == NLTYPE_CRLF)
338 #define IS_NLTYPE_LF(X)     ((X)->new_line_type == NLTYPE_LF)
339 #define IS_NLTYPE_CR(X)     ((X)->new_line_type == NLTYPE_CR)
340 #define IS_NLTYPE_NONE(X)   ((X)->new_line_type == NLTYPE_NONE)
341 #define TO_NLCODE(X)        (IS_NLTYPE_CRLF(X) ? "\r\n" : \
342                              IS_NLTYPE_LF(X)   ? "\n"   : \
343                              IS_NLTYPE_CR(X)   ? "\r"   : \
344                              IS_NLTYPE_NONE(X) ? ""     : "\r\n")
345
346 struct mod_chxj_config {
347   int                   image;
348
349   char                  *device_data_file;
350   char                  *emoji_data_file;
351
352   char                  *image_cache_dir;
353   char                  *image_copyright;
354   unsigned long         image_cache_limit;
355   device_table_list     *devices;
356   emoji_t               *emoji;
357   emoji_t               *emoji_tail;
358   int                   imode_emoji_color;
359   char                  *server_side_encoding;
360
361   char                  *dir; /* for LOG */
362
363   apr_array_header_t    *convrules;
364
365   char                  *cookie_db_dir;
366   long                  cookie_timeout;
367   cookie_store_type_t   cookie_store_type;
368   int                   cookie_lazy_mode;
369   char                  *cookie_dbm_type;
370   
371   int                   detect_device_type; /* XML|TSV */
372
373 #if defined(USE_MYSQL_COOKIE)
374   mysql_t               mysql;
375 #endif
376 #if defined(USE_MEMCACHE_COOKIE)
377   memcache_t            memcache;
378 #endif
379   char                  *forward_url_base;  /* use input filter */
380   char                  *forward_server_ip; /* use input filter */
381
382   char                  *allowed_cookie_domain; /* default is null */
383
384   chxj_new_line_type_t  new_line_type;
385
386   char                  *post_log;              /* post log environment name. */
387   
388   apr_array_header_t    *device_keys;           /* TSV header array */
389   apr_hash_t            *device_hash;           /* TSV device data hash table */
390
391   int                   image_rewrite;
392   char                  *image_rewrite_url;
393   int                   image_rewrite_mode;
394
395   int                   use_emoji_image;
396   char                  *emoji_image_url;
397
398
399   int                   use_google_analytics;
400   char                  *google_analytics_account;
401   char                  *google_analytics_target;   /* i.e. /ga.pl */
402   char                  *google_analytics_debug;    /* debug filename */
403 };
404
405 struct mod_chxj_req_config_t {
406   char               *user_agent;
407   device_table       *spec;
408   ap_filter_t        *f;
409   chxjconvrule_entry *entryp;
410 };
411
412 #define IS_COOKIE_STORE_DBM(X)      ((X) == COOKIE_STORE_TYPE_DBM)
413 #define IS_COOKIE_STORE_MYSQL(X)    ((X) == COOKIE_STORE_TYPE_MYSQL)
414 #define IS_COOKIE_STORE_MEMCACHE(X) ((X) == COOKIE_STORE_TYPE_MEMCACHE)
415 #define IS_COOKIE_STORE_NONE(X)     ((X) == COOKIE_STORE_TYPE_NONE)
416
417 #define COOKIE_LAZY_ON                (2)
418 #define COOKIE_LAZY_OFF               (1)
419 #define IS_COOKIE_LAZY(X)             ((X)->cookie_lazy_mode == COOKIE_LAZY_ON)
420
421
422 #define CONVRULE_ENGINE_ON_BIT        (0x00000001)
423 #define CONVRULE_ENGINE_OFF_BIT       (0x00000002)
424 #define CONVRULE_COOKIE_ON_BIT        (0x00000004)
425 #define CONVRULE_CSS_ON_BIT           (0x10000000)
426 #define CONVRULE_Z2H_ON_BIT           (0x00000008)
427 #define CONVRULE_Z2H_OFF_BIT          (0x00000010)
428 #define CONVRULE_Z2H_ALPHA_ON_BIT     (0x00000020)
429 #define CONVRULE_Z2H_ALPHA_OFF_BIT    (0x00000040)
430 #define CONVRULE_Z2H_NUM_ON_BIT       (0x00000080)
431 #define CONVRULE_Z2H_NUM_OFF_BIT      (0x00000100)
432 #define CONVRULE_QSCONV_OFF_BIT       (0x00000200)
433 #define CONVRULE_JRCONV_OFF_BIT       (0x00000400)
434 #define CONVRULE_NOCACHE_ON_BIT       (0x00000800)
435 #define CONVRULE_EMOJI_ONLY_BIT       (0x00001000)
436 #define CONVRULE_ENVINFO_ONLY_BIT     (0x00002000)
437 #define CONVRULE_COOKIE_ONLY_BIT      (0x00004000)
438 #define CONVRULE_OVERWRITE_X_CLIENT_TYPE_BIT (0x00008000)
439
440 #define CONVRULE_ENGINE_ON_CMD        "EngineOn"
441 #define CONVRULE_ENGINE_OFF_CMD       "EngineOff"
442 #define CONVRULE_COOKIE_ON_CMD        "CookieOn"
443 #define CONVRULE_COOKIE_OFF_CMD       "CookieOff"
444 #define CONVRULE_CSS_ON_CMD           "CssOn"
445 #define CONVRULE_CSS_OFF_CMD          "CssOff"
446 #define CONVRULE_Z2H_ON_CMD           "Z2hOn"
447 #define CONVRULE_Z2H_OFF_CMD          "Z2hOff"
448 #define CONVRULE_Z2H_ALPHA_ON_CMD     "Z2hAlphaOn"
449 #define CONVRULE_Z2H_ALPHA_OFF_CMD    "Z2hAlphaOff"
450 #define CONVRULE_Z2H_NUM_ON_CMD       "Z2hNumOn"
451 #define CONVRULE_Z2H_NUM_OFF_CMD      "Z2hNumOff"
452 #define CONVRULE_Z2H_ALL_ON_CMD       "Z2hAllOn"
453 #define CONVRULE_Z2H_ALL_OFF_CMD      "Z2hAllOff"
454 #define CONVRULE_QSCONV_OFF_CMD       "QSConvOff"
455 #define CONVRULE_JRCONV_OFF_CMD       "JRConvOff"
456 #define CONVRULE_NOCACHE_ON_CMD       "NoCacheOn"
457 #define CONVRULE_EMOJI_ONLY_CMD       "EmojiOnly"
458 #define CONVRULE_ENVINFO_ONLY_CMD     "EnvInfoOnly"
459 #define CONVRULE_COOKIE_ONLY_CMD      "CookieOnly"
460 #define CONVRULE_OVERWRITE_X_CLIENT_TYPE_CMD "OverwriteXClientType"
461
462
463 #define CONVRULE_FLAG_NOTMATCH        (0x00000001)
464
465 #define CONVRULE_PC_FLAG_ON_CMD       "PC"
466
467 #define CONVRULE_PC_FLAG_ON_BIT       (0x00000001)
468 #define CONVRULE_PC_FLAG_OFF_BIT      (0x00000002)
469
470
471 #define IS_CSS_ON(X)                  ((X)->action & CONVRULE_CSS_ON_BIT)
472
473 typedef struct {
474   apr_global_mutex_t* cookie_db_lock;
475 } mod_chxj_global_config;
476
477 typedef struct {
478   apr_size_t len;
479   chxjconvrule_entry  *entryp;
480   device_table        *spec;
481
482   apr_bucket_brigade *bb;
483   apr_pool_t *pool;
484
485   char* buffer;
486 } mod_chxj_ctx;
487
488 #include "chxj_tag_util.h"
489
490 #define CHXJ_MOD_CONFIG_KEY   "chxj_module_key"
491
492 #define HTTP_USER_AGENT       "User-Agent"
493 #define HTTP_HOST             "Host"
494 #define CHXJ_HTTP_USER_AGENT  "CHXJ_HTTP_USER_AGENT"
495 #define CHXJ_HEADER_ORIG_CLIENT_IP "X-Chxj-Orig-Client-Ip"
496 #define CHXJ_HEADER_ORIG_CLIENT_TYPE "X-Chxj-Orig-Client-Type"
497
498 module AP_MODULE_DECLARE_DATA chxj_module;
499
500 #define CHXJ_IMG_ON     (2)
501 #define CHXJ_IMG_OFF    (1)
502 #define CHXJ_IMG_NONE   (0)
503
504 #define CHXJ_IMODE_EMOJI_COLOR_ON   (3)
505 #define CHXJ_IMODE_EMOJI_COLOR_AUTO (2)
506 #define CHXJ_IMODE_EMOJI_COLOR_OFF  (1)
507 #define CHXJ_IMODE_EMOJI_COLOR_NONE (0)
508
509 #define CHXJ_ADD_DETECT_DEVICE_TYPE_TSV     (1)
510 #define CHXJ_ADD_DETECT_DEVICE_TYPE_NONE    (0)
511
512 #define CHXJ_PROVIDER_UNKNOWN  (0)
513 #define CHXJ_PROVIDER_DOCOMO   (1)
514 #define CHXJ_PROVIDER_AU       (2)
515 #define CHXJ_PROVIDER_SOFTBANK (3)
516
517 #define CHXJ_IMG_REWRITE_ON     (2)
518 #define CHXJ_IMG_REWRITE_OFF    (1)
519 #define CHXJ_IMG_REWRITE_NONE   (0)
520
521 #define CHXJ_IMG_REWRITE_MODE_ALL  (3)
522 #define CHXJ_IMG_REWRITE_MODE_USER (2)
523 #define CHXJ_IMG_REWRITE_MODE_TAG  (1)
524 #define CHXJ_IMG_REWRITE_MODE_NONE (0)
525
526 #define CHXJ_IMG_REWRITE_URL_STRING             "_x-chxj_imgrewrite=on"
527 #define CHXJ_IMG_X_HTTP_IMAGE_FILENAME          "X-Chxj-Image-Filename"
528 #define CHXJ_IMG_X_HTTP_IMAGE_TYPE              "X-Chxj-Image-Type"
529
530 #define DBG(X,args...)  chxj_log_rerror(APLOG_MARK,APLOG_DEBUG,0,(request_rec*)(X),##args)
531 #define SDBG(X,Y)       chxj_log_error(APLOG_MARK,APLOG_DEBUG,0,(X),(Y))
532 #define PDBG(X,args...) chxj_log_perror(APLOG_MARK,APLOG_DEBUG,0,(apr_pool_t *)(X),##args)
533 #define ERR(X,args...)  chxj_log_rerror(APLOG_MARK,APLOG_ERR,0,(X), ##args)
534 #define SERR(X,args...) chxj_log_error(APLOG_MARK,APLOG_ERR,0,(X),##args)
535 #define PERR(X,args...) chxj_log_perror(APLOG_MARK,APLOG_ERR,0,(apr_pool_t *)(X),##args)
536 #define WRN(rec,format,args...)  chxj_log_rerror(APLOG_MARK,APLOG_WARNING,0,(rec),(format), ##args)
537
538 extern tag_handlers chxj_tag_handlers[];
539 extern tag_handler  chtml10_handler[];
540 extern tag_handler  chtml20_handler[];
541 extern tag_handler  chtml30_handler[];
542 extern tag_handler  chtml40_handler[];
543 extern tag_handler  chtml50_handler[];
544 extern tag_handler  ixhtml10_handler[];
545 extern tag_handler  xhtml_handler[];
546 extern tag_handler  hdml_handler[];
547 extern tag_handler  jhtml_handler[];
548 extern tag_handler  jxhtml_handler[];
549 extern tag_handler  iphone_handler[];
550 extern tag_handler  android_handler[];
551
552 extern char* chxj_node_convert( 
553   device_table *spec,
554   request_rec  *r,
555   void         *pdoc,
556   Doc          *doc,
557   Node         *node,
558   int          indent
559 );
560 extern char *chxj_node_convert_chxjif_only(
561   request_rec  *r,
562   device_table *spec,
563   const char   *src,
564   apr_size_t   *len
565 );
566 extern void chxj_remove_filter(request_rec *r);
567 extern mod_chxj_req_config *chxj_get_req_config(request_rec *r);
568
569 #define IMAGE_CACHE_LIMIT_FMT_LEN  (20)
570
571
572 #if HAVE_MALLOC == 0
573 extern void *rpl_malloc(size_t n);
574 #endif
575
576
577 #define TO_ADDR(X) ((unsigned int)(apr_size_t)(X))
578 #define ADJUST_WIDTH_FOR_ANDROID (40)
579
580 #if APR_MAJOR_VERSION < 1
581   #ifndef APR_FOPEN_READ
582     #define APR_FOPEN_READ APR_READ
583   #endif
584   #ifndef APR_FOPEN_BUFFERED
585     #define APR_FOPEN_BUFFERED APR_BUFFERED
586   #endif
587   #ifndef APR_FOPEN_BINARY
588     #define APR_FOPEN_BINARY APR_BINARY
589   #endif
590   #ifndef APR_FOPEN_CREATE
591     #define APR_FOPEN_CREATE APR_CREATE
592   #endif
593   #ifndef APR_FOPEN_WRITE
594     #define APR_FOPEN_WRITE APR_WRITE
595   #endif
596 #endif
597
598 #endif
599 /*
600  * vim:ts=2 et
601  */