1470 lines
36 KiB
C
1470 lines
36 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: util.c,v 1.5 2007/03/19 08:43:12 elenoa Exp $
|
|
|
|
Redistribution and use in source and binary forms, with or with out
|
|
modification, are not permitted in outside of SolutionBox Inc.
|
|
|
|
****************************************************************************/
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <iconv.h>
|
|
|
|
#include <httpd.h>
|
|
#include <http_config.h>
|
|
#include <http_protocol.h>
|
|
#include <http_log.h>
|
|
#include <http_request.h>
|
|
#include <http_core.h> /* for ap_construct_url */
|
|
|
|
|
|
#include <apr.h>
|
|
#include <apr_md5.h>
|
|
#include <apr_strings.h>
|
|
#include <apr_hash.h>
|
|
#include <apr_tables.h>
|
|
#include <apr_file_io.h>
|
|
#include <apu_version.h>
|
|
#include <apr_dbd.h>
|
|
#include <mod_dbd.h>
|
|
|
|
|
|
|
|
#include "dav_repos.h"
|
|
#include "dbms.h"
|
|
#include "util.h"
|
|
|
|
|
|
/* Note: the "dav_repos" prefix is mandatory */
|
|
extern module AP_MODULE_DECLARE_DATA dav_repos_module;
|
|
|
|
/*****************************/
|
|
/* common functions */
|
|
|
|
// FreeBSD 6.2 설치된 iconv 경우 iconv에 srcbuf를 const char* 로 받음
|
|
#ifdef __FreeBSD__
|
|
static char *iconv_string(apr_pool_t *p, iconv_t cd, const char *srcbuf, size_t srclen)
|
|
#else // !__FreeBSD__
|
|
static char *iconv_string(apr_pool_t *p, iconv_t cd, char *srcbuf, size_t srclen)
|
|
#endif // __FreeBSD__
|
|
{
|
|
char *outbuf, *marker;
|
|
size_t outlen;
|
|
|
|
if (srclen == 0) {
|
|
#ifdef __FreeBSD__
|
|
return (char *)srcbuf;
|
|
#else // !__FreeBSD__
|
|
return srcbuf;
|
|
#endif // __FreeBSD__
|
|
}
|
|
|
|
/* Allocate space for conversion. Note max bloat factor is 4 of UCS-4 */
|
|
marker = outbuf = (char *)apr_palloc(p, outlen = srclen * 4 + 1);
|
|
|
|
if (outbuf == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* Convert every character within input string. */
|
|
while (srclen > 0) {
|
|
#ifdef __FreeBSD__
|
|
if (iconv(cd, (const char **)&srcbuf, &srclen, &outbuf, &outlen) == (size_t)(-1))
|
|
#else // !__FreeBSD__
|
|
if (iconv(cd, &srcbuf, &srclen, &outbuf, &outlen) == (size_t)(-1))
|
|
#endif // __FreeBSD__
|
|
{
|
|
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
*outbuf = '\0';
|
|
|
|
return marker;
|
|
}
|
|
|
|
// NEW 2019-09-18 huibong 인코딩 처리 관련 신규 추가 (#32584)
|
|
// - URL 인코딩에 대한 판단 오류 상황을 보완하기 위해 인터넷에 유통 중인 소스 중 신뢰성 있는 소스의 기능을 추가
|
|
// - 본 소스는 전달받은 문자열이 UTF-8 인코딩인지를 판단하는 함수로서
|
|
// - android base 소스에 등록된 함수임
|
|
// - 참고자료
|
|
// -- https://android.googlesource.com/platform/frameworks/base/+/master/media/jni/android_media_MediaScanner.cpp
|
|
static bool isValidUtf8( const char * bytes )
|
|
{
|
|
while( *bytes != '\0' )
|
|
{
|
|
unsigned char utf8 = *( bytes++ );
|
|
//ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "isValidUtf8: [%c][%02X][%02X]", utf8, utf8, utf8>>4);
|
|
|
|
// Switch on the high four bits.
|
|
switch( utf8 >> 4 )
|
|
{
|
|
case 0x00:
|
|
case 0x01:
|
|
case 0x02:
|
|
case 0x03:
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x06:
|
|
case 0x07:
|
|
// Bit pattern 0xxx. No need for any extra bytes.
|
|
break;
|
|
|
|
case 0x08:
|
|
case 0x09:
|
|
case 0x0a:
|
|
case 0x0b:
|
|
case 0x0f:
|
|
/*
|
|
* Bit pattern 10xx or 1111, which are illegal start bytes.
|
|
* Note: 1111 is valid for normal UTF-8, but not the
|
|
* modified UTF-8 used here.
|
|
*/
|
|
return false;
|
|
|
|
case 0x0e:
|
|
// Bit pattern 1110, so there are two additional bytes.
|
|
utf8 = *( bytes++ );
|
|
if( ( utf8 & 0xc0 ) != 0x80 ) {
|
|
return false;
|
|
}
|
|
// Fall through to take care of the final byte.
|
|
//FALLTHROUGH_INTENDED;
|
|
case 0x0c:
|
|
case 0x0d:
|
|
// Bit pattern 110x, so there is one additional byte.
|
|
utf8 = *( bytes++ );
|
|
//ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "isValidUtf8: [%c][%02X][%02X]", utf8, utf8, utf8 & 0xc0 );
|
|
|
|
if( ( utf8 & 0xc0 ) != 0x80 ) {
|
|
return false;
|
|
}
|
|
|
|
// ADD 2019-09-18 huibong 연관일감 #21096 관련 회피 기능 추가 ((#32584)
|
|
// - "책" 문자열이 utf-8 로 인식되는 거를 막기 위해 회피하도록 조건 추가
|
|
if( utf8 == 0xa5 ) {
|
|
return false;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// CHG 2019-09-18 huibong URL의 정확한 인코딩 탐지 실패 관련 기능 보완 (#32584)
|
|
// - #32584 에서 UTF-8 기반 url 을 UHC 로 인식하는 문제 발생
|
|
// - UTF-8, UHC 혼합사용으로 인해 정확한 탐지를 실패할 가능성이 존재하지만.....
|
|
// - 이를 조금이라도 보완하기 위해 인코딩 check 로직을 보완함.
|
|
static int is_valid_uhc( char * buf )
|
|
{
|
|
// CHG 2019-09-18 huibong UTF-8 enconding 인지 check 기능 추가 (#32584)
|
|
// - 우선 기본으로 UTF-8 인 요청을 거른다.
|
|
// - 인코딩 특성상 UHC 인데.. UTF-8 로 인식될 가능성이 있다.
|
|
// - 이런 경우에는 isValidUtf8() 함수에 해당 요청에 대한 예외를 추가하는 방법 밖에 없다.
|
|
if( isValidUtf8( buf ) == true )
|
|
{
|
|
//ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "is_valid_uhc: isValidUtf8() return UTF-8 [%s]", buf );
|
|
return 0;
|
|
}
|
|
|
|
// 일단 UTF-8 인코딩이 아니라고 판단된 경우....
|
|
// - 대부분 UHC 이겠지만....
|
|
// - UTF-8 인데.. 예외 처리 등으로 UHC 로 잘못 판정될 가능성 존재하므로.....
|
|
// - iconv 를 이용하여 다시 UHC 인지 다시 확인한다.
|
|
char outBuf[4096] = { 0 };
|
|
|
|
iconv_t cd = iconv_open( "UTF-8", "UHC" );
|
|
if( cd == (iconv_t)( -1 ) )
|
|
{
|
|
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "is_valid_uhc: iconv open failed [%s]", buf );
|
|
return 0;
|
|
}
|
|
|
|
size_t readBytes = strlen( buf );
|
|
size_t writeBytes = sizeof( outBuf );
|
|
|
|
char * in = buf;
|
|
char * out = outBuf;
|
|
if( iconv( cd, (const char **)& in, &readBytes, &out, &writeBytes ) == (size_t)-1 )
|
|
{
|
|
int errorNum = errno;
|
|
iconv_close( cd );
|
|
|
|
// UHC -> UTF-8 로 변환 실패시...
|
|
// - 변환 성공시 UHC 이지만.. 변환 실패시에는 UTF-8 로 판정한다.
|
|
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "is_valid_uhc: iconv UHC->UTF-8 error. reuturn UTF-8 [%d][%s]", errorNum, buf );
|
|
return 0;
|
|
}
|
|
|
|
iconv_close( cd );
|
|
|
|
// 최종 UHC 로 판정한다.
|
|
//ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "is_valid_uhc: return UHC [%s]", buf );
|
|
return 1;
|
|
}
|
|
|
|
|
|
// UTF-8 -> Database Character Set
|
|
char* transformDBCharacter(request_rec *r, char* srcbuf, char *prefixmsg )
|
|
{
|
|
char *ret = NULL;
|
|
char *srccharset = NULL, *destcharset = NULL;
|
|
dav_repos_server_conf *conf = NULL;
|
|
conf = dav_repos_get_server_conf(r->server);
|
|
iconv_t cd;
|
|
|
|
if( conf == NULL )
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"%s: dav_repos_get_server_conf NULL. return srcbuf", prefixmsg);
|
|
return srcbuf;
|
|
}
|
|
|
|
if( conf->db_charset == NULL )
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"%s: config DavProviderDBCharset set NULL. return srcbuf", prefixmsg);
|
|
return srcbuf;
|
|
}
|
|
|
|
destcharset = (char *) conf->db_charset;
|
|
|
|
// Database Character UTF-8 지원 시 해당 로직은 수행하지 않음
|
|
if (strcmp( destcharset, "UTF-8") == 0)
|
|
{
|
|
return srcbuf;
|
|
}
|
|
|
|
// check UHC Character
|
|
if ( is_valid_uhc(srcbuf) == 1)
|
|
{
|
|
ap_log_error( APLOG_MARK, APLOG_ERR, 0, NULL, "transformDBCharacter: url encoding is UHC [%s][%s]", prefixmsg, srcbuf);
|
|
srccharset = "UHC";
|
|
}
|
|
else
|
|
{
|
|
//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "transformDBCharacter: url encoding is UTF-8 [%s][%s]", prefixmsg, srcbuf);
|
|
srccharset = "UTF-8";
|
|
}
|
|
|
|
// unknown Character set and return srcbuf
|
|
if( srccharset == NULL )
|
|
{
|
|
return srcbuf;
|
|
}
|
|
|
|
// compare character set
|
|
if( strcmp(srccharset, destcharset) == 0 )
|
|
{
|
|
//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s: same Character [%s]", prefixmsg, srcbuf);
|
|
return srcbuf;
|
|
}
|
|
|
|
// transform src character set -> DB character set
|
|
cd = iconv_open(destcharset, srccharset);
|
|
if( cd == (iconv_t)(-1))
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s: iconv open failed [%s]", prefixmsg, srcbuf);
|
|
ret = apr_pstrdup(r->pool, srcbuf);
|
|
}
|
|
else
|
|
{
|
|
ret = iconv_string(r->pool, cd, srcbuf, strlen(srcbuf));
|
|
if (ret == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s: iconv error [%s]",prefixmsg, srcbuf);
|
|
ret = apr_pstrdup(r->pool, srcbuf);
|
|
}
|
|
|
|
iconv_close(cd);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
// Database Character Set -> UTF-8
|
|
char* transformUTF8(request_rec *r, char* srcbuf, char *prefixmsg )
|
|
{
|
|
char *ret = NULL;
|
|
char *srccharset = NULL, *destcharset = NULL;
|
|
dav_repos_server_conf *conf = NULL;
|
|
conf = dav_repos_get_server_conf(r->server);
|
|
iconv_t cd;
|
|
|
|
destcharset = "UTF-8";
|
|
|
|
if( conf == NULL )
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"%s: dav_repos_get_server_conf NULL. return srcbuf", prefixmsg);
|
|
return srcbuf;
|
|
}
|
|
|
|
if( conf->db_charset == NULL )
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
|
|
"%s: config DavProviderDBCharset set NULL. return srcbuf", prefixmsg);
|
|
return srcbuf;
|
|
}
|
|
|
|
// check UHC Character
|
|
if (is_valid_uhc(srcbuf) == 1)
|
|
{
|
|
srccharset = "UHC";
|
|
}
|
|
else
|
|
{
|
|
srccharset = "UTF-8";
|
|
}
|
|
|
|
// compare character set
|
|
if( strcmp(srccharset, destcharset) == 0 )
|
|
{
|
|
return srcbuf;
|
|
}
|
|
|
|
// transform DB character set -> UTF-8
|
|
cd = iconv_open(destcharset, srccharset);
|
|
if( cd == (iconv_t)(-1))
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s: iconv open failed [%s]", prefixmsg, srcbuf);
|
|
ret = apr_pstrdup(r->pool, srcbuf);
|
|
}
|
|
else
|
|
{
|
|
ret = iconv_string(r->pool, cd, srcbuf, strlen(srcbuf));
|
|
if (ret == NULL)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "%s: iconv error[%s]", prefixmsg, srcbuf);
|
|
ret = apr_pstrdup(r->pool, srcbuf);
|
|
}
|
|
|
|
iconv_close(cd);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int dav_repos_remove_base_uri(const char *base_uri, const char *req_uri, char *result)
|
|
{
|
|
int nCount = 0;
|
|
int req_uri_length = 0;
|
|
|
|
if((base_uri == NULL) || (req_uri == NULL) || (result == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
req_uri_length = strlen(req_uri);
|
|
if(req_uri_length == 1)
|
|
{
|
|
if((*req_uri == '/') || (*req_uri == '\0') || (*req_uri == ' '))
|
|
{
|
|
result[0] = '/';
|
|
result[1] = '\0';
|
|
}
|
|
else
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
else if(req_uri_length == 0)
|
|
{
|
|
return -3;
|
|
}
|
|
|
|
while((*req_uri != '\0') && (*base_uri != '\0'))
|
|
{
|
|
if(*base_uri == *req_uri)
|
|
{
|
|
base_uri++;
|
|
req_uri++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
while(*req_uri != '\0')
|
|
{
|
|
result[nCount++] = *req_uri++;
|
|
}
|
|
|
|
result[nCount] = '\0';
|
|
return 1;
|
|
}
|
|
|
|
|
|
int remove_user_root_dir_from_fake_uri(const char *pcszFakeURI, char *pURI)
|
|
{
|
|
int nCount = 0;
|
|
int sCount = 0;
|
|
char sztmpBuffer[MaxSizeOfPathLength];
|
|
|
|
if(pcszFakeURI == NULL)
|
|
{
|
|
return -1;
|
|
}
|
|
if(strlen(pcszFakeURI) > MaxSizeOfPathLength)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
while(*pcszFakeURI != '\0')
|
|
{
|
|
if(*pcszFakeURI == '/')
|
|
{
|
|
sCount++;
|
|
if(sCount == 2)
|
|
{
|
|
nCount = 0;
|
|
memset(sztmpBuffer, 0, MaxSizeOfPathLength);
|
|
sztmpBuffer[nCount++] = *pcszFakeURI++;
|
|
}
|
|
}
|
|
sztmpBuffer[nCount++] = *pcszFakeURI++;
|
|
}
|
|
|
|
sztmpBuffer[nCount] = '\0';
|
|
snprintf(pURI, MaxSizeOfPathLength, "%s", sztmpBuffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int get_filename_in_path(const char *pcszPath, char *pszPathName, char *pszFileName)
|
|
{
|
|
int nCount = 0;
|
|
char sztmpBuffer[MaxSizeOfPathLength];
|
|
|
|
if((pcszPath == NULL) || (pszFileName == NULL) || (pszPathName == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
if(strlen(pcszPath) > MaxSizeOfPathLength)
|
|
{
|
|
return -2;
|
|
}
|
|
|
|
memset(sztmpBuffer, 0, MaxSizeOfPathLength);
|
|
while(*pcszPath != '\0')
|
|
{
|
|
if(*pcszPath == '/')
|
|
{
|
|
sztmpBuffer[nCount++] = *pcszPath++;
|
|
if(*pcszPath == '\0')
|
|
{
|
|
break;
|
|
}
|
|
|
|
sztmpBuffer[nCount] = '\0';
|
|
//DBG1("get_filename_in_path::sztmpBuffer = %s", sztmpBuffer);
|
|
strncat(pszPathName, sztmpBuffer, MaxSizeOfPathLength - strlen(pszPathName));
|
|
nCount = 0;
|
|
memset(sztmpBuffer, 0, MaxSizeOfPathLength);
|
|
}
|
|
sztmpBuffer[nCount++] = *pcszPath++;
|
|
}
|
|
|
|
sztmpBuffer[nCount] = '\0';
|
|
snprintf(pszFileName, MaxSizeOfPathLength, "%s", sztmpBuffer);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
// CHG 2010-08-10 huibong
|
|
// Hash 정보 생성 처리시 생성 결과를 static 변수에 저장하고
|
|
// 해당 변수를 반환처리 하는 경우 ..
|
|
// 동시간 접근시 Lock 을 사용하지 않게 되면 문제가 발생하게 됨. ( File Name에 대한 Hash 정보가 동일하게 생성)
|
|
// 하지만 Lock 을 처리속도에 영향을 미칠수 있으므로
|
|
// 결과 값을 저장할 출력변수를 매개변수로 전달받도록 수정처리 한다.
|
|
//char *get_hashed_filepath(const char *plain_filepath)
|
|
bool get_hashed_filepath( const char *plain_filepath, char * result, int result_length)
|
|
{
|
|
// 매개변수에 대한 검증 처리
|
|
if( plain_filepath == NULL || result == NULL || result_length < (APR_MD5_DIGESTSIZE * 2 + 1))
|
|
return false;
|
|
else
|
|
{
|
|
// 출력값을 저장할 변수가 적합한 경우.
|
|
int i;
|
|
unsigned char digest[APR_MD5_DIGESTSIZE];
|
|
apr_md5(digest, (const unsigned char *) plain_filepath, strlen(plain_filepath));
|
|
|
|
// 화면에 표시 가능하도록 Hex 처리.
|
|
for (i = 0; i < APR_MD5_DIGESTSIZE; i++)
|
|
apr_snprintf((char *) &result[i + i], 3, "%02x", digest[i]);
|
|
|
|
result[APR_MD5_DIGESTSIZE * 2] = '\0';
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/* split user_login_id@partner_login_id into */
|
|
/* user_login_id, partner_login_id */
|
|
|
|
/* 2007. 07. 30: Elenoa Lazyfake
|
|
* r->user format changed: for classified traffic manage
|
|
* (in Makefile, __CLASSIFIED_TRAFFIC_MANAGE__)
|
|
* from: tranid@userid@sessionkey
|
|
* to: tranid.classid@userid@sessionkey
|
|
*/
|
|
int at_split(const char *pszAcctInfo, acct_info *pAcctInfo)
|
|
{
|
|
int fFound = 0;
|
|
int chCount = 0;
|
|
char sztmpBuffer[MaxSizeOfAcctSession + 1];
|
|
|
|
if((pszAcctInfo == NULL) || (pAcctInfo == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/* 0nd step : clear acct_info buffer */
|
|
memset((char *)pAcctInfo, 0, sizeof(acct_info));
|
|
|
|
/* 1st step : parse user login id */
|
|
fFound = 0;
|
|
chCount = 0;
|
|
memset(sztmpBuffer, 0, MaxSizeOfAcctVolume);
|
|
while(*pszAcctInfo != '\0')
|
|
{
|
|
if(*pszAcctInfo == '@')
|
|
{
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szVolumeID, MaxSizeOfAcctVolume, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #1(end) = %s", sztmpBuffer);
|
|
fFound = -1;
|
|
break;
|
|
}
|
|
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
|
|
if(*pszAcctInfo == '.')
|
|
{
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szVolumeID, MaxSizeOfAcctVolume, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #1(cont') = %s", sztmpBuffer);
|
|
fFound = 1;
|
|
break;
|
|
}
|
|
#endif
|
|
sztmpBuffer[chCount++] = *pszAcctInfo++;
|
|
}
|
|
|
|
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
|
|
if (fFound == -1)
|
|
{
|
|
sprintf(pAcctInfo->szTCClassID, "0");
|
|
goto second_step;
|
|
}
|
|
#endif
|
|
|
|
if (fFound == 0)
|
|
{
|
|
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
|
|
pAcctInfo->szTCClassID[0] = '\0';
|
|
#endif
|
|
return -2;
|
|
}
|
|
|
|
#ifdef __CLASSIFIED_TRAFFIC_MANAGE__
|
|
fFound = 0;
|
|
chCount = 0;
|
|
pszAcctInfo++;
|
|
memset(sztmpBuffer, 0, MaxSizeOfAcctVolume);
|
|
|
|
while(*pszAcctInfo != '\0')
|
|
{
|
|
if(*pszAcctInfo == '@')
|
|
{
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szTCClassID, MaxSizeOfAcctVolume, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #1(cid) = %s", sztmpBuffer);
|
|
fFound = 1;
|
|
break;
|
|
}
|
|
sztmpBuffer[chCount++] = *pszAcctInfo++;
|
|
}
|
|
if(fFound != 1)
|
|
{
|
|
return -3;
|
|
}
|
|
|
|
second_step:
|
|
#endif
|
|
/* 2nd step : parse partner login id */
|
|
fFound = 0;
|
|
chCount = 0;
|
|
pszAcctInfo++;
|
|
memset(sztmpBuffer, 0, MaxSizeOfAcctUserID);
|
|
|
|
while(*pszAcctInfo != '\0')
|
|
{
|
|
if(*pszAcctInfo == '@')
|
|
{
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szUserID, MaxSizeOfAcctUserID, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #2 = %s", sztmpBuffer);
|
|
fFound = 1;
|
|
break;
|
|
}
|
|
sztmpBuffer[chCount++] = *pszAcctInfo++;
|
|
}
|
|
|
|
if(fFound != 1)
|
|
{
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szUserID, MaxSizeOfAcctUserID, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #2 = %s, #3 none", sztmpBuffer);
|
|
pAcctInfo->szSessionID[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
/* 3rd step : parse session id */
|
|
chCount = 0;
|
|
memset(sztmpBuffer, 0, MaxSizeOfAcctSession);
|
|
|
|
pszAcctInfo++;
|
|
while(*pszAcctInfo != '\0')
|
|
{
|
|
sztmpBuffer[chCount++] = *pszAcctInfo++;
|
|
}
|
|
sztmpBuffer[chCount] = '\0';
|
|
snprintf(pAcctInfo->szSessionID, MaxSizeOfAcctSession, "%s", sztmpBuffer);
|
|
DBG1("at_split::sztmpBuffer #3 = %s", sztmpBuffer);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int check_string(char *to, const char *from, size_t length)
|
|
{
|
|
int nCount = 0;
|
|
char tmpBuff[length];
|
|
|
|
if((to == NULL) || (from == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while((*from != '\0') && (length > 0))
|
|
{
|
|
if(*from != '\'')
|
|
{
|
|
tmpBuff[nCount++] = *from;
|
|
}
|
|
from++;
|
|
length--;
|
|
}
|
|
|
|
tmpBuff[nCount] = '\0';
|
|
snprintf(to, nCount + 1, "%s", tmpBuff);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
/*************************/
|
|
/* configuration support */
|
|
|
|
dav_repos_server_conf *dav_repos_get_server_conf( server_rec *s )
|
|
{
|
|
if( s == NULL )
|
|
return NULL;
|
|
else
|
|
return ap_get_module_config(s->module_config, &dav_repos_module);
|
|
}
|
|
|
|
inline void dav_spin_wait(int vsleep)
|
|
{
|
|
struct timeval tv;
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = vsleep;
|
|
select (0, NULL, NULL, NULL, &tv);
|
|
}
|
|
|
|
ap_dbd_t *dav_repos_get_db(request_rec *r)
|
|
{
|
|
ap_dbd_t *db;
|
|
|
|
/* loop until get acquire db session */
|
|
if( (db = ap_dbd_open(r->server->process->pool, r->server)) != NULL )
|
|
{
|
|
return db;
|
|
}
|
|
|
|
/* can reach here? */
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "OPENDAV:dav_repos_get_db database connection pool error.");
|
|
return NULL;
|
|
}
|
|
|
|
void dav_repos_release_db(request_rec *r, ap_dbd_t *db, int o_rv)
|
|
{
|
|
int retval;
|
|
|
|
{
|
|
ap_dbd_close(r->server, db);
|
|
retval = OK;
|
|
}
|
|
|
|
if (retval == !OK)
|
|
{
|
|
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "OPENDAV: database not properly released");
|
|
}
|
|
}
|
|
|
|
|
|
int dav_repos_begin_trans(const char *func, request_rec *r, ap_dbd_t *db, apr_dbd_transaction_t **trans)
|
|
{
|
|
int rv;
|
|
|
|
rv = apr_dbd_transaction_start(db->driver, r->pool, db->handle, trans);
|
|
if (rv)
|
|
{
|
|
char errbuf[1024];
|
|
|
|
sprintf(errbuf, "%s: begin transaction", func);
|
|
db_error_message(db, errbuf, rv);
|
|
dav_repos_release_db(r, db, rv);
|
|
//apr_thread_rwlock_unlock(db_lock);
|
|
return -20;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int dav_repos_end_trans(const char *func, request_rec *r, ap_dbd_t *db, apr_dbd_transaction_t *trans)
|
|
{
|
|
int rv;
|
|
|
|
rv = apr_dbd_transaction_end(db->driver, r->pool, trans);
|
|
if (rv)
|
|
{
|
|
char errbuf[1024];
|
|
|
|
sprintf(errbuf, "%s: end transaction", func);
|
|
db_error_message(db, errbuf, rv);
|
|
dav_repos_release_db(r, db, rv);
|
|
//apr_thread_rwlock_unlock(db_lock);
|
|
return -21;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Note: picked up from ap_gm_timestr_822() */
|
|
/* NOTE: buf must be at least DAV_TIMEBUF_SIZE chars in size */
|
|
void dav_repos_format_time(int style, apr_time_t sec, char *buf)
|
|
{
|
|
apr_time_exp_t tms;
|
|
|
|
DBG1("dav_repos_format_time:sec = %" APR_TIME_T_FMT "", sec);
|
|
|
|
(void) apr_time_exp_gmt(&tms, sec);
|
|
|
|
TRACE();
|
|
|
|
if (style == DAV_STYLE_ISO8601)
|
|
{
|
|
/* ### should we use "-00:00" instead of "Z" ?? */
|
|
|
|
/* 20 chars plus null term */
|
|
sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2dZ",
|
|
tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday,
|
|
tms.tm_hour, tms.tm_min, tms.tm_sec);
|
|
}
|
|
else
|
|
{
|
|
/* RFC 822 date format; as strftime '%a, %d %b %Y %T GMT' */
|
|
/* 29 chars plus null term */
|
|
sprintf(buf,
|
|
"%s, %.2d %s %d %.2d:%.2d:%.2d GMT",
|
|
apr_day_snames[tms.tm_wday],
|
|
tms.tm_mday, apr_month_snames[tms.tm_mon],
|
|
tms.tm_year + 1900, tms.tm_hour, tms.tm_min, tms.tm_sec);
|
|
}
|
|
|
|
DBG1("dav_repos_format_time:buf = %s", buf);
|
|
}
|
|
|
|
|
|
const char *dav_repos_build_ns_name_key(const char *ns, const char *name, apr_pool_t * pool)
|
|
{
|
|
TRACE();
|
|
|
|
/* Woops */
|
|
if (ns == NULL || name == NULL || pool == NULL)
|
|
return NULL;
|
|
|
|
if (strlen(ns)==0)
|
|
ns=" "; /* No namespace */
|
|
|
|
return apr_psprintf(pool, "%s\t%s", ns, name);
|
|
}
|
|
|
|
|
|
void dav_repos_get_ns_name_key(const char *key, dav_prop_name * pname, apr_pool_t * pool)
|
|
{
|
|
char *str;
|
|
pname->ns = pname->name = NULL;
|
|
|
|
/* Woops */
|
|
if (key == NULL || pool == NULL)
|
|
return;
|
|
|
|
str = apr_pstrdup(pool, key);
|
|
pname->ns = strtok(str, "\t");
|
|
pname->name = strtok(NULL, "\t");
|
|
}
|
|
|
|
|
|
/* Make XML response */
|
|
dav_response *dav_repos_mkresponse(dav_repos_resource * db_r)
|
|
{
|
|
int i;
|
|
char *s = NULL;
|
|
const char *ns;
|
|
apr_text_header hdr = { 0 };
|
|
apr_text_header hdr_ns = { 0 };
|
|
dav_response *res = apr_pcalloc(db_r->p, sizeof(*res));
|
|
dav_repos_property *dead_prop;
|
|
char *ns_use = apr_pcalloc(db_r->p, DAV_REPOS_MAX_NAMESPACE); /* Maximul namespaces */
|
|
|
|
/* Resopnse Example
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<D:multistatus xmlns:D="DAV:">
|
|
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://localhost/repos/">
|
|
<D:href>/</D:href>
|
|
<D:propstat>
|
|
<D:prop>
|
|
<lp1:resourcetype><D:collection/></lp1:resourcetype>
|
|
<lp1:creationdate>2001-10-22T02:46:33Z</lp1:creationdate>
|
|
<lp1:getlastmodified>Mon, 22 Oct 2001 02:46:33 GMT</lp1:getlastmodified>
|
|
<lp1:getetag>"59272-1000-7e1c7440"</lp1:getetag>
|
|
<D:supportedlock>
|
|
<D:lockentry>
|
|
<D:lockscope><D:exclusive/></D:lockscope>
|
|
<D:locktype><D:write/></D:locktype>
|
|
</D:lockentry>
|
|
<D:lockentry>
|
|
<D:lockscope><D:shared/></D:lockscope>
|
|
<D:locktype><D:write/></D:locktype>
|
|
</D:lockentry>
|
|
</D:supportedlock>
|
|
<D:lockdiscovery/>
|
|
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
|
|
</D:prop>
|
|
<D:status>HTTP/1.1 200 OK</D:status>
|
|
</D:propstat>
|
|
</D:response>
|
|
</D:multistatus>
|
|
*/
|
|
|
|
/* Make fake data for test */
|
|
res->href = db_r->m_uri;
|
|
res->status = 200;
|
|
|
|
TRACE();
|
|
|
|
DBG0("dav_repos_mkresponse:");
|
|
|
|
/* Generate namespace first */
|
|
/* Dead properties */
|
|
for (dead_prop = db_r->pr; dead_prop; dead_prop = dead_prop->next)
|
|
{
|
|
ns_use[(int) dead_prop->m_ns_id] = 1;
|
|
}
|
|
|
|
/* Add namespace for dead properties */
|
|
for (i = 0; i < DAV_REPOS_MAX_NAMESPACE; i++)
|
|
{
|
|
if (ns_use[i] == 1)
|
|
{
|
|
ns = dbms_get_ns(db_r, i);
|
|
if (ns == NULL || strlen(ns) == 0)
|
|
{
|
|
ns_use[i] = -1; /* nullns */
|
|
}
|
|
else
|
|
{
|
|
s = apr_psprintf(db_r->p, " xmlns:%s%d=\"%s\"", "ns", i, ns);
|
|
apr_text_append(db_r->p, &hdr_ns, s);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Make XML here */
|
|
|
|
apr_text_append(db_r->p, &hdr, "<D:propstat>" DEBUG_CR "<D:prop>" DEBUG_CR);
|
|
|
|
/* Start prop */
|
|
|
|
/* Dead properties */
|
|
for (dead_prop = db_r->pr; dead_prop; dead_prop = dead_prop->next)
|
|
{
|
|
/* Null ns need xmlns="" */
|
|
if (ns_use[(int) dead_prop->m_ns_id] == -1)
|
|
{
|
|
s = apr_psprintf(db_r->p, "<%s xmlns=\"\">%s</%s>" DEBUG_CR,
|
|
dead_prop->m_propname, dead_prop->m_propvalue,
|
|
dead_prop->m_propname);
|
|
}
|
|
else
|
|
{
|
|
s = apr_psprintf(db_r->p, "<ns%ld:%s>%s</ns%ld:%s>" DEBUG_CR,
|
|
dead_prop->m_ns_id, dead_prop->m_propname,
|
|
dead_prop->m_propvalue,
|
|
dead_prop->m_ns_id, dead_prop->m_propname);
|
|
}
|
|
|
|
apr_text_append(db_r->p, &hdr, s);
|
|
ns_use[(int) dead_prop->m_ns_id] = 1;
|
|
}
|
|
|
|
/* Live properties */
|
|
if (db_r->lpr_hash) /* build it before mkresponse */
|
|
{
|
|
long klen;
|
|
const char *stmp;
|
|
const char *key, *val;
|
|
apr_hash_index_t *hindex;
|
|
|
|
/* Read live props from hash */
|
|
for (hindex = apr_hash_first(db_r->p, db_r->lpr_hash); hindex; hindex = apr_hash_next(hindex))
|
|
{
|
|
apr_hash_this(hindex, (void *) &key, &klen, (void *) &val);
|
|
stmp = apr_psprintf(db_r->p, "<D:%s>%s</D:%s>" DEBUG_CR, key, val, key);
|
|
DBG1("dav_repos_mkresponse: %s", stmp);
|
|
apr_text_append(db_r->p, &hdr, stmp);
|
|
}
|
|
}
|
|
|
|
/* Lock discovery print, if we have */
|
|
/* FIXME : Do we really need lock info for search */
|
|
#if 0
|
|
apr_text_append(db_r->p, &hdr, "<lp1:lockdiscovery>" DEBUG_CR);
|
|
if (db_r->lockdiscovery)
|
|
apr_text_append(db_r->p, &hdr, db_r->lockdiscovery);
|
|
apr_text_append(db_r->p, &hdr, "</lp1:lockdiscovery>" DEBUG_CR);
|
|
|
|
/* Supported lock */
|
|
if (db_r->supportedlock)
|
|
apr_text_append(db_r->p, &hdr, db_r->supportedlock);
|
|
#endif
|
|
|
|
/* Closing */
|
|
apr_text_append(db_r->p, &hdr,
|
|
"</D:prop>" DEBUG_CR
|
|
"<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
|
|
"</D:propstat>" DEBUG_CR);
|
|
|
|
/*
|
|
** name space set up
|
|
** Better way??
|
|
*/
|
|
s = apr_psprintf(db_r->p, " xmlns:%s%d=\"%s\"", "lp", 0, "DAV:");
|
|
apr_text_append(db_r->p, &hdr_ns, s);
|
|
|
|
s = apr_psprintf(db_r->p, " xmlns:%s%d=\"%s\"", "lp", 1, "DAV:");
|
|
apr_text_append(db_r->p, &hdr_ns, s);
|
|
|
|
res->propresult.propstats = hdr.first;
|
|
res->propresult.xmlns = hdr_ns.first;
|
|
|
|
return res;
|
|
}
|
|
|
|
/* Build dead property hash
|
|
* Build the hash before makeresponse
|
|
*/
|
|
void dav_repos_build_pr_hash(dav_repos_resource * db_r)
|
|
{
|
|
dav_repos_property *dead_prop;
|
|
|
|
TRACE();
|
|
|
|
/* Let's build hash */
|
|
db_r->pr_hash = apr_hash_make(db_r->p);
|
|
|
|
/* Dead properties */
|
|
for (dead_prop = db_r->pr; dead_prop; dead_prop = dead_prop->next)
|
|
{
|
|
const char *ns = dbms_get_ns(db_r, dead_prop->m_ns_id);
|
|
const char *key = dav_repos_build_ns_name_key(ns, dead_prop->m_propname, db_r->p);
|
|
apr_hash_set(db_r->pr_hash, key, APR_HASH_KEY_STRING, dead_prop);
|
|
//DBG2("KEY: [%s]%s", key, dead_prop->m_propname);
|
|
}
|
|
|
|
}
|
|
|
|
/* Build live property */
|
|
void dav_repos_build_lpr_hash(dav_repos_resource *db_r)
|
|
{
|
|
const char *s;
|
|
dav_repos_server_conf *dsc = NULL;
|
|
|
|
/* an HTTP-date can be 29 chars plus a null term */
|
|
/* a 64-bit size can be 20 chars plus a null term */
|
|
char date[DAV_TIMEBUF_SIZE];;
|
|
|
|
TRACE();
|
|
|
|
dsc = dav_repos_get_server_conf(db_r->r->server);
|
|
if (!dsc)
|
|
return;
|
|
|
|
/* Let's build hash */
|
|
db_r->lpr_hash = apr_hash_make(db_r->p);
|
|
|
|
/* is directory */
|
|
if (db_r->m_resource_type == dav_repos_COLLECTION)
|
|
{
|
|
apr_hash_set(db_r->lpr_hash, "resourcetype", APR_HASH_KEY_STRING, "<D:collection/>");
|
|
}
|
|
else
|
|
{
|
|
apr_hash_set(db_r->lpr_hash, "resourcetype", APR_HASH_KEY_STRING, "");
|
|
}
|
|
|
|
s = apr_psprintf(db_r->p, "%" APR_INT64_T_FMT "", db_r->m_get_content_length);
|
|
apr_hash_set(db_r->lpr_hash, "getcontentlength", APR_HASH_KEY_STRING, s);
|
|
|
|
DBG1("dav_repos_build_lpr_hash:db_r->m_creation_date= %" APR_INT64_T_FMT "", db_r->m_creation_date);
|
|
/* set live properties */
|
|
dav_repos_format_time(DAV_STYLE_ISO8601, db_r->m_creation_date, date);
|
|
apr_hash_set(db_r->lpr_hash, "creationdate", APR_HASH_KEY_STRING, apr_pstrdup(db_r->p, date));
|
|
|
|
DBG1("dav_repos_build_lpr_hash:db_r->m_get_lastmodified = %" APR_INT64_T_FMT "", db_r->m_get_lastmodified);
|
|
dav_repos_format_time(DAV_STYLE_RFC822, db_r->m_get_lastmodified, date);
|
|
apr_hash_set(db_r->lpr_hash, "getlastmodified", APR_HASH_KEY_STRING, apr_pstrdup(db_r->p, date));
|
|
|
|
apr_hash_set(db_r->lpr_hash, "getetag", APR_HASH_KEY_STRING, dav_repos_getetag_dbr(db_r));
|
|
|
|
apr_hash_set(db_r->lpr_hash, "getcontenttype", APR_HASH_KEY_STRING, db_r->m_get_content_type ? db_r->m_get_content_type : "");
|
|
|
|
DBG2("dav_repos_build_lpr_hash:db_r->m_host_name=%s dsc->host_name=%s", db_r->m_host_name, dsc->host_name);
|
|
|
|
/* CHG 2010-07-02 huibong
|
|
* NetCache 상에서 PROFIND 에 대한 결과 요청시 원본 host_name 정보를 무조건 입력해서 보낼도록 수정
|
|
* 기존 양방향과 호환을 위해 User-Agent String 상에 NetCache 가 존재하는 경우에만 처리하도록 함.
|
|
* 양방향에서 현 장비에 해당 파일이 존재하는 경우 Connection 재사용을 위해 Host Name 정보를 보내지 않음.
|
|
*/
|
|
/*
|
|
apr_hash_set(db_r->lpr_hash, "source", APR_HASH_KEY_STRING,
|
|
(db_r->m_host_name && strcmp(db_r->m_host_name, dsc->host_name) ?
|
|
apr_pstrdup(db_r->p, db_r->m_host_name) : ""));
|
|
*/
|
|
if( db_r->m_host_name != NULL ) // 원본 파일에 대한 Host Name 정보가 존재하는 경우
|
|
{
|
|
// 원본 Host Name 과 현재 장비의 Host Name 이 틀린 경우 => Host Name 정보 전달.
|
|
if( strcmp(db_r->m_host_name, dsc->host_name) != 0 )
|
|
{
|
|
apr_hash_set(db_r->lpr_hash, "source", APR_HASH_KEY_STRING, apr_pstrdup(db_r->p, db_r->m_host_name));
|
|
}
|
|
else
|
|
{
|
|
// NetCache Agent 인지를 확인하기 위해 PROFPIND Header 의 User-Agent 정보 검사.
|
|
const char * userAgent = NULL;
|
|
userAgent = apr_table_get( db_r->r->headers_in, "User-Agent");
|
|
|
|
if( userAgent != NULL && (strncmp(userAgent, "NetCache", 8)==0) )
|
|
{
|
|
// User-Agent 정보가 NetCache 로 시작하는 경우 -> 무조건 Host Name 정보를 입력하여 전달.
|
|
//ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,"dav_repos_build_lpr_hash: User-Agent[%s] source[%s]", userAgent, db_r->m_host_name);
|
|
apr_hash_set(db_r->lpr_hash, "source", APR_HASH_KEY_STRING, apr_pstrdup(db_r->p, db_r->m_host_name));
|
|
}
|
|
else
|
|
{
|
|
// 기존 양방향 Client 인 경우 Host Name 정보와 현재 장비가 동일한 하면 => 빈 문자열 전달.
|
|
apr_hash_set(db_r->lpr_hash, "source", APR_HASH_KEY_STRING, "");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 원본 파일에 대한 Host Name 정보가 존재하지 않는 경우 빈값을 전달처리
|
|
apr_hash_set(db_r->lpr_hash, "source", APR_HASH_KEY_STRING, "");
|
|
}
|
|
|
|
// 2014.07.09 : 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
|
|
apr_hash_set(db_r->lpr_hash, "getcontentlanguage", APR_HASH_KEY_STRING, "");
|
|
|
|
}
|
|
|
|
/*# FIXME : This is a insert lock info for search and prop.
|
|
** Do we really need a lock info when we search ?
|
|
** Then we should make params in search semewhere.
|
|
**
|
|
** Need to move find_live and live props
|
|
*/
|
|
dav_error *dav_repos_insert_lock_prop(const dav_walk_params * params, dav_repos_resource * db_r)
|
|
{
|
|
dav_error *err;
|
|
dav_resource *resource = NULL;
|
|
|
|
//dav_walker_ctx *ctx = params->walk_ctx;
|
|
|
|
TRACE();
|
|
|
|
/* Initilize */
|
|
// 2014.07.09 : 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
|
|
|
|
if (params->lockdb != NULL)
|
|
{
|
|
dav_lock *locks = NULL;
|
|
|
|
/*
|
|
* FIXME : We don't have a resource here
|
|
* Our lock hook will use only uri and exist filed in resource
|
|
*/
|
|
resource = apr_pcalloc(db_r->p, sizeof(*resource));
|
|
resource->exists = 1;
|
|
resource->uri = db_r->m_fake_uri;
|
|
|
|
if ((err = dav_lock_query(params->lockdb, resource, &locks)) != NULL)
|
|
{
|
|
return dav_push_error(db_r->p, err->status, 0,
|
|
"DAV:lockdiscovery could not be "
|
|
"determined due to a problem fetching "
|
|
"the locks for this resource.", err);
|
|
}
|
|
|
|
/* fast-path the no-locks case */
|
|
if (locks)
|
|
{
|
|
/*
|
|
** This may modify the buffer. value may point to
|
|
** wb_lock.pbuf or a string constant.
|
|
*/
|
|
// 2014.07.09 : 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
|
|
//db_r->m_lock_discovery = dav_lock_get_activelock(ctx->r, locks, NULL);
|
|
|
|
/* Do we need strdup here */
|
|
/* db_r->lockdiscovery = apr_pstrdup(db_r->p, wb_lock.buf); */
|
|
}
|
|
|
|
/*
|
|
* Get supported lock info
|
|
* Our lock hook will not use resource though.
|
|
*/
|
|
// 2014.07.09 : 사용되지 않는 컬럼 정리(get_content_language,get_etag,supported_lock,lock_discovery)
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* make sure the pathname does not have a trailing "/" */
|
|
void dav_repos_no_trail(char *str)
|
|
{
|
|
int len = strlen(str);
|
|
while (len > 1 && str[len - 1] == '/')
|
|
{
|
|
str[len - 1] = '\0';
|
|
len = strlen(str);
|
|
}
|
|
|
|
TRACE();
|
|
}
|
|
|
|
|
|
int dav_repos_remove_unsafe_chars(const char *pOld, char *pNew)
|
|
{
|
|
int nCount = 0;
|
|
|
|
if((pOld == NULL) || (pNew == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while(*pOld != '\0')
|
|
{
|
|
if((*pOld == '\'') || (*pOld == '\\'))
|
|
{
|
|
pOld++;
|
|
}
|
|
else
|
|
{
|
|
pNew[nCount++] = *pOld++;
|
|
}
|
|
}
|
|
|
|
pNew[nCount] = '\0';
|
|
return 1;
|
|
}
|
|
|
|
|
|
int dav_repos_replace_unsafe_chars(const char *pOld, char *pNew)
|
|
{
|
|
if ((pOld == NULL) || (pNew == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
char const * const pattern = "'";
|
|
char const * const replacement = "''";
|
|
|
|
size_t const replen = strlen(replacement);
|
|
size_t const patlen = strlen(pattern);
|
|
|
|
const char * oriptr;
|
|
const char * patloc;
|
|
|
|
memset(pNew, 0x00, sizeof(*pNew));
|
|
for (oriptr = pOld; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
|
|
{
|
|
size_t const skplen = patloc - oriptr;
|
|
// copy the section until the occurence of the pattern
|
|
strncpy(pNew, oriptr, skplen);
|
|
pNew += skplen;
|
|
// copy the replacement
|
|
strncpy(pNew, replacement, replen);
|
|
pNew += replen;
|
|
}
|
|
|
|
// copy the rest of the string.
|
|
strcpy(pNew, oriptr);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int dav_repos_restore_unsafe_chars(const char *pOld, char *pNew)
|
|
{
|
|
|
|
if ((pOld == NULL) || (pNew == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
char const * const pattern = "''";
|
|
char const * const replacement = "'";
|
|
|
|
size_t const replen = strlen(replacement);
|
|
size_t const patlen = strlen(pattern);
|
|
|
|
const char * oriptr;
|
|
const char * patloc;
|
|
|
|
memset(pNew, 0x00, sizeof(*pNew));
|
|
for (oriptr = pOld; (patloc = strstr(oriptr, pattern)); oriptr = patloc + patlen)
|
|
{
|
|
size_t const skplen = patloc - oriptr;
|
|
// copy the section until the occurence of the pattern
|
|
strncpy(pNew, oriptr, skplen);
|
|
pNew += skplen;
|
|
// copy the replacement
|
|
strncpy(pNew, replacement, replen);
|
|
pNew += replen;
|
|
}
|
|
|
|
// copy the rest of the string.
|
|
strcpy(pNew, oriptr);
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
int dav_repos_replace_multi_slash_chars(const char *pOld, char *pNew)
|
|
{
|
|
int nCount = 0;
|
|
int slash_detect = 0;
|
|
|
|
if ((pOld == NULL) || (pNew == NULL))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
while (*pOld != '\0')
|
|
{
|
|
if (*pOld == '/')
|
|
{
|
|
if (slash_detect == 0)
|
|
{
|
|
slash_detect = 1;
|
|
}
|
|
else
|
|
{
|
|
pOld++;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
slash_detect = 0;
|
|
}
|
|
|
|
pNew[nCount++] = *pOld++;
|
|
}
|
|
|
|
pNew[nCount] = '\0';
|
|
return 1;
|
|
}
|
|
|
|
|
|
#ifdef __OPENDISK_SOLUTION__
|
|
int dav_repos_change_resource_type(int resource_type)
|
|
{
|
|
if (resource_type >= dav_repos_RECYCLE)
|
|
{
|
|
return (resource_type - dav_repos_RECYCLE);
|
|
}
|
|
else if (resource_type >= dav_repos_SHARE)
|
|
{
|
|
return (resource_type - dav_repos_SHARE);
|
|
}
|
|
|
|
return resource_type;
|
|
}
|
|
#endif
|
|
|
|
|
|
#define PRIVATE_KEY "gE\x8bk\xc6\x23{2i\x98<dsH3f"
|
|
|
|
|
|
//static void __tea_encrypt(unsigned int *v, unsigned int *k)
|
|
//{
|
|
// unsigned int v0 = v[0], v1 = v[1], sum = 0, i; /* set up */
|
|
// unsigned int delta = 0x9e3779b9; /* a key schedule constant */
|
|
// unsigned int k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
|
|
|
|
// for (i = 0; i < 32; i++) { /* basic cycle start */
|
|
// sum += delta;
|
|
// v0 += (v1 << 4) + (k0 ^ v1) + (sum ^ (v1 >> 5)) + k1;
|
|
// v1 += (v0 << 4) + (k2 ^ v0) + (sum ^ (v0 >> 5)) + k3; /* end cycle */
|
|
// }
|
|
|
|
// v[0] = v0; v[1] = v1;
|
|
//}
|
|
|
|
static void __tea_decrypt(unsigned int *v, unsigned int *k)
|
|
{
|
|
unsigned int v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i; /* set up */
|
|
unsigned int delta = 0x9e3779b9; /* a key schedule constant */
|
|
unsigned int k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; /* cache key */
|
|
|
|
for (i = 0; i < 32; i++) { /* basic cycle start */
|
|
v1 -= (v0 << 4) + (k2 ^ v0) + (sum ^ (v0 >> 5)) + k3;
|
|
v0 -= (v1 << 4) + (k0 ^ v1) + (sum ^ (v1 >> 5)) + k1;
|
|
sum -= delta; /* end cycle */
|
|
}
|
|
|
|
v[0] = v0; v[1] = v1;
|
|
}
|
|
|
|
/*
|
|
static void tea_encrypt(char *buf, int len)
|
|
{
|
|
int __len = (len + 7) >> 3;
|
|
int i;
|
|
//char *key = PRIVATE_KEY;
|
|
|
|
for (i = 0; i < __len; i++) {
|
|
__tea_encrypt((((unsigned int *)buf) + (i << 1)), (unsigned int *)PRIVATE_KEY);
|
|
}
|
|
}
|
|
*/
|
|
|
|
void tea_decrypt(char *buf, int len)
|
|
{
|
|
int __len = (len + 7) >> 3;
|
|
int i;
|
|
|
|
for (i = 0; i < __len; i++) {
|
|
__tea_decrypt((((unsigned int *)buf) + (i << 1)), (unsigned int *)PRIVATE_KEY);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int file_trylock(int fd)
|
|
{
|
|
struct flock _lock;
|
|
|
|
memset( &_lock, 0, sizeof(struct flock) );
|
|
|
|
_lock.l_type = F_WRLCK;
|
|
_lock.l_start = 0;
|
|
_lock.l_whence = SEEK_SET;
|
|
_lock.l_len = 0;
|
|
|
|
return fcntl(fd, F_SETLK, &_lock);
|
|
}
|
|
|
|
|
|
int file_unlock(int fd)
|
|
{
|
|
struct flock _lock;
|
|
|
|
memset( &_lock, 0, sizeof(struct flock) );
|
|
|
|
_lock.l_type = F_UNLCK;
|
|
_lock.l_start = 0;
|
|
_lock.l_whence = SEEK_SET;
|
|
_lock.l_len = 0;
|
|
|
|
return fcntl(fd, F_SETLK, &_lock);
|
|
}
|
|
|
|
/* apache version 업에 따른 apr_dbd_get_row 처리 방법 변경 */
|
|
int solbox_apr_dbd_get_row(const apr_dbd_driver_t *driver, apr_pool_t *pool,
|
|
apr_dbd_results_t *res, apr_dbd_row_t **row, int rownum)
|
|
{
|
|
DBG1("solbox_apr_dbd_get_row #1 = %s", APU_VERSION_STRING);
|
|
/* apu vsrsion 1.3.0 부터 rowunm counting 1부터 시작*/
|
|
if(rownum >= 0 && strcmp(APU_VERSION_STRING, "1.3.0") >= 0)
|
|
{
|
|
return apr_dbd_get_row(driver, pool, res, row, rownum+1);
|
|
}
|
|
else
|
|
{
|
|
return apr_dbd_get_row(driver, pool, res, row, rownum);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
dav_error* solbox_dav_new_error(apr_pool_t *p, int status,
|
|
int error_id, const char *desc)
|
|
{
|
|
|
|
|
|
#if AP_SERVER_MAJORVERSION_NUMBER > 2 || AP_SERVER_MINORVERSION_NUMBER >= 3
|
|
return dav_new_error(p, status, error_id, 0, desc);
|
|
#else // 2.2.x
|
|
return dav_new_error(p, status, error_id, desc);
|
|
#endif // 2.3 over
|
|
|
|
}
|
|
|
|
const char *dav_http_scheme(const request_rec *r)
|
|
{
|
|
/*
|
|
* The http module shouldn't return anything other than
|
|
* "http" (the default) or "https".
|
|
*/
|
|
if (r->server->server_scheme &&
|
|
(strcmp(r->server->server_scheme, "https") == 0))
|
|
return "https";
|
|
|
|
return "http";
|
|
}
|