OSDN Git Service

* updated copyright.
[modchxj/mod_chxj.git] / src / chxj_load_device_data.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 <qs_ignore_sp.h>
19 #include <qs_log.h>
20 #include <qs_malloc.h>
21 #include <qs_parse_attr.h>
22 #include <qs_parse_file.h>
23 #include <qs_parse_string.h>
24 #include <qs_parse_tag.h>
25 #include "chxj_load_device_data.h"
26 #include "chxj_str_util.h"
27
28
29 static void s_set_devices_data(
30   Doc              *doc, 
31   apr_pool_t       *p, 
32   mod_chxj_config  *conf, 
33   Node             *node) ;
34
35 static void s_set_user_agent_data(
36   Doc              *doc, 
37   apr_pool_t       *p, 
38   mod_chxj_config  *conf, 
39   Node             *node);
40
41 static void s_set_device_data(
42   Doc               *doc, 
43   apr_pool_t        *p, 
44   device_table_list *dtl, 
45   Node              *node) ;
46
47 static int s_sort_table_compare(const void *a, const void *b);
48 static void s_set_sort_table(Doc *doc, apr_pool_t *p, device_table_list *dtl);
49
50 #if 0
51 #include <stdio.h>
52 static void
53 s_debug_dump(device_table_list *dtl) 
54 {
55   size_t ii=0;
56   FILE *fp = fopen("/tmp/device_dump.log", "a");
57   fprintf(fp, "===================== %d\n", dtl->table_count);
58   fflush(fp);
59   for (ii=0; ii<dtl->table_count; ii++) {
60     if (dtl->sort_table == NULL) {
61       fprintf(fp, "sort_table is NULL\n"); 
62       fflush(fp);
63     }
64     if (dtl->sort_table[ii] == NULL) {
65       fprintf(fp, "sort_table[%d] is NULL\n", ii);
66       fflush(fp);
67     }
68     fprintf(fp, "[%s]\n", dtl->sort_table[ii]->device_id); 
69   }
70   fclose(fp);
71 }
72 #endif
73 #define DBG_DUMP(X) 
74
75
76 /**
77  * load device_data.xml
78  */
79 void
80 chxj_load_device_data(Doc *doc, apr_pool_t *p, mod_chxj_config *conf) 
81 {
82   conf->devices = NULL;
83   s_set_devices_data(doc, p, conf,qs_get_root(doc));
84 }
85
86
87 /**
88  * <devices>
89  */
90 static void
91 s_set_devices_data(Doc *doc, apr_pool_t *p, mod_chxj_config *conf, Node *node) 
92 {
93   Node *child;
94
95   for (child = qs_get_child_node(doc,node); 
96        child ; 
97        child = qs_get_next_node(doc,child)) {
98     char *name = qs_get_node_name(doc,child);
99     if (STRCASEEQ('d','D',"devices",name)) {
100       s_set_user_agent_data(doc, p, conf, child);
101     }
102   }
103 }
104
105 /**
106  * <user_agent>
107  */
108 static void
109 s_set_user_agent_data(Doc *doc, apr_pool_t *p, mod_chxj_config *conf, Node *node) 
110 {
111   Node              *child;
112   device_table_list *t;
113
114   for (child = qs_get_child_node(doc,node);
115        child ;
116        child = qs_get_next_node(doc,child)) {
117     char *name = qs_get_node_name(doc,child);
118     if (STRCASEEQ('u','U',"user_agent",name)) {
119       Attr *attr;
120       device_table_list *dtl;
121
122       if (! conf->devices) {
123         conf->devices = apr_pcalloc(p, sizeof(device_table_list));
124         conf->devices->next    = NULL;
125         conf->devices->pattern = NULL;
126         conf->devices->table   = NULL;
127         conf->devices->tail    = NULL;
128         dtl = conf->devices;
129       }
130       else {
131         for (t = conf->devices; t ; t = t->next) {
132           if (! t->next)
133             break;
134         }
135         t->next = apr_pcalloc(p, sizeof(device_table_list));
136         t->next->next    = NULL;
137         t->next->pattern = NULL;
138         t->next->table   = NULL;
139         t->next->tail    = NULL;
140         dtl = t->next;
141       }
142
143       for (attr = qs_get_attr(doc,child); 
144            attr ; 
145            attr = qs_get_next_attr(doc,attr)) {
146         char *attr_name = qs_get_attr_name(doc,attr);
147
148         if (STRCASEEQ('p','P',"pattern",attr_name)) {
149             dtl->pattern = apr_pstrdup(p, qs_get_attr_value(doc,attr));
150             dtl->regexp = ap_pregcomp(p, (const char *)dtl->pattern, AP_REG_EXTENDED|AP_REG_ICASE);
151         }
152       }
153       dtl->table_count = 0;
154       s_set_device_data(doc, p, dtl, child);
155       s_set_sort_table(doc, p, dtl);
156     }
157   }
158 }
159
160
161 static void
162 s_set_device_data(Doc *doc, apr_pool_t *p, device_table_list *dtl, Node *node) 
163 {
164   Node         *child;
165   device_table *dt;
166
167   dt = apr_pcalloc(p, sizeof(device_table));
168   dt->next           = NULL;
169   dt->device_id      = NULL;
170   dt->device_name    = NULL;
171   dt->html_spec_type = CHXJ_SPEC_Chtml_3_0;
172   dt->width          = 0;
173   dt->heigh          = 0;
174   dt->wp_width       = 0;
175   dt->wp_heigh       = 0;
176   dt->cache          = 5;
177   dt->emoji_type     = NULL;
178   dt->color          = 256;
179   dt->dpi_width      = 96;
180   dt->dpi_heigh      = 96;
181
182   for (child = qs_get_child_node(doc,node); 
183        child ;
184        child = qs_get_next_node(doc,child)) {
185     char *name = qs_get_node_name(doc,child);
186     switch (*name) {
187     case 'd':
188     case 'D':
189       if (strcasecmp(name, "device") == 0) {
190         s_set_device_data(doc,p, dtl, child);
191       }
192       else
193       if (strcasecmp(name, "device_id") == 0) {
194         Node* ch = qs_get_child_node(doc, child);
195         if (ch &&  strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
196           dt->device_id = apr_pstrdup(p, qs_get_node_value(doc, ch));
197         }
198       }
199       else
200       if (strcasecmp(name, "device_name") == 0) {
201         Node* ch = qs_get_child_node(doc, child);
202         if (ch &&  strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
203           dt->device_name = apr_pstrdup(p, qs_get_node_value(doc, ch));
204         }
205       }
206       else
207       if (strcasecmp(name, "dpi_width") == 0) {
208         Node* ch = qs_get_child_node(doc, child);
209         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
210           char *vv = qs_get_node_value(doc,ch);
211           unsigned int ii;
212           for (ii=0; ii<strlen(vv); ii++) {
213             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
214               continue;
215             break;
216           }
217           if (ii == strlen(vv)) 
218             dt->dpi_width = atoi(qs_get_node_value(doc,ch));
219           else 
220             dt->dpi_width = 0;
221         }
222       }
223       else
224       if (strcasecmp(name, "dpi_heigh") == 0) {
225         Node* ch = qs_get_child_node(doc, child);
226         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
227           char *vv = qs_get_node_value(doc,ch);
228           unsigned int ii;
229           for (ii=0; ii<strlen(vv); ii++) {
230             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
231               continue;
232             break;
233           }
234   
235           if (ii == strlen(vv)) 
236             dt->dpi_heigh = atoi(qs_get_node_value(doc,ch));
237           else 
238             dt->dpi_heigh = 0;
239         }
240       }
241       break;
242
243     case 'h':
244     case 'H':
245       if (strcasecmp(name, "html_spec_type") == 0) {
246         Node *ch = qs_get_child_node(doc, child);
247         if (ch &&  strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
248           char *vv = qs_get_node_value(doc, ch);
249           if (STRCASEEQ('x','X',"xhtml_mobile_1_0",vv)) {
250             dt->html_spec_type = CHXJ_SPEC_XHtml_Mobile_1_0;
251           }
252           else if (STRCASEEQ('c','C',"chtml_1_0",vv)) {
253             dt->html_spec_type = CHXJ_SPEC_Chtml_1_0;
254           }
255           else if (STRCASEEQ('c','C',"chtml_2_0",vv)) {
256             dt->html_spec_type = CHXJ_SPEC_Chtml_2_0;
257           }
258           else if (STRCASEEQ('c','C',"chtml_3_0",vv)) {
259             dt->html_spec_type = CHXJ_SPEC_Chtml_3_0;
260           }
261           else if (STRCASEEQ('c','C',"chtml_4_0",vv)) {
262             dt->html_spec_type = CHXJ_SPEC_Chtml_4_0;
263           }
264           else if (STRCASEEQ('c','C',"chtml_5_0",vv)) {
265             dt->html_spec_type = CHXJ_SPEC_Chtml_5_0;
266           }
267           else if (STRCASEEQ('c','C',"chtml_6_0",vv)) {
268             dt->html_spec_type = CHXJ_SPEC_Chtml_6_0;
269           }
270           else if (STRCASEEQ('c','C',"chtml_7_0",vv)) {
271             dt->html_spec_type = CHXJ_SPEC_Chtml_7_0;
272           }
273           else if (STRCASEEQ('h','H',"hdml",vv)) {
274             dt->html_spec_type = CHXJ_SPEC_Hdml;
275           }
276           else if (STRCASEEQ('j','J',"jhtml",vv)) {
277             dt->html_spec_type = CHXJ_SPEC_Jhtml;
278           }
279           else if (STRCASEEQ('j','J',"jxhtml",vv)) {
280             dt->html_spec_type = CHXJ_SPEC_Jxhtml;
281           }
282         }
283       }
284       else 
285       if (strcasecmp(name, "heigh") == 0) {
286         Node* ch = qs_get_child_node(doc, child);
287         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
288           char *vv = qs_get_node_value(doc,ch);
289           unsigned int ii;
290           for (ii=0; ii<strlen(vv); ii++) {
291             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
292               continue;
293             break;
294           }
295   
296           if (ii == strlen(vv)) 
297             dt->heigh = atoi(qs_get_node_value(doc,ch));
298           else 
299             dt->heigh = 0;
300         }
301       }
302       break;
303
304     case 'w':
305     case 'W':
306       if (strcasecmp(name, "width") == 0) {
307         Node *ch = qs_get_child_node(doc, child);
308         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
309           char *vv = qs_get_node_value(doc,ch);
310           unsigned int ii;
311           for (ii=0; ii<strlen(vv); ii++) {
312             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0')
313               continue;
314             break;
315           }
316           if (ii == strlen(vv))
317             dt->width = atoi(qs_get_node_value(doc,ch));
318           else 
319             dt->width = 0;
320         }
321       }
322       else
323       if (strcasecmp(name, "wp_width") == 0) {
324         Node *ch = qs_get_child_node(doc, child);
325         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
326           char *vv = qs_get_node_value(doc,ch);
327           unsigned int ii;
328           for (ii=0; ii<strlen(vv); ii++) {
329             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
330               continue;
331             break;
332           }
333   
334           if (ii == strlen(vv)) 
335             dt->wp_width = atoi(qs_get_node_value(doc,ch));
336           else 
337             dt->wp_width = 0;
338         }
339       }
340       else
341       if (strcasecmp(name, "wp_heigh") == 0) {
342         Node *ch = qs_get_child_node(doc, child);
343         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
344           char *vv = qs_get_node_value(doc,ch);
345           unsigned int ii;
346           for (ii=0; ii<strlen(vv); ii++) {
347             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
348               continue;
349             break;
350           }
351   
352           if (ii == strlen(vv)) 
353             dt->wp_heigh = atoi(qs_get_node_value(doc,ch));
354           else 
355             dt->wp_heigh = 0;
356         }
357       }
358       break;
359
360     case 'g':
361     case 'G':
362       if (strcasecmp(name, "gif") == 0) {
363         Node *ch = qs_get_child_node(doc, child);
364         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
365           char *vv = qs_get_node_value(doc,ch);
366   
367           if (strcasecmp(vv, "true") == 0)
368             dt->available_gif = 1;
369           else
370             dt->available_gif = 0;
371         }
372       }
373       break;
374
375     case 'j':
376     case 'J':
377       if (strcasecmp(name, "jpeg") == 0 || strcasecmp(name, "jpg") == 0) {
378         Node *ch = qs_get_child_node(doc, child);
379         if (ch != NULL && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
380           char *vv = qs_get_node_value(doc,ch);
381   
382           if (strcasecmp(vv, "true") == 0) 
383             dt->available_jpeg = 1;
384           else 
385             dt->available_jpeg = 0;
386         }
387       }
388       break;
389   
390     case 'p':
391     case 'P':
392       if (strcasecmp(name, "png") == 0) {
393         Node *ch = qs_get_child_node(doc, child);
394         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
395           char *vv = qs_get_node_value(doc,ch);
396   
397           if (strcasecmp(vv, "true") == 0) 
398             dt->available_png = 1;
399           else
400             dt->available_png = 0;
401         }
402       }
403       break;
404
405     case 'b':
406     case 'B':
407       if (strcasecmp(name, "bmp2") == 0) {
408         Node *ch = qs_get_child_node(doc, child);
409         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
410           char *vv = qs_get_node_value(doc,ch);
411   
412           if (strcasecmp(vv, "true") == 0) 
413             dt->available_bmp2 = 1;
414           else
415             dt->available_bmp2 = 0;
416         }
417       }
418       else
419       if (strcasecmp(name, "bmp4") == 0) {
420         Node *ch = qs_get_child_node(doc, child);
421         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
422           char *vv = qs_get_node_value(doc,ch);
423   
424           if (strcasecmp(vv, "true") == 0) 
425             dt->available_bmp4 = 1;
426           else
427             dt->available_bmp4 = 0;
428         }
429       }
430       break;
431
432     case 'c':
433     case 'C':
434       if (strcasecmp(name, "color") == 0) {
435         Node *ch = qs_get_child_node(doc, child);
436         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
437           char *vv = qs_get_node_value(doc,ch);
438   
439           if (chxj_chk_numeric(vv) != 0)
440             dt->color = 0;
441           else 
442             dt->color = chxj_atoi(vv);
443         }
444       }
445       else
446       if (strcasecmp(name, "cache") == 0) {
447         Node *ch = qs_get_child_node(doc, child);
448         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) {
449           char *vv = qs_get_node_value(doc,ch);
450           unsigned int ii;
451           for (ii=0; ii<strlen(vv); ii++) {
452             if ((vv[ii] >= '1' && vv[ii] <= '9') || vv[ii] == '0') 
453               continue;
454             break;
455           }
456   
457           if (ii == strlen(vv)) 
458             dt->cache = atoi(qs_get_node_value(doc,ch));
459           else 
460             dt->cache = 0;
461         }
462       }
463       break;
464
465     case 'e':
466     case 'E':
467       if (strcasecmp(name, "emoji_type") == 0) {
468         Node *ch = qs_get_child_node(doc, child);
469         if (ch && strcasecmp(qs_get_node_name(doc,ch), "text") == 0) 
470           dt->emoji_type = apr_pstrdup(p, qs_get_node_value(doc, ch));
471       }
472       break;
473     default:
474       break;
475     }
476   }
477
478   if (dt->device_id) {
479     if (! dtl->table) {
480       dtl->table = dt;
481       dtl->tail = dt;
482     }
483     else {
484       dtl->tail->next = dt;
485       dtl->tail = dt;
486     }
487     dtl->table_count++;
488   }
489 }
490
491
492 static void
493 s_set_sort_table(Doc *doc, apr_pool_t *p, device_table_list *dtl)
494 {
495   device_table **sort_table;
496   device_table *dt;
497   size_t ii=0;
498
499   sort_table = apr_palloc(p, sizeof(device_table) * dtl->table_count);
500
501   for (dt = dtl->table; dt; dt = dt->next) {
502     sort_table[ii++] = dt;
503   }
504
505   dtl->sort_table = sort_table;
506   DBG_DUMP(dtl);
507
508   qsort((void *)sort_table, (size_t)dtl->table_count, sizeof(*sort_table), s_sort_table_compare);
509
510
511   DBG_DUMP(dtl);
512 }
513
514 static int
515 s_sort_table_compare(const void *a, const void *b)
516 {
517   device_table *aa = *(device_table **)a;
518   device_table *bb = *(device_table **)b;
519   /* not strcasecmp. for LOAD */
520   return strcmp(aa->device_id, bb->device_id);
521 }
522
523 /*
524  * vim:ts=2 et
525  */