Files
2026-08-07 17:38:18 +09:00

454 lines
14 KiB
C

/****************************************************************************
mod_dav_pgsql (DASL) for apache 2.X
CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
Author : sean kim (sean@solutionbox.co.kr)
$Id: main.c,v 1.2 2007/01/25 06:52:16 elenoa Exp $
Redistribution and use in source and binary forms, with or with out
modification, are not permitted in outside of SolutionBox Inc.
****************************************************************************/
#include <httpd.h>
#include <http_config.h>
#include <http_protocol.h>
#include <http_log.h>
#include <http_core.h> /* for ap_construct_url */
#include <http_request.h>
#include <http_connection.h>
#include <apr_strings.h>
#include <apr_hash.h>
#include <apr_base64.h>
#include "dav_repos.h"
#include "dbms.h"
#include "util.h"
#include "share_common.h"
#include "share_statistic.h"
#include "share_anonymous.h"
#include "transfer.h"
#include "inout_filter.h"
#define INHERIT_VALUE(parent, child, field) \
((child)->field ? (child)->field : (parent)->field)
#define DBMS_PRIVIDER_NAME "repos"
#define MaxSizeOfQueryBuffer 1024
/* Note: the "dav_repos" prefix is mandatory */
extern module AP_MODULE_DECLARE_DATA dav_repos_module;
#if APR_HAS_THREADS
apr_thread_rwlock_t *db_lock = NULL;
#endif
//apr_global_mutex_t *db_global_lock = NULL;
// 2012.07.04 dadamin
// FreeBSD 경우 getmntent 함수 쓰레드 지원하지 않기 때문에
// 관련 함수 사용 로직에 lock을 사용하여 이를 대처함
#ifdef __FreeBSD__
apr_global_mutex_t *local_disk_lock = NULL;
#endif // __FreeBSD__
static void *dav_repos_create_dir_config(apr_pool_t * p, char *dir)
{
/* NOTE: dir==NULL creates the default per-dir config */
dav_repos_dir_conf *conf;
conf = (dav_repos_dir_conf *) apr_pcalloc(p, sizeof(*conf));
return conf;
}
static void *dav_repos_merge_dir_config(apr_pool_t * p, void *base,
void *overrides)
{
dav_repos_dir_conf *newconf;
newconf = apr_pcalloc(p, sizeof(*newconf));
return newconf;
}
static void *dav_repos_create_server_config(apr_pool_t * p, server_rec * s)
{
dav_repos_server_conf *newconf;
newconf = (dav_repos_server_conf *) apr_pcalloc(p, sizeof(*newconf));
return newconf;
}
static void *dav_repos_merge_server_config(apr_pool_t * p, void *base, void *overrides)
{
dav_repos_server_conf *parent = base;
dav_repos_server_conf *child = overrides;
dav_repos_server_conf *newconf;
newconf = (dav_repos_server_conf *) apr_pcalloc(p, sizeof(*newconf));
newconf->storage_dir = INHERIT_VALUE(parent, child, storage_dir);
return newconf;
}
/*
* Command handler for the DAV directive, which is TAKE1.
*/
static const char *dav_repos_storage_dir_cmd(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
char *pszSafeStr;
pszSafeStr = apr_pcalloc(cmd->pool, strlen(arg1) + 1);
dav_repos_replace_multi_slash_chars(arg1, pszSafeStr);
conf->storage_dir = apr_pstrdup(cmd->pool, pszSafeStr);
return NULL;
}
static const char *dav_repos_base_uri_cmd(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->base_uri = apr_pstrdup(cmd->pool, arg1);
return NULL;
}
static const char *dav_repos_host_name_cmd(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->host_name = apr_pstrdup(cmd->pool, arg1);
return NULL;
}
static const char *dav_repos_max_fhs(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->max_fhs = apr_pstrdup(cmd->pool, arg1);
return NULL;
}
static const char *dav_repos_max_anony(cmd_parms * cmd, void *config,
const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->max_anony_realm = apr_pstrdup(cmd->pool, arg1);
return NULL;
}
static const char *dav_repos_max_progess(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->max_progress = atoi(arg1);
return NULL;
}
// CHG 2019-09-24 huibong Bigbox FHS 장비 사용에 따른 mount 별 운영여유공간 계산방식 개선 (#32807)
// - 기존 conf 상의 DavProviderStorageLimit 설정은 제거 처리
/*
static const char *dav_repos_storage_limit(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->storage_limit = atoi(arg1);
return NULL;
}
*/
#define DEF_USER_CACHE 20
static const char *dav_repos_user_cache(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->user_cache = atoi(arg1);
if( conf->user_cache <= 0 )
{
conf->user_cache = DEF_USER_CACHE;
}
return NULL;
}
static const char *dav_repos_db_charset(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->db_charset = apr_pstrdup(cmd->pool, arg1);
if(conf->db_charset == NULL || strlen(conf->db_charset) <= 0 )
{
conf->db_charset = apr_pstrdup(cmd->pool, "UHC");
}
return NULL;
}
static const char *dav_repos_close_insert(cmd_parms * cmd, void *config, const char *arg1)
{
dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
conf->close_insertoff = strcasecmp(arg1, "on");
return NULL;
}
// CHG 2012-06-27 dadamin
// sibling 및 sync_host 기능은 2011 년 BD-06 사내망 제거 이후 더 이상 사용하지 않는 기능임.
// 따라서 아래 관련 코드를 주석 처리함.
//static const char *dav_repos_sibling(cmd_parms * cmd, void *config, const char *arg1)
//{
// dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
// conf->sibling = apr_pstrdup(cmd->pool, arg1);
//
// return NULL;
//}
//static const char *dav_repos_sync_host(cmd_parms * cmd, void *config, const char *arg1)
//{
// dav_repos_server_conf *conf = ap_get_module_config(cmd->server->module_config, &dav_repos_module);
// conf->sync_host = apr_pstrdup(cmd->pool, arg1);
//
// return NULL;
//}
static const command_rec dav_repos_cmds[] = {
/* per directory/location */
/* how can I make it mandatory */
/* RSRC_CONF : For server */
/* ACCESS_CONF : For dir */
AP_INIT_TAKE1("DavProviderBaseURI", dav_repos_base_uri_cmd, NULL, RSRC_CONF, "specify DavProviderBaseURI"),
AP_INIT_TAKE1("DavProviderStorageDir", dav_repos_storage_dir_cmd, NULL, RSRC_CONF, "specify DavProviderStorageDir"),
AP_INIT_TAKE1("DavProviderHostName", dav_repos_host_name_cmd, NULL, RSRC_CONF, "specify DavProviderHostName"),
AP_INIT_TAKE1("DavProviderMaxFHS", dav_repos_max_fhs, NULL, RSRC_CONF, "specify DavProviderMaxFHS"),
AP_INIT_TAKE1("DavProviderMaxAnonymous", dav_repos_max_anony, NULL, RSRC_CONF, "specify DavProviderMaxAnonymous"),
AP_INIT_TAKE1("DavProviderMaxAccount", dav_repos_user_cache, NULL, RSRC_CONF, "specify DavProviderMaxAccount"),
AP_INIT_TAKE1("DavProviderMaxProgess", dav_repos_max_progess, NULL, RSRC_CONF, "specify DavProviderMaxProgess"),
// CHG 2019-09-24 huibong Bigbox FHS 장비 사용에 따른 mount 별 운영여유공간 계산방식 개선 (#32807)
// - 기존 conf 상의 DavProviderStorageLimit 설정은 제거 처리
//AP_INIT_TAKE1("DavProviderStorageLimit", dav_repos_storage_limit, NULL, RSRC_CONF, "specify DavProviderStorageLimit"),
// CHG 2012-06-27 dadamin
// sibling 및 sync_host 기능은 2011 년 BD-06 사내망 제거 이후 더 이상 사용하지 않는 기능임.
// 따라서 아래 관련 코드를 주석 처리함.
//AP_INIT_TAKE1("DavProviderSibling", dav_repos_sibling, NULL, RSRC_CONF, "specify DavProviderSibling"),
//AP_INIT_TAKE1("DavProviderSyncHost", dav_repos_sync_host, NULL, RSRC_CONF, "specify DavProviderSyncHost"),
// 2012.06.27 dadamin
// Database Client encoding
AP_INIT_TAKE1("DavProviderDBCharset", dav_repos_db_charset, NULL, RSRC_CONF, "specify DavProviderDBCharset"),
// 2012.07.13 dadamin
// close 시 insert 유무 설정( On : Insert , off : insert X)
AP_INIT_TAKE1("DavProviderCloseInsert", dav_repos_close_insert, NULL, RSRC_CONF, "specify dav_repos_close_insert"),
{NULL}
};
static int dav_repos_init_handler(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * s)
{
void *data;
const char *userdata_key = "mod_dav_repos_init";
//int dav_of_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s);
ap_add_version_component(p,
"OpenDisk/" VERSION
#ifdef __OPENDAV_DEBUG__
",DEBUG"
#endif
#ifdef __OPENDAV_DEBUG_AUTH__
",Da"
#endif
#ifdef __OPENDAV_DEBUG_SHARED__
",Ds"
#endif
#ifdef __OPENDAV_DEBUG_USER_AUTH__
",Da"
#endif
#ifdef __OPENDAV_DEBUG_TRAFFIC_CONTROL__
",Dtc"
#endif
#ifdef __USE_TRANSFER_LOG__
",tl"
#endif
#ifdef __OPENDAV_BAND_CONTROL__
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
",ct"
#else
",nt"
#endif
#endif
#ifdef __ONLY_GET_SUCCESS_OUT__
",so"
#endif
#ifdef __OPENDAV_TRANSFER_LOG_ANONYMOUS__
",tla"
#endif
#ifdef __USE_MULTIPLE_STORAGE__
",ms"
#endif
#ifdef __USE_OLD_AUTH__
",oa"
#endif
#ifdef __NOT_USE_AUTH_TIMESLICE__
",nat"
#endif
/* from here, not affected, i supposed */
#ifdef __OPENDAV_USER_AUTH_GET
",uag"
#endif
#ifdef __NOT_USE_LOCKDB__
",nul"
#endif
#ifdef __OPENDAV_OLDAUTH_LOG__
",oal"
#endif
#ifdef __OPENDAV_SHARED_NOT_USE
",snu"
#endif
#ifdef __OPENDISK_SOLUTION__
",os"
#endif
#ifdef __OPENDISK_SOLUTION_NOT_USE_TS__
",nut"
#endif // !__OPENDISK_SOLUTION_NOT_USE_TS__
#ifdef __UNUSE_FILELOCK__
",nfl"
#endif // __UNUSE_FILELOCK__
#ifdef __USE_AUTH_SOFTLINE_ONLY__
",uso"
#endif // __USE_AUTH_SOFTLINE_ONLY__
/* until here, not affected, i supposed */
);
/* Elenoa: 2006. 1. 3. spawn new child */
apr_pool_userdata_get(&data, userdata_key, s->process->pool);
if( !data )
{
apr_pool_userdata_set((const void *)1, userdata_key, apr_pool_cleanup_null, s->process->pool);
return OK;
}
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "OPENDAV: initialize...");
/* shared memory */
// 2012.09.20 : dadamin
// 공유 메모리 attach 실패 시 프로세스 종료되게 한다.
if( dav_initialize_shared_memory(s, s->process->pool) != OK )
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "OPENDAV: dav_initialize_shared_memory failed. Exit Process.");
return !OK;
}
apr_pool_cleanup_register(p, s->process->pool, dav_cleanup_shared_memory, dav_cleanup_shared_memory);
/* transfer queue */
if (dav_initialize_transfer_queue(s, s->process->pool) != OK)
{
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "OPENDAV: dav_initialize_transfer_queue failed. Exit Process.");
return !OK;
}
apr_pool_cleanup_register(p, s->process->pool, dav_cleanup_transfer_queue, dav_cleanup_transfer_queue);
return OK;
}
/* Provider interface */
static const dav_provider dav_repos_provider = {
&dav_repos_hooks_repos, /* repos */
&dav_repos_hooks_propdb, /* prop */
#ifdef __NOT_USE_LOCKDB__
NULL,
#else
&dav_repos_hooks_locks, /* locks */
#endif
NULL, /* versioning */
NULL, /* binding */
&dav_repos_hooks_search /* search */
};
static void register_hooks(apr_pool_t * p)
{
/* apache hooks */
ap_hook_post_config(dav_repos_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
//ap_hook_child_init(dav_repos_child_init, NULL, NULL, APR_HOOK_MIDDLE);
/* live property handling */
dav_hook_find_liveprop(dav_repos_find_liveprop, NULL, NULL, APR_HOOK_MIDDLE);
dav_hook_insert_all_liveprops(dav_repos_insert_all_liveprops, NULL, NULL, APR_HOOK_MIDDLE);
/* register the namespace URIs */
dav_register_liveprop_group(p, &dav_repos_liveprop_group);
/* register our provider */
dav_register_provider(p, DBMS_PRIVIDER_NAME, &dav_repos_provider);
/* authentication / authorication */
#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
#else // 2.2.X
ap_hook_auth_checker(dav_auth_authorization, NULL, NULL, APR_HOOK_FIRST);
#endif // 2.3 over
ap_hook_check_user_id(dav_auth_authenticate, NULL, NULL, APR_HOOK_MIDDLE);
#ifndef __OPENDISK_SOLUTION_NOT_USE_TS__
/* statistics */
ap_hook_log_transaction(dav_shared_ts_access_statistic, NULL,NULL,APR_HOOK_FIRST);
#endif // !__OPENDISK_SOLUTION_NOT_USE_TS__
ap_hook_log_transaction(dav_transfer_log_generate, NULL,NULL,APR_HOOK_LAST);
/* anonymous realm */
ap_hook_post_read_request(dav_shared_ar_check_request, NULL, NULL, APR_HOOK_FIRST);
// 2015.7.15 dadamin
// in,out 트래픽 필터 추가
ap_register_input_filter("dav_input_statistic", dav_input_filter, NULL, AP_FTYPE_TRANSCODE);
ap_register_output_filter("dav_bc_output", dav_bc_output_filter, NULL, AP_FTYPE_TRANSCODE);
//apr_thread_rwlock_create(&db_lock, p);
// 2012.07.09 dadamin
// 암호화 관련 library 사용을 위한 lock 사용이지만,
// 현재 사용하고 있는 libmcrypt 는 thread safe 하기 때문에 관련 lock 삭제처리
//apr_global_mutex_create(&db_global_lock, "/tmp/dav_repos", APR_LOCK_DEFAULT, p);
// 2012.07.04 dadamin
// FreeBSD 경우 getmntent 함수 쓰레드 지원하지 않기 때문에
// 관련 함수 사용 로직에 lock을 사용하여 이를 대처함
#ifdef __FreeBSD__
apr_global_mutex_create(&local_disk_lock, "/tmp/dav_repos_disk", APR_LOCK_DEFAULT, p);
#endif // __FreeBSD__
}
module DAV_DECLARE_DATA dav_repos_module = {
STANDARD20_MODULE_STUFF,
dav_repos_create_dir_config, /* dir config creater */
dav_repos_merge_dir_config, /* dir merger --- default is to override */
dav_repos_create_server_config, /* server config */
dav_repos_merge_server_config, /* merge server config */
dav_repos_cmds, /* command table */
register_hooks, /* register hooks */
};