OSDN Git Service

* Fixed Bug.
[modchxj/mod_chxj.git] / src / mod_chxj.c
old mode 100755 (executable)
new mode 100644 (file)
index fec4515..f71a661
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2009 Atsushi Konno All rights reserved.
+ * Copyright (C) 2005-2011 Atsushi Konno All rights reserved.
  * Copyright (C) 2005 QSDN,Inc. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -175,6 +175,7 @@ static apr_status_t
 chxj_headers_fixup(request_rec *r)
 {
   mod_chxj_config*    dconf; 
+  mod_chxj_req_config *request_conf; 
   chxjconvrule_entry* entryp;
   char*               user_agent;
   device_table*       spec;
@@ -188,9 +189,22 @@ chxj_headers_fixup(request_rec *r)
     return DECLINED;
   }
 
+  request_conf = (mod_chxj_req_config *)chxj_get_module_config(r->request_config, &chxj_module);
+  if (!request_conf) {
+    request_conf = apr_palloc(r->pool, sizeof(mod_chxj_req_config));
+    request_conf->spec = NULL;
+    request_conf->user_agent = NULL;
+    request_conf->f = NULL;
+    chxj_set_module_config(r->request_config, &chxj_module, request_conf);
+  }
   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
 
   user_agent = (char*)apr_table_get(r->headers_in, HTTP_USER_AGENT);
+
+  /*
+   * check and get mobile type.
+   * and request_conf->user_agent , request_conf->spec is set.
+   */
   spec = chxj_specified_device(r, user_agent);
 
   contentType = (char *)apr_table_get(r->headers_in, "Content-Type");
@@ -215,39 +229,42 @@ chxj_headers_fixup(request_rec *r)
   case CHXJ_SPEC_Jhtml:
   case CHXJ_SPEC_Jxhtml:
     entryp = chxj_apply_convrule(r, dconf->convrules);
-    if (! entryp) {
-      DBG(r, "REQ[%X] end %s() (no pattern)", TO_ADDR(r),__func__);
-      return DECLINED;
-    }
-    if (!(entryp->action & CONVRULE_ENGINE_ON_BIT) && !(entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
-      DBG(r, "REQ[%X] end %s() (engine off)", TO_ADDR(r),__func__);
-      return DECLINED;
-    }
-    if (entryp->action & CONVRULE_EMOJI_ONLY_BIT) {
-      DBG(r, "REQ[%X] end %s() (emoji only)", TO_ADDR(r),__func__);
-      return DECLINED;
+    if (dconf->image != CHXJ_IMG_ON) {
+      if (! entryp) {
+        DBG(r, "REQ[%X] end %s() (no pattern)", TO_ADDR(r), __func__);
+        return DECLINED;
+      }
+      if (!(entryp->action & CONVRULE_ENGINE_ON_BIT) && !(entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
+        DBG(r, "REQ[%X] end %s() (engine off)", TO_ADDR(r), __func__);
+        return DECLINED;
+      }
+      if (entryp->action & CONVRULE_EMOJI_ONLY_BIT) {
+        DBG(r, "REQ[%X] end %s() (emoji only)", TO_ADDR(r), __func__);
+        return DECLINED;
+      } 
     } 
-  
     apr_table_setn(r->headers_in, 
                    CHXJ_HTTP_USER_AGENT, 
                    user_agent);
   
-    if (entryp->user_agent)
+    if (entryp && entryp->user_agent)
       apr_table_setn(r->headers_in, 
                      HTTP_USER_AGENT, 
                      entryp->user_agent);
     /*
      * this clear process must do before chxj_convert_input_header function.
      */
-    if ((entryp->action & CONVRULE_COOKIE_ON_BIT) || (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
-      if (r->method_number == M_POST) {
-        if (! apr_table_get(r->headers_in, "X-Chxj-Forward")) {
+    if (entryp) {
+      if ((entryp->action & CONVRULE_COOKIE_ON_BIT) || (entryp->action & CONVRULE_COOKIE_ONLY_BIT)) {
+        if (r->method_number == M_POST) {
+          if (! apr_table_get(r->headers_in, "X-Chxj-Forward")) {
+            s_clear_cookie_header(r, spec);
+          }
+        }
+        else {
           s_clear_cookie_header(r, spec);
         }
       }
-      else {
-        s_clear_cookie_header(r, spec);
-      }
     }
 
     chxj_convert_input_header(r,entryp, spec);
@@ -271,9 +288,9 @@ chxj_headers_fixup(request_rec *r)
 
   if (r->method_number == M_POST) {
     if (! apr_table_get(r->headers_in, "X-Chxj-Forward")) {
-        DBG(r, "REQ[%X] set Input handler old:[%s] proxyreq:[%d] uri:[%s] filename:[%s]", TO_ADDR(r), r->handler, r->proxyreq, r->uri, r->filename);
-        r->proxyreq = PROXYREQ_NONE;
-        r->handler = apr_psprintf(r->pool, "chxj-input-handler");
+      DBG(r, "REQ[%X] set Input handler old:[%s] proxyreq:[%d] uri:[%s] filename:[%s]", TO_ADDR(r), r->handler, r->proxyreq, r->uri, r->filename);
+      r->proxyreq = PROXYREQ_NONE;
+      r->handler = apr_psprintf(r->pool, "chxj-input-handler");
     }
     else {
       char *client_ip = (char *)apr_table_get(r->headers_in, CHXJ_HEADER_ORIG_CLIENT_IP);
@@ -303,7 +320,7 @@ chxj_headers_fixup(request_rec *r)
         if (strcmp(addr, r->connection->remote_ip) == 0) {
           r->connection->remote_ip = apr_pstrdup(r->connection->pool, client_ip);
           /* For mod_cidr_lookup */
-          if (entryp->action & CONVRULE_OVERWRITE_X_CLIENT_TYPE_BIT) {
+          if (entryp && (entryp->action & CONVRULE_OVERWRITE_X_CLIENT_TYPE_BIT)) {
             char *client_type = (char *)apr_table_get(r->headers_in, CHXJ_HEADER_ORIG_CLIENT_TYPE);
             DBG(r, "REQ[%X] Overwrite X-Client-Type to [%s]", TO_ADDR(r), client_type);
             if (client_type) {
@@ -415,6 +432,7 @@ chxj_convert(request_rec *r, const char **src, apr_size_t *len, device_table *sp
   char                *tmp;
   cookie_t            *cookie;
   mod_chxj_config     *dconf; 
+  mod_chxj_req_config *request_conf; 
   chxjconvrule_entry  *entryp;
 
   DBG(r,"REQ[%X] start %s()", TO_ADDR(r),__func__);
@@ -424,6 +442,7 @@ chxj_convert(request_rec *r, const char **src, apr_size_t *len, device_table *sp
   dst  = apr_pstrcat(r->pool, (char *)*src, NULL);
 
   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
+  request_conf = chxj_get_module_config(r->request_config, &chxj_module);
 
 
   entryp = chxj_apply_convrule(r, dconf->convrules);
@@ -457,6 +476,9 @@ chxj_convert(request_rec *r, const char **src, apr_size_t *len, device_table *sp
     /* again */
     spec = chxj_specified_device(r, user_agent);
   }
+  else {
+    spec = request_conf->spec;
+  }
 
   /*
    * save cookie.
@@ -685,7 +707,7 @@ chxj_convert_input_header(request_rec *r,chxjconvrule_entry *entryp, device_tabl
       if (strlen(result) != 0) 
         result = apr_pstrcat(r->pool, result, "&", NULL);
 
-      if (strcasecmp(entryp->encoding, "NONE") != 0) {
+      if (entryp && strcasecmp(entryp->encoding, "NONE") != 0) {
         apr_size_t dlen;
         char *dvalue;
         char *dname;
@@ -907,7 +929,7 @@ chxj_input_convert(
       if (strlen(result) != 0)
         result = apr_pstrcat(pool, result, "&", NULL);
 
-      if (strcasecmp(entryp->encoding, "NONE") != 0 && value && strlen(value)) {
+      if (entryp && strcasecmp(entryp->encoding, "NONE") != 0 && value && strlen(value)) {
         apr_size_t dlen;
         char       *dvalue;
 
@@ -1044,7 +1066,7 @@ pass_data_to_filter(ap_filter_t *f, const char *data,
 static void
 s_add_no_cache_headers(request_rec *r, chxjconvrule_entry  *entryp)
 {
-  if (entryp->action & CONVRULE_NOCACHE_ON_BIT) {
+  if (entryp && (entryp->action & CONVRULE_NOCACHE_ON_BIT)) {
     apr_table_unset(r->headers_out,     "Pragma");
     apr_table_unset(r->err_headers_out, "Pragma");
     apr_table_unset(r->headers_out,     "Expires");
@@ -1123,7 +1145,6 @@ chxj_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
     s_add_no_cache_headers(r, entryp);
     /* must not send body. */
     rv = pass_data_to_filter(f, "", 0);
-    chxj_specified_cleanup(r);
     DBG(f->r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
     return rv;
   }
@@ -1178,15 +1199,13 @@ chxj_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
       s_add_no_cache_headers(r, entryp);
       ap_pass_brigade(f->next, bb);
       DBG(f->r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
-      chxj_specified_cleanup(r);
       return APR_SUCCESS;
     }
   }
   else {
     DBG(r, "REQ[%X] not convert content-type:[(null)]", TO_ADDR(r));
     ap_pass_brigade(f->next, bb);
-    chxj_specified_cleanup(r);
-    DBG(f->r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
+    DBG(f->r, "REQ[%X] end %s()", TO_ADDR(f->r),__func__);
     return APR_SUCCESS;
   }
 
@@ -1304,7 +1323,6 @@ chxj_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
             if (sts != OK) {
               ERR(r, "REQ[%X] qrcode create failed.", TO_ADDR(r));
               chxj_cookie_unlock(r, lock);
-              chxj_specified_cleanup(r);
               DBG(f->r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
               return sts;
             }
@@ -1376,7 +1394,6 @@ chxj_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
                                    (const char *)ctx->buffer, 
                                    (apr_size_t)ctx->len);
         }
-        chxj_specified_cleanup(r);
         DBG(f->r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
         return rv;
       }
@@ -1423,15 +1440,13 @@ chxj_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
         apr_table_setn(r->headers_out, "Content-Length", "0");
         s_add_no_cache_headers(r, entryp);
         rv = pass_data_to_filter(f, (const char *)"", (apr_size_t)0);
-        chxj_specified_cleanup(r);
         return rv;
       }
     }
   }
   apr_brigade_destroy(bb);
 
-  chxj_specified_cleanup(r);
-  DB(f->r, "REQ[%X]nend %s()", TO_ADDR(r),__func__);
+  DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
 
   return APR_SUCCESS;
 }
@@ -1470,6 +1485,7 @@ static apr_status_t
 chxj_input_handler(request_rec *r)
 {
   mod_chxj_config     *dconf;
+  mod_chxj_req_config *request_conf;
   chxjconvrule_entry  *entryp = NULL;
   device_table        *spec   = NULL;
   char                *post_data = NULL;
@@ -1488,12 +1504,18 @@ chxj_input_handler(request_rec *r)
   apr_pool_create(&pool, r->pool);
 
   dconf      = chxj_get_module_config(r->per_dir_config, &chxj_module);
+  request_conf = chxj_get_module_config(r->request_config, &chxj_module);
   user_agent = (char*)apr_table_get(r->headers_in, CHXJ_HTTP_USER_AGENT);
   if (!user_agent) {
     user_agent = (char*)apr_table_get(r->headers_in, HTTP_USER_AGENT);
   }
-  spec       = chxj_specified_device(r, user_agent);
-  entryp     = chxj_apply_convrule(r, dconf->convrules);
+  if (user_agent && request_conf->user_agent && strcmp(user_agent, request_conf->user_agent)) {
+    spec = chxj_specified_device(r, user_agent);
+  }
+  else {
+    spec = request_conf->spec;
+  }
+  entryp = chxj_apply_convrule(r, dconf->convrules);
 
   post_data = apr_pstrdup(pool, "");
   if (ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK) == OK) {
@@ -1545,14 +1567,6 @@ chxj_input_handler(request_rec *r)
   apr_table_unset(r->headers_in, "Content-Length");
   apr_table_setn(r->headers_in, "Content-Length", apr_psprintf(pool, "%" APR_SIZE_T_FMT, post_data_len));
   response = chxj_serf_post(r, pool, url_path, post_data, post_data_len, 1, &res_len, &response_code);
-#if 0
-  DBG(r, "REQ[%X] -------------------------------------------------------", TO_ADDR(r));
-  DBG(r, "REQ[%X] response length:[%" APR_SIZE_T_FMT "]", (unsigned int)(apr_size_t)r, res_len);
-  for (ii=0; ii<res_len/64; ii++) {
-    DBG(r, "REQ[%X] response:[%.*s]", TO_ADDR(r), 64, &response[ii*64]);
-  }
-  DBG(r, "REQ[%X] -------------------------------------------------------", TO_ADDR(r));
-#endif
 
   char *chunked;
   if ((chunked = (char *)apr_table_get(r->headers_out, "Transfer-Encoding")) != NULL) {
@@ -1720,6 +1734,7 @@ chxj_insert_filter(request_rec *r)
   char                *user_agent;
   device_table        *spec;
   mod_chxj_config     *dconf;
+  mod_chxj_req_config *req_conf;
   chxjconvrule_entry  *entryp;
   mod_chxj_ctx        *ctx;
   apr_status_t        rv;
@@ -1728,6 +1743,7 @@ chxj_insert_filter(request_rec *r)
   DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);
 
   dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
+  req_conf = chxj_get_module_config(r->request_config, &chxj_module);
 
   /* we get User-Agent from CHXJ_HTTP_USER_AGENT header if any */
   user_agent = (char *)apr_table_get(r->headers_in, CHXJ_HTTP_USER_AGENT);
@@ -1743,9 +1759,15 @@ chxj_insert_filter(request_rec *r)
     return;
   }
 
-  spec = chxj_specified_device(r, user_agent);
+  if (user_agent && req_conf->user_agent && strcmp(user_agent, req_conf->user_agent)) {
+    spec = chxj_specified_device(r, user_agent);
+  }
+  else {
+    spec = req_conf->spec;
+  }
   entryp = chxj_apply_convrule(r, dconf->convrules);
-  if (!entryp) {
+  if (!entryp && dconf->image != CHXJ_IMG_ON) {
+    DBG(r, "REQ[%X] entryp is NULL and ChxjImageEngine Off", TO_ADDR(r));
     DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
     return;
   }
@@ -1761,12 +1783,11 @@ chxj_insert_filter(request_rec *r)
   ctx->buffer = apr_palloc(ctx->pool, 1);
   ctx->buffer[0] = 0;
 
-  if (!entryp || (!(entryp->action & CONVRULE_ENGINE_ON_BIT) && !(entryp->action & CONVRULE_COOKIE_ONLY_BIT))) {
-    DBG(r,"REQ[%X] EngineOff", TO_ADDR(r));
-    DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
+  if (dconf->image != CHXJ_IMG_ON && (!entryp || (!(entryp->action & CONVRULE_ENGINE_ON_BIT) && !(entryp->action & CONVRULE_COOKIE_ONLY_BIT)))) {
+    DBG(r,"REQ[%X] EngineOff and ChxjImageEngine Off", TO_ADDR(r));
+    DBG(r,"REQ[%X] end %s()", TO_ADDR(r),__func__);
     return;
   }
-
   switch(spec->html_spec_type) {
   case CHXJ_SPEC_Chtml_1_0:
   case CHXJ_SPEC_Chtml_2_0:
@@ -1788,7 +1809,7 @@ chxj_insert_filter(request_rec *r)
 
 
   if (! apr_table_get(r->headers_in, "X-Chxj-Forward")) {
-    ap_add_output_filter("chxj_output_filter", ctx, r, r->connection);
+    req_conf->f = ap_add_output_filter("chxj_output_filter", ctx, r, r->connection);
     DBG(r, "REQ[%X] added Output Filter", TO_ADDR(r));
   }
 
@@ -1796,6 +1817,21 @@ chxj_insert_filter(request_rec *r)
 }
 
 
+void 
+chxj_remove_filter(request_rec *r)
+{
+  mod_chxj_req_config *req_conf;
+
+  DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);
+  req_conf = chxj_get_module_config(r->request_config, &chxj_module);
+  if (req_conf && req_conf->f) {
+    ap_remove_output_filter(req_conf->f);
+    DBG(r, "REQ[%X] REMOVE Output Filter", TO_ADDR(r));
+  }
+  DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
+}
+
+
 /**
  * The hook is registered.
  *