OSDN Git Service

* version up.
[modchxj/mod_chxj.git] / src / chxj_specified_device.c
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 #include "mod_chxj.h"
18 #include "chxj_str_util.h"
19 #include "chxj_add_device_env.h"
20
21 static device_table  UNKNOWN_DEVICE      = {
22   .next = NULL,
23   .provider  = CHXJ_PROVIDER_UNKNOWN,
24   .device_id = "",
25   .device_name = "UNKNOWN",
26   .html_spec_type = CHXJ_SPEC_UNKNOWN,
27   .width = 640,
28   .heigh = 480,
29   /*--------------------------------------------------------------------------*/
30   /* Walll Paper Size                                                         */
31   /*--------------------------------------------------------------------------*/
32   .wp_width = 640,
33   .wp_heigh = 480,
34   /*--------------------------------------------------------------------------*/
35   /* Cache Size                                                               */
36   /*--------------------------------------------------------------------------*/
37   .cache    = 10000000,
38   /*--------------------------------------------------------------------------*/
39   /* Correspondence image format                                              */
40   /* 1: It is possible to display it.                                         */
41   /* 0: It is not possible to display it.                                     */
42   /*--------------------------------------------------------------------------*/
43   .available_gif = 1,
44   .available_jpeg = 1,
45   .available_png = 1,
46   .available_bmp2 = 1,
47   .available_bmp4 = 1,
48   .dpi_width = 96,
49   .dpi_heigh = 96,
50   /*--------------------------------------------------------------------------*/
51   /* Color number type                                                        */
52   /* 2       : 2        Colors                                                */
53   /* 4       : 4        Colors                                                */
54   /* 256     : 256      Colors                                                */
55   /* 4096    : 4096     Colors                                                */
56   /* 65536   : 65536    Colors                                                */
57   /* 262144  : 262144   Colors                                                */
58   /* 15680000: 15680000 over colors                                           */
59   /*--------------------------------------------------------------------------*/
60   .color = 15680000,
61   .emoji_type = NULL,
62   .output_encoding = "Shift_JIS",
63 };
64 /* spec cache */
65 static device_table *s_get_device_data(request_rec *r, const char *device_id, device_table_list *dtl);
66 static device_table *s_specified_device_from_xml(request_rec *r, mod_chxj_config * conf, const char *user_agent);
67 static device_table *s_specified_device_from_tsv(request_rec *r,device_table *spec,const char *user_agent);
68
69
70 int
71 get_boolean_value(request_rec *r,const char *val){
72   switch(*val) {
73     case '0':
74     case 'f':
75     case 'F':
76     case 'n':
77     case 'N':
78       return 0;
79       break;
80     case '1':
81     case 't':
82     case 'T':
83     case 'y':
84     case 'Y':
85       return 1;
86       break;
87   }
88   return -1;
89 }
90
91 /**
92  * The device is specified from UserAgent. 
93  * @param r Request_rec is appointed.
94  * @param userAgent UserAgent is appointed here,
95  * @return The style which corresponds is returned.
96  */
97 device_table *
98 chxj_specified_device(request_rec *r, const char *user_agent) 
99 {
100   device_table         *dt = &UNKNOWN_DEVICE;
101   mod_chxj_config      *conf;
102   mod_chxj_req_config  *request_conf;
103   
104   DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);
105
106   request_conf = (mod_chxj_req_config *)chxj_get_module_config(r->request_config, &chxj_module);
107   if (user_agent) {
108     request_conf->user_agent = apr_pstrdup(r->pool, user_agent);
109   }
110   else {
111     request_conf->user_agent = "";
112   }
113   
114   conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
115   if(! user_agent){
116     request_conf->spec = dt;
117     DBG(r, "REQ[%X] end %s() %d", TO_ADDR(r), __func__,conf->detect_device_type);
118     return dt;
119   }
120   
121   dt = s_specified_device_from_xml(r,conf, user_agent);
122
123   if (conf->detect_device_type == CHXJ_ADD_DETECT_DEVICE_TYPE_TSV ){
124     s_specified_device_from_tsv(r,dt,user_agent);
125   }
126   /* save to spec cache */
127   request_conf->spec = dt;
128   
129   DBG(r, "REQ[%X] end %s() %d",TO_ADDR(r), __func__,conf->detect_device_type);
130   return dt;
131 }
132
133 /**
134  * The device is specified from UserAgent. 
135  * @param r Request_rec is appointed.
136  * @param userAgent UserAgent is appointed here,
137  * @return The style which corresponds is returned.
138  */
139 static device_table *
140 s_specified_device_from_xml(request_rec *r, mod_chxj_config * conf, const char *user_agent) 
141 {
142   ap_regmatch_t        match[10];
143   device_table         *returnType = &UNKNOWN_DEVICE;
144   device_table_list    *dtl;
145   device_table         *dt;
146   char                 *device_id;
147
148   DBG(r, "REQ[%X] start %s()", TO_ADDR(r),__func__);
149   if (! user_agent) {
150     DBG(r, "REQ[%X] end %s() (user_agent is not set)", TO_ADDR(r),__func__);
151     return returnType;
152   }
153             
154
155
156   if (! conf->devices) {
157     ERR(r, "REQ[%X] device_data.xml load failure", TO_ADDR(r));
158     DBG(r, "REQ[%X] end %s()", TO_ADDR(r), __func__);
159     return returnType;
160   }
161
162   for (dtl = conf->devices; dtl; dtl = dtl->next) {
163     if (! dtl->pattern) {
164       continue;
165     }
166
167     /* DBG(r, "pattern is [%s]", dtl->pattern); */
168     if (! dtl->regexp) {
169       ERR(r,"REQ[%X] compile failed.", TO_ADDR(r));
170       DBG(r, "REQ[%X] %s()", TO_ADDR(r),__func__);
171       return returnType;
172     }
173
174     if (ap_regexec((const ap_regex_t *)dtl->regexp, user_agent, (apr_size_t)dtl->regexp->re_nsub + 1, match, 0) == 0) {
175       device_id = ap_pregsub(r->pool, "$1", user_agent, dtl->regexp->re_nsub + 1, match);
176       DBG(r, "REQ[%X] device_id:[%s]", TO_ADDR(r), device_id);
177
178       dt = s_get_device_data(r, device_id, dtl);
179       if (! dt) {
180         dt = dtl->tail;
181         if (dt){
182           if (conf->detect_device_type > CHXJ_ADD_DETECT_DEVICE_TYPE_NONE ){
183             dt->device_id = device_id;
184           }
185           DBG(r,"REQ[%X] end %s() (Not Found) use [%s]", TO_ADDR(r), __func__, dt->device_id);
186           return dt;
187         }
188       }
189       DBG(r,"REQ[%X] end %s() (Found) use [%s]", TO_ADDR(r), __func__, dt->device_id);
190       return dt;
191     }
192   }
193
194   DBG(r,"REQ[%X] end %s()", TO_ADDR(r), __func__);
195
196   return returnType;
197 }
198
199
200 #include <stdlib.h>
201 static int 
202 s_compar(const void *a, const void *b)
203 {
204   device_table *aa = *(device_table **)a;
205   device_table *bb = *(device_table **)b;
206
207   /*
208    * Don't use strcasecmp for LOAD!!
209    */
210   return strcmp(aa->device_id, bb->device_id);
211 }
212
213
214 static device_table *
215 s_get_device_data(request_rec *r, const char *device_id, device_table_list *dtl)
216 {
217   device_table dt;
218   device_table *_dt;
219   dt.device_id = device_id;
220   _dt = &dt;
221   device_table **ret = bsearch(&_dt, dtl->sort_table, dtl->table_count, sizeof(device_table *), s_compar);
222   if (ret && *ret) {
223     return *ret;
224   }
225   return NULL;
226 }
227
228
229 /**
230  * The device is specified from TSV file. 
231  * @param r Request_rec is appointed.
232  * @param userAgent UserAgent is appointed here,
233  * @return The style which corresponds is returned.
234  */
235 static device_table *
236 s_specified_device_from_tsv(request_rec *r,device_table *spec,const char *user_agent)
237 {
238   if(spec->device_id == NULL){
239     return spec;
240   }
241   
242   DBG(r, "REQ[%X] start %s() device_id:[%s]", TO_ADDR(r), __func__,spec->device_id);
243   mod_chxj_config      *conf;
244   
245   conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
246   
247   if(conf->device_hash == NULL){
248     DBG(r, "REQ[%X] end %s()", TO_ADDR(r),__func__);
249     return spec;
250   }
251   char *key = apr_psprintf(r->pool,"%d.%s",spec->provider,spec->device_id);
252   
253   apr_table_t *ht = apr_hash_get(conf->device_hash,key,APR_HASH_KEY_STRING);
254   
255   if(ht != NULL){
256     DBG(r, "REQ[%X] found ! %s() %s", TO_ADDR(r), __func__,key);
257     int i;
258     for ( i=0; i< conf->device_keys->nelts; i++){
259       const char *k = ((const char**)conf->device_keys->elts)[i];
260       char *val = (char *)apr_table_get(ht,k);
261       if(val == NULL){
262         continue;
263       }
264       DBG(r, "REQ[%X] start chxj_specified_device_from_tsv() [%s] = [%s]:[%s]",TO_ADDR(r),spec->device_id,k,val);
265       if (STRCASEEQ('d','D',"device_name",k)){
266         spec->device_name = apr_pstrdup(r->pool,val);
267       }
268       if (STRCASEEQ('w','W',"width",k)){
269         if(chxj_chk_numeric(val) == 0){
270           spec->width = chxj_atoi(val);
271         }
272       }
273       else if (STRCASEEQ('h','H',"heigh",k)){
274         if(chxj_chk_numeric(val) == 0){
275           spec->heigh = chxj_atoi(val);
276         }
277       }
278       else if (STRCASEEQ('h','H',"height",k)){
279         if(chxj_chk_numeric(val) == 0){
280           spec->heigh = chxj_atoi(val);
281         }
282       }
283       else if (STRCASEEQ('w','W',"wp_width",k)){
284         if(chxj_chk_numeric(val) == 0){
285           spec->wp_width = chxj_atoi(val);
286         }
287       }
288       else if (STRCASEEQ('w','W',"wp_heigh",k)){
289         if(chxj_chk_numeric(val) == 0){
290           spec->wp_heigh = chxj_atoi(val);
291         }
292       }
293       else if (STRCASEEQ('w','W',"wp_height",k)){
294         if(chxj_chk_numeric(val) == 0){
295           spec->wp_heigh = chxj_atoi(val);
296         }
297       }
298       else if (STRCASEEQ('c','C',"cache",k)){
299         if(chxj_chk_numeric(val) == 0){
300           spec->cache = chxj_atoi(val);
301         }
302       }
303       else if (STRCASEEQ('g','G',"gif",k)){
304         int tmp = get_boolean_value(r,val);
305         if(tmp > -1 ){
306             spec->available_gif = tmp;
307         }
308       }
309       else if (STRCASEEQ('j','J',"jpeg",k)){
310         int tmp = get_boolean_value(r,val);
311         if(tmp > -1 ){
312             spec->available_jpeg = tmp;
313         }
314       }
315       else if (STRCASEEQ('p','P',"png",k)){
316         int tmp = get_boolean_value(r,val);
317         if(tmp > -1 ){
318           spec->available_png = tmp;
319         }
320       }
321       else if (STRCASEEQ('b','B',"bmp2",k)){
322         int tmp = get_boolean_value(r,val);
323         if(tmp > -1 ){
324           spec->available_bmp2 = tmp;
325         }
326       }
327       else if (STRCASEEQ('b','B',"bmp4",k)){
328         int tmp = get_boolean_value(r,val);
329         if(tmp > -1 ){
330           spec->available_bmp4 = tmp;
331         }
332       }
333       else if (STRCASEEQ('c','C',"color",k)){
334         if(chxj_chk_numeric(val) == 0){
335           spec->color = chxj_atoi(val);
336         }
337       }
338       else if (STRCASEEQ('e','E',"emoji_type",k)){
339         spec->emoji_type = apr_pstrdup(r->pool,val);
340       }
341       else if (STRCASEEQ('h','H',"html_spec_type",k)){
342         if (STRCASEEQ('x','X',"xhtml_mobile_1_0",val)) {
343           spec->html_spec_type = CHXJ_SPEC_XHtml_Mobile_1_0;
344         }
345         else if (STRCASEEQ('c','C',"chtml_1_0",val)) {
346           spec->html_spec_type = CHXJ_SPEC_Chtml_1_0;
347         }
348         else if (STRCASEEQ('c','C',"chtml_2_0",val)) {
349           spec->html_spec_type = CHXJ_SPEC_Chtml_2_0;
350         }
351         else if (STRCASEEQ('c','C',"chtml_3_0",val)) {
352           spec->html_spec_type = CHXJ_SPEC_Chtml_3_0;
353         }
354         else if (STRCASEEQ('c','C',"chtml_4_0",val)) {
355           spec->html_spec_type = CHXJ_SPEC_Chtml_4_0;
356         }
357         else if (STRCASEEQ('c','C',"chtml_5_0",val)) {
358           spec->html_spec_type = CHXJ_SPEC_Chtml_5_0;
359         }
360         else if (STRCASEEQ('c','C',"chtml_6_0",val)) {
361           spec->html_spec_type = CHXJ_SPEC_Chtml_6_0;
362         }
363         else if (STRCASEEQ('c','C',"chtml_7_0",val)) {
364           spec->html_spec_type = CHXJ_SPEC_Chtml_7_0;
365         }
366         else if (STRCASEEQ('h','H',"hdml",val)) {
367           spec->html_spec_type = CHXJ_SPEC_Hdml;
368         }
369         else if (STRCASEEQ('i','I',"ixhtml",val)) {
370           spec->html_spec_type = CHXJ_SPEC_Chtml_7_0;
371         }
372         else if (STRCASEEQ('j','J',"jhtml",val)) {
373           spec->html_spec_type = CHXJ_SPEC_Jhtml;
374         }
375         else if (STRCASEEQ('j','J',"jxhtml",val)) {
376           spec->html_spec_type = CHXJ_SPEC_Jxhtml;
377         }
378       }
379       else if (STRCASEEQ('o','O',"output_encoding",k)){
380           spec->output_encoding = apr_pstrdup(r->pool,val);
381       }
382     }
383   }
384   
385   DBG(r, "REQ[%X] end %s() [%d]",TO_ADDR(r),__func__,spec->provider);
386   return spec;
387 }
388 /*
389  * vim:ts=2 et
390  */
391