#define HTTP_X_CHXJ_VERSION "X-Chxj-Version"
+#define HTTP_X_CHXJ_INFO "X-Chxj-Info"
+
extern void chxj_add_device_env(request_rec *r, device_table *spec);
#endif
apr_pool_t* p,
mod_chxj_config* conf);
+extern void chxj_load_device_tsv_data(
+ apr_file_t* fp,
+ apr_pool_t* p,
+ mod_chxj_config* conf);
+
#endif
struct device_table_t {
struct device_table_t* next;
+ int provider; /* DOCOMO|AU|SOFTBANK|UNKNOWN */
const char* device_id;
const char* device_name;
spec_type html_spec_type;
request_rec *r,
const char *user_agent);
+extern device_table* chxj_specified_device_from_xml(
+ request_rec *r,
+ const char *user_agent);
+
+extern device_table* chxj_specified_device_from_tsv(
+ request_rec *r,
+ device_table *spec,
+ const char *user_agent);
+
#endif
#include "apr_dso.h"
#include "apr_general.h"
#include "apr_pools.h"
+#include "apr_hash.h"
#if defined(AP_NEED_SET_MUTEX_PERMS)
# include "unixd.h"
cookie_store_type_t cookie_store_type;
int cookie_lazy_mode;
char *cookie_dbm_type;
+
+ int detect_device_type; /* XML|TSV */
#if defined(USE_MYSQL_COOKIE)
mysql_t mysql;
chxj_new_line_type_t new_line_type;
char *post_log; /* post log environment name. */
+
+ apr_array_header_t *device_keys; /* TSV header array */
+ apr_hash_t *device_hash; /* TSV device data hash table */
};
#define IS_COOKIE_STORE_DBM(X) ((X) == COOKIE_STORE_TYPE_DBM)
#define CHXJ_IMODE_EMOJI_COLOR_OFF (1)
#define CHXJ_IMODE_EMOJI_COLOR_NONE (0)
+#define CHXJ_ADD_DETECT_DEVICE_TYPE_TSV (1)
+#define CHXJ_ADD_DETECT_DEVICE_TYPE_NONE (0)
+
+#define CHXJ_PROVIDER_UNKNOWN (0)
+#define CHXJ_PROVIDER_DOCOMO (1)
+#define CHXJ_PROVIDER_AU (2)
+#define CHXJ_PROVIDER_SOFTBANK (3)
+
#define DBG(X,args...) chxj_log_rerror(APLOG_MARK,APLOG_DEBUG,0,(request_rec*)(X),##args)
#define SDBG(X,Y) chxj_log_error(APLOG_MARK,APLOG_DEBUG,0,(X),(Y))
apr_table_setn(r->headers_in, HTTP_X_CHXJ_CACHE, apr_psprintf(r->pool, "%d", spec->cache));
apr_table_setn(r->headers_in, HTTP_X_CHXJ_VERSION, apr_pstrdup(r->pool, PACKAGE_VERSION));
+
+ mod_chxj_config* dconf;
+ dconf = chxj_get_module_config(r->per_dir_config, &chxj_module);
+ if (dconf->detect_device_type == CHXJ_ADD_DETECT_DEVICE_TYPE_TSV ){
+ if (spec->device_id != NULL &&
+ dconf->device_hash != NULL){
+ char *key = apr_psprintf(r->pool,"%d.%s",spec->provider,spec->device_id);
+ apr_table_t *ht = apr_hash_get(dconf->device_hash,key,APR_HASH_KEY_STRING);
+
+ if(ht != NULL){
+ int i;
+ for ( i=0; i< dconf->device_keys->nelts; i++){
+ const char *k = ((const char**)dconf->device_keys->elts)[i];
+ char *val = (char *)apr_table_get(ht,k);
+ if(val != NULL){
+ char *info_key = apr_psprintf(r->pool,"%s-%s",HTTP_X_CHXJ_INFO,k);
+ apr_table_setn(r->headers_in, info_key, val);
+ }
+ }
+ }
+ }
+ }
DBG(r, "REQ[%X] end chxj_add_device_env()", (unsigned int)(apr_size_t)r);
}
dt = apr_pcalloc(p, sizeof(device_table));
dt->next = NULL;
+ dt->provider = CHXJ_PROVIDER_UNKNOWN;
dt->device_id = NULL;
dt->device_name = NULL;
dt->html_spec_type = CHXJ_SPEC_Chtml_3_0;
char *vv = qs_get_node_value(doc, ch);
if (STRCASEEQ('x','X',"xhtml_mobile_1_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_XHtml_Mobile_1_0;
+ dt->provider = CHXJ_PROVIDER_AU;
}
else if (STRCASEEQ('c','C',"chtml_1_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_1_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_2_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_2_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_3_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_3_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_4_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_4_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_5_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_5_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_6_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_6_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('c','C',"chtml_7_0",vv)) {
dt->html_spec_type = CHXJ_SPEC_Chtml_7_0;
+ dt->provider = CHXJ_PROVIDER_DOCOMO;
}
else if (STRCASEEQ('h','H',"hdml",vv)) {
dt->html_spec_type = CHXJ_SPEC_Hdml;
+ dt->provider = CHXJ_PROVIDER_AU;
}
else if (STRCASEEQ('j','J',"jhtml",vv)) {
dt->html_spec_type = CHXJ_SPEC_Jhtml;
+ dt->provider = CHXJ_PROVIDER_SOFTBANK;
}
else if (STRCASEEQ('j','J',"jxhtml",vv)) {
dt->html_spec_type = CHXJ_SPEC_Jxhtml;
+ dt->provider = CHXJ_PROVIDER_SOFTBANK;
}
}
}
}
}
}
+
+/**
+ * load device_data.xml
+ */
+void
+chxj_load_device_tsv_data(apr_file_t *fp,apr_pool_t *p, mod_chxj_config *conf)
+{
+ apr_status_t st;
+
+ char *pstat;
+ char *pair;
+
+ char *line = apr_palloc(p,256);
+
+ int is_header = 1;
+ int keynum = 0;
+ int valnum = 0;
+
+ conf->device_keys = apr_array_make(p,2, sizeof(const char*));
+ conf->device_hash = apr_hash_make(p);
+
+ while(APR_EOF != (st=apr_file_eof(fp))){
+ st = apr_file_gets(line,1024,fp);
+ if(st == APR_SUCCESS){
+ if(is_header){
+ keynum=0;
+
+ for(pair = apr_strtok(line,"\t",&pstat); pair != NULL; pair = apr_strtok(NULL,"\t",&pstat)){
+ apr_collapse_spaces(pair,pair);
+ if(keynum < 128){
+ *(const char**)apr_array_push(conf->device_keys) = apr_pstrdup(p,pair);
+ }
+
+ //ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, "V[[%s]]", pair);
+ keynum++;
+ }
+ is_header = 0;
+ }
+ else{
+ apr_table_t *tsv_table = apr_table_make(p,keynum);
+ valnum = 0;
+ char *uid = NULL;
+ char *provider = NULL;
+ for(pair = apr_strtok(line,"\t",&pstat); pair != NULL; pair = apr_strtok(NULL,"\t",&pstat)){
+ apr_collapse_spaces(pair,pair);
+ if(valnum < keynum){
+ const char *kn = ((const char**)conf->device_keys->elts)[valnum];
+ if(strcasecmp("-",pair) != 0){
+ apr_table_set(tsv_table,kn,pair);
+ if(strcasecmp(kn,"device_id") == 0){
+ uid = apr_pstrdup(p,pair);
+ }
+ else if(strcasecmp(kn,"provider") == 0){
+ if(strcasecmp(pair,"docomo") == 0){
+ provider = "1";
+ }
+ else if(strcasecmp(pair,"au") == 0){
+ provider = "2";
+ }
+ else if(strcasecmp(pair,"softbank") == 0){
+ provider = "3";
+ }
+ else{
+ provider = apr_pstrdup(p,pair);
+ }
+ }
+ //ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, "[%s] %d:V[%s] = [%s]", uid,valnum,kn,pair);
+ }
+ }
+ valnum++;
+ }
+ if(uid != NULL && *uid && provider != NULL && *provider){
+ char *key = apr_psprintf(p,"%s.%s",provider,uid);
+ //ap_log_error(APLOG_MARK, APLOG_CRIT, 0, NULL, "save hash [%s]",key );
+ apr_hash_set(conf->device_hash,key,APR_HASH_KEY_STRING,tsv_table);
+ }
+ }
+ }
+ }
+}
+
/*
* vim:ts=2 et
*/
static device_table UNKNOWN_DEVICE = {
.next = NULL,
+ .provider = CHXJ_PROVIDER_UNKNOWN,
.device_id = "",
.device_name = "UNKNOWN",
.html_spec_type = CHXJ_SPEC_UNKNOWN,
.emoji_type = NULL,
};
+int
+get_boolean_value(request_rec *r,const char *val){
+ switch(*val) {
+ case '0':
+ case 'f':
+ case 'F':
+ case 'n':
+ case 'N':
+ return 0;
+ break;
+ case '1':
+ case 't':
+ case 'T':
+ case 'y':
+ case 'Y':
+ return 1;
+ break;
+ }
+ return -1;
+}
+
/**
* The device is specified from UserAgent.
* @param r Request_rec is appointed.
device_table *
chxj_specified_device(request_rec *r, const char *user_agent)
{
+ device_table *returnType = &UNKNOWN_DEVICE;
+ device_table *dt;
+ mod_chxj_config *conf;
+
+ conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
+
+ DBG(r, "start chxj_specified_device() %d",conf->detect_device_type);
+
+ if(! user_agent){
+ return returnType;
+ }
+
+ dt = chxj_specified_device_from_xml(r,user_agent);
+
+ if (conf->detect_device_type == CHXJ_ADD_DETECT_DEVICE_TYPE_TSV ){
+ chxj_specified_device_from_tsv(r,dt,user_agent);
+ }
+
+ DBG(r, "end chxj_specified_device() %d",conf->detect_device_type);
+ return dt;
+}
+/**
+ * The device is specified from UserAgent.
+ * @param r Request_rec is appointed.
+ * @param userAgent UserAgent is appointed here,
+ * @return The style which corresponds is returned.
+ */
+device_table *
+chxj_specified_device_from_xml(request_rec *r, const char *user_agent)
+{
ap_regmatch_t match[10];
device_table *returnType = &UNKNOWN_DEVICE;
device_table_list *dtl;
break;
}
- if (dt)
+ if (dt){
+ if (conf->detect_device_type > CHXJ_ADD_DETECT_DEVICE_TYPE_NONE ){
+ dt->device_id = device_id;
+ }
returnType = dt;
+ }
}
}
return returnType;
}
+/**
+ * The device is specified from TSV file.
+ * @param r Request_rec is appointed.
+ * @param userAgent UserAgent is appointed here,
+ * @return The style which corresponds is returned.
+ */
+device_table *
+chxj_specified_device_from_tsv(request_rec *r,device_table *spec,const char *user_agent)
+{
+ if(spec->device_id == NULL){
+ return spec;
+ }
+
+ DBG(r, "start chxj_specified_device_from_tsv() device_id:[%s]",spec->device_id);
+ mod_chxj_config *conf;
+
+ conf = chxj_get_module_config(r->per_dir_config, &chxj_module);
+
+ if(conf->device_hash == NULL){
+ return spec;
+ }
+ char *key = apr_psprintf(r->pool,"%d.%s",spec->provider,spec->device_id);
+
+ apr_table_t *ht = apr_hash_get(conf->device_hash,key,APR_HASH_KEY_STRING);
+
+ if(ht != NULL){
+ DBG(r, "found ! chxj_specified_device_from_tsv() %s",key);
+ int i;
+ for ( i=0; i< conf->device_keys->nelts; i++){
+ const char *k = ((const char**)conf->device_keys->elts)[i];
+ char *val = (char *)apr_table_get(ht,k);
+ if(val == NULL){
+ continue;
+ }
+ DBG(r, "start chxj_specified_device_from_tsv() [%s] = [%s]:[%s]",spec->device_id,k,val);
+ if (STRCASEEQ('d','D',"device_name",k)){
+ spec->device_name = apr_pstrdup(r->pool,val);
+ }
+ if (STRCASEEQ('w','W',"width",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->width = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('h','H',"heigh",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->heigh = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('h','H',"height",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->heigh = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('w','W',"wp_width",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->wp_width = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('w','W',"wp_heigh",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->wp_heigh = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('w','W',"wp_height",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->wp_heigh = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('c','C',"cache",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->cache = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('g','G',"gif",k)){
+ int tmp = get_boolean_value(r,val);
+ if(tmp > -1 ){
+ spec->available_gif = tmp;
+ }
+ }
+ else if (STRCASEEQ('j','J',"jpeg",k)){
+ int tmp = get_boolean_value(r,val);
+ if(tmp > -1 ){
+ spec->available_jpeg = tmp;
+ }
+ }
+ else if (STRCASEEQ('p','P',"png",k)){
+ int tmp = get_boolean_value(r,val);
+ if(tmp > -1 ){
+ spec->available_png = tmp;
+ }
+ }
+ else if (STRCASEEQ('b','B',"bmp2",k)){
+ int tmp = get_boolean_value(r,val);
+ if(tmp > -1 ){
+ spec->available_bmp2 = tmp;
+ }
+ }
+ else if (STRCASEEQ('b','B',"bmp4",k)){
+ int tmp = get_boolean_value(r,val);
+ if(tmp > -1 ){
+ spec->available_bmp4 = tmp;
+ }
+ }
+ else if (STRCASEEQ('c','C',"color",k)){
+ if(chxj_chk_numeric(val) == 0){
+ spec->color = chxj_atoi(val);
+ }
+ }
+ else if (STRCASEEQ('e','E',"emoji_type",k)){
+ spec->emoji_type = apr_pstrdup(r->pool,val);
+ }
+ else if (STRCASEEQ('h','H',"html_spec_type",k)){
+ if (STRCASEEQ('x','X',"xhtml_mobile_1_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_XHtml_Mobile_1_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_1_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_1_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_2_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_2_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_3_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_3_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_4_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_4_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_5_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_5_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_6_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_6_0;
+ }
+ else if (STRCASEEQ('c','C',"chtml_7_0",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Chtml_7_0;
+ }
+ else if (STRCASEEQ('h','H',"hdml",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Hdml;
+ }
+ else if (STRCASEEQ('j','J',"jhtml",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Jhtml;
+ }
+ else if (STRCASEEQ('j','J',"jxhtml",val)) {
+ spec->html_spec_type = CHXJ_SPEC_Jxhtml;
+ }
+ }
+ }
+ }
+
+ DBG(r, "end chxj_specified_device_from_tsv() [%d]",spec->provider);
+ return spec;
+}
+
/*
* vim:ts=2 et
#include "apr_dso.h"
#include "apr_general.h"
#include "apr_pools.h"
+#include "apr_file_info.h"
#include "mod_chxj.h"
#include "chxj_encoding.h"
conf->cookie_store_type = COOKIE_STORE_TYPE_NONE;
conf->cookie_lazy_mode = 0;
conf->cookie_dbm_type = NULL;
+
+ conf->detect_device_type = CHXJ_ADD_DETECT_DEVICE_TYPE_NONE;
+
#if defined(USE_MYSQL_COOKIE)
memset((void *)&conf->mysql, 0, sizeof(mysql_t));
conf->mysql.port = MYSQL_PORT;
mrg->allowed_cookie_domain = NULL;
mrg->post_log = NULL;
mrg->cookie_dbm_type = NULL;
+
+ mrg->device_keys = NULL;
+ mrg->device_hash = NULL;
mrg->dir = apr_pstrdup(p, add->dir);
mrg->imode_emoji_color = add->imode_emoji_color;
}
+ if (add->detect_device_type == CHXJ_ADD_DETECT_DEVICE_TYPE_NONE) {
+ mrg->detect_device_type = base->detect_device_type;
+ }
+ else {
+ mrg->detect_device_type = add->detect_device_type;
+ }
+
+ if (add->device_keys) {
+ mrg->device_keys = add->device_keys;
+ }
+ else{
+ mrg->device_keys = base->device_keys;
+ }
+
+ if (add->device_hash) {
+ mrg->device_hash = add->device_hash;
+ }
+ else{
+ mrg->device_hash = base->device_hash;
+ }
+
return mrg;
}
return NULL;
}
+static const char *
+cmd_add_device_data_tsv(cmd_parms *parms, void *mconfig, const char *arg)
+{
+ mod_chxj_config *conf;
+
+ if (strlen(arg) > 256)
+ return "mod_chxj: device tsv filename too long.";
+
+ conf = (mod_chxj_config *)mconfig;
+
+ conf->detect_device_type = CHXJ_ADD_DETECT_DEVICE_TYPE_TSV;
+
+ apr_finfo_t info;
+ apr_status_t res = apr_stat(&info,arg,APR_FINFO_TYPE,parms->pool);
+ if(res != APR_SUCCESS){
+ return apr_psprintf(parms->pool,"ChxjDeviceTSV [%s]: not found ",arg);
+ }
+ else{
+ if(info.filetype != APR_REG ){
+ return apr_psprintf(parms->pool,"ChxjDeviceTSV [%s]: is not file ",arg);
+ }
+ }
+ apr_file_t *fp;
+ apr_file_open(&fp, arg, APR_READ|APR_BUFFERED, APR_OS_DEFAULT, parms->pool);
+
+ chxj_load_device_tsv_data(fp,parms->pool,conf);
+
+ apr_file_close(fp);
+ return NULL;
+}
static const command_rec cmds[] = {
AP_INIT_TAKE1(
NULL,
OR_ALL,
"Auto i-mode emoji color"),
+ AP_INIT_TAKE1(
+ "ChxjAddDeviceDataTSV",
+ cmd_add_device_data_tsv,
+ NULL,
+ OR_ALL,
+ "Additional devices TSV data"),
{NULL,{NULL},NULL,0,0,NULL},
};