From 9416c33df02fc144b55feb8a1f410a36f3d285f6 Mon Sep 17 00:00:00 2001 From: coltware Date: Fri, 19 Feb 2010 15:58:54 +0000 Subject: [PATCH] *Add new feature Additional device data from TSV file conf) ChxjAddDeviceDataTSV path_to_tsv_file tsv sample) PROVIDER DEVICE_ID WIDTH HEIGHT HTML_TYPE FOO1 1 F01A 240 352 IXHTML Y feature 1. ) override device spec from TSV ( key is provider and device id ) Booked header key name Provider ) 1: docomo, 2: au, 3:SoftBank, 0:unknown Device_id ) same xml Device_name ) same xml Html_spec_type ) same xml width ) same xml heigh ) same xml ( alias: height ) wp_width ) same xml wp_heigh ) same xml ( alias : wp_height ) gif ) same xml jpeg ) same xml png ) same xml bmp2) same xml bmp4) same xml color) same xml cache) same xml feature 2. ) Add request header ex ) X-Chxj-Info-FOO1 = Y if you use PHP, you can get value form $_SERVER['HTTP_X_CHXJ_INFO_FOO1']. Note: Tsv spec data overrides device XML data. allows tsv null value ( so if you use xml device data, please put null value ) Typical usage: ChxjLoadDeviceData .../simple_device_data.xml ChxjAddDeviceDataTSV path_to_tsv_file --- include/chxj_add_device_env.h | 2 + include/chxj_load_device_data.h | 5 + include/chxj_specified_device.h | 10 ++ include/mod_chxj.h | 14 +++ src/chxj_add_device_env.c | 22 +++++ src/chxj_load_device_data.c | 93 ++++++++++++++++++ src/chxj_specified_device.c | 211 +++++++++++++++++++++++++++++++++++++++- src/mod_chxj.c | 64 ++++++++++++ 8 files changed, 420 insertions(+), 1 deletion(-) mode change 100644 => 100755 include/chxj_add_device_env.h mode change 100644 => 100755 include/chxj_load_device_data.h mode change 100644 => 100755 include/chxj_specified_device.h mode change 100644 => 100755 include/mod_chxj.h mode change 100644 => 100755 src/chxj_add_device_env.c mode change 100644 => 100755 src/chxj_load_device_data.c mode change 100644 => 100755 src/chxj_specified_device.c diff --git a/include/chxj_add_device_env.h b/include/chxj_add_device_env.h old mode 100644 new mode 100755 index 82cae00e..acb1bd52 --- a/include/chxj_add_device_env.h +++ b/include/chxj_add_device_env.h @@ -68,6 +68,8 @@ #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 diff --git a/include/chxj_load_device_data.h b/include/chxj_load_device_data.h old mode 100644 new mode 100755 index ca036f58..66811c3a --- a/include/chxj_load_device_data.h +++ b/include/chxj_load_device_data.h @@ -24,4 +24,9 @@ extern void chxj_load_device_data( 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 diff --git a/include/chxj_specified_device.h b/include/chxj_specified_device.h old mode 100644 new mode 100755 index 9d6abd94..459e4508 --- a/include/chxj_specified_device.h +++ b/include/chxj_specified_device.h @@ -44,6 +44,7 @@ typedef struct device_table_t device_table; 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; @@ -128,4 +129,13 @@ extern device_table* chxj_specified_device( 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 diff --git a/include/mod_chxj.h b/include/mod_chxj.h old mode 100644 new mode 100755 index 42c69cb8..a043e60a --- a/include/mod_chxj.h +++ b/include/mod_chxj.h @@ -43,6 +43,7 @@ #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" @@ -351,6 +352,8 @@ struct mod_chxj_config { 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; @@ -366,6 +369,9 @@ struct mod_chxj_config { 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) @@ -462,6 +468,14 @@ module AP_MODULE_DECLARE_DATA chxj_module; #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)) diff --git a/src/chxj_add_device_env.c b/src/chxj_add_device_env.c old mode 100644 new mode 100755 index 4fa865f1..82f8368b --- a/src/chxj_add_device_env.c +++ b/src/chxj_add_device_env.c @@ -79,6 +79,28 @@ chxj_add_device_env(request_rec *r, device_table *spec) 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); } diff --git a/src/chxj_load_device_data.c b/src/chxj_load_device_data.c old mode 100644 new mode 100755 index 72bb1937..980d43d4 --- a/src/chxj_load_device_data.c +++ b/src/chxj_load_device_data.c @@ -136,6 +136,7 @@ s_set_device_data(Doc *doc, apr_pool_t *p, device_table_list *dtl, Node *node) 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; @@ -218,36 +219,47 @@ s_set_device_data(Doc *doc, apr_pool_t *p, device_table_list *dtl, Node *node) 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; } } } @@ -456,6 +468,87 @@ s_set_device_data(Doc *doc, apr_pool_t *p, device_table_list *dtl, Node *node) } } } + +/** + * 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 */ diff --git a/src/chxj_specified_device.c b/src/chxj_specified_device.c old mode 100644 new mode 100755 index 68247ec4..e37ace7d --- a/src/chxj_specified_device.c +++ b/src/chxj_specified_device.c @@ -18,6 +18,7 @@ static device_table UNKNOWN_DEVICE = { .next = NULL, + .provider = CHXJ_PROVIDER_UNKNOWN, .device_id = "", .device_name = "UNKNOWN", .html_spec_type = CHXJ_SPEC_UNKNOWN, @@ -58,6 +59,27 @@ static device_table UNKNOWN_DEVICE = { .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. @@ -67,6 +89,36 @@ static device_table UNKNOWN_DEVICE = { 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; @@ -115,8 +167,12 @@ chxj_specified_device(request_rec *r, const char *user_agent) break; } - if (dt) + if (dt){ + if (conf->detect_device_type > CHXJ_ADD_DETECT_DEVICE_TYPE_NONE ){ + dt->device_id = device_id; + } returnType = dt; + } } } @@ -130,6 +186,159 @@ chxj_specified_device(request_rec *r, const char *user_agent) 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 diff --git a/src/mod_chxj.c b/src/mod_chxj.c index fd117792..b79cddef 100755 --- a/src/mod_chxj.c +++ b/src/mod_chxj.c @@ -33,6 +33,7 @@ #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" @@ -1748,6 +1749,9 @@ chxj_create_per_dir_config(apr_pool_t *p, char *arg) 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; @@ -1810,6 +1814,9 @@ chxj_merge_per_dir_config(apr_pool_t *p, void *basev, void *addv) 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); @@ -2055,6 +2062,27 @@ chxj_merge_per_dir_config(apr_pool_t *p, void *basev, void *addv) 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; } @@ -2991,6 +3019,36 @@ cmd_imode_emoji_color( 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( @@ -3165,6 +3223,12 @@ static const command_rec cmds[] = { 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}, }; -- 2.11.0