This commit is contained in:
biosvos
2026-08-07 17:38:18 +09:00
commit 873193a243
9613 changed files with 2755992 additions and 0 deletions
+256
View File
@@ -0,0 +1,256 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "SmsSender.h"
#include <iterator>
#define DEFAULT_BUFFER_SIZE 9216
#define MaxSizeOfTRxBuffer 1024
string CSmsSender::RemoveBlankSpace(const char* pszData, size_t nLength)
{
char * szTemp = NULL;
string strReturn;
const char * src;
char * dest;
szTemp = (char*) ::malloc(sizeof(char) * nLength +1);
::memset(szTemp, 0 , sizeof(char)*nLength +1);
src = pszData;
dest = szTemp;
if( pszData == NULL )
{
strReturn.clear();
return strReturn;
}
if( *src == '\0' )
{
strReturn = src;
return strReturn;
}
// start with 2nd position
src++;
while ( src <= (pszData + nLength) && *(src-1) != '\0' )
{
if( *(src-1) == ' ' && *(src) == ' ' )
{ // 연속된 공백이 발견되면, 스킵한다.
src++;
continue;
}
*dest = *(src-1);
src++;
dest++;
}
// 종료표기
dest++;
*(dest) = '\0';
strReturn = szTemp;
if (szTemp != NULL)
{
free(szTemp);
szTemp = NULL;
}
return strReturn;
}
char hexchars[] = "0123456789ABCDEF";
string CSmsSender::PostDataEncode(const char *pszCommand, size_t length)
{
int i;
char tmpBuffer[MaxSizeOfTRxBuffer];
string strReturn;
if( pszCommand == NULL )
{
strReturn.clear();
return strReturn;
}
::memset(tmpBuffer, 0 , MaxSizeOfTRxBuffer);
i = 0;
while( *pszCommand != '\0' )
{
if( *pszCommand == ' ' )
{ // ' ' => '+'
tmpBuffer[i++] = '+';
pszCommand++;
}
else if(*pszCommand == '%')
{ // % => %%
tmpBuffer[i++] = '%';
tmpBuffer[i++] = '%';
pszCommand++;
}
else if( (*pszCommand < '0' && *pszCommand != '-' && *pszCommand != '.' )
|| (*pszCommand < 'A' && *pszCommand > '9' )
|| (*pszCommand > 'Z' && *pszCommand < 'a' && *pszCommand != '_' )
|| (*pszCommand > 'z' ) )
{
tmpBuffer[i++] = '%';
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand >> 4];
tmpBuffer[i++] = hexchars[(unsigned char)*pszCommand & 15];
pszCommand++;
}
else
{
tmpBuffer[i++] = *pszCommand++;
}
}
tmpBuffer[i] = '\0';
strReturn = tmpBuffer;
return strReturn;
}
CSmsSender::CSmsSender(const std::string& szHost, const int nPort, const std::string& szPath)
: CBaseSocket( SOCKET_NOT_VALID), m_szHost(szHost), m_nPort(nPort), m_szPath(szPath)
{
// 생성자
}
CSmsSender::~CSmsSender()
{
// 소멸자에 BaseSocket의 명시적 Close 처리를 한다.
Close();
}
bool CSmsSender::Init(void)
{
bool bRet = false;
// 데이터 체크
if( m_szHost.empty() || m_nPort < 0 || m_szPath.empty() )
{
LOG(LERR, "Invalid Parameter.");
return false;
}
return true;
}
bool CSmsSender::SendToWebServ(const string& pszHost, const string& pszTime, const string& pszMsg)
{
string szHost;
string szTime;
string szMsg;
char szSndBuffer[DEFAULT_BUFFER_SIZE];
char szRcvBuffer[DEFAULT_BUFFER_SIZE];
bool bRet = false;
int nRet = 0;
if( pszHost.empty() || pszMsg.empty() || pszTime.empty() )
{
LOG(LERR, "Invalid Parameter.");
Close();
return false;
}
// Connect
bRet = Connect(m_szHost, m_nPort);
if( bRet == false )
{
LOG(LERR, "Socket Connect Error.[%s:%d]", m_szHost.c_str(), m_nPort);
return false;
}
if( IsValidSocket() == false )
{
LOG(LERR, "Invalid Socket.");
Close();
return false;
}
::bzero(szSndBuffer, DEFAULT_BUFFER_SIZE);
::bzero(szRcvBuffer, DEFAULT_BUFFER_SIZE);
szHost = PostDataEncode(pszHost.c_str(), pszHost.size());
szTime = PostDataEncode(pszTime.c_str(), pszTime.size());
szMsg = RemoveBlankSpace(pszMsg.c_str(), pszMsg.size());
LOG(LDBG, "SMSMsg = [%s]", szMsg.c_str());
szMsg = PostDataEncode(szMsg.c_str(), szMsg.size());
// CHG 2019-09-16 huibong HTTP 관련 줄바꿈문자 LF->CR+LF 변경 (#32794)
// - CVE-2016-8743 이슈에 따라 Apache 2.2.32 버전부터 HTTP header 상에서
// - 줄바꿈문자가 CR+LF 가 아닌 경우 HTTP 400 응답 발생
// - 이를 해결하기 위해 기존 줄바꿈 문자 \n -> \r\n 으로 변경처리한다.
::snprintf(szSndBuffer, DEFAULT_BUFFER_SIZE, "GET %s?host=%s&time=%s&msg=%s HTTP/1.0\r\n"\
"Content-Type: text/plain\r\n"\
"User-Agent: Arcmond\r\n"\
"Host: %s\r\n"\
"Connection: close\r\n"\
"Cache-Control: no-cache\r\n\r\n"
,m_szPath.c_str(), szHost.c_str(), szTime.c_str(), szMsg.c_str() ,m_szHost.c_str());
//DEBUG_LOG("%s", szSndBuffer);
//요청 전송 시작
nRet = WriteN(&szSndBuffer, ::strlen(szSndBuffer)+1);
// MAX_SEND_RETRY_COUNT 회수만큼 재시도 후 실패처리된다.
if( nRet == 0 )
{
LOG(LERR, "write socket closed.");
Close();
return false;
}
else if( nRet == -1 )
{
LOG(LERR, "write socket error.(%s)",strerror(errno));
Close();
return false;
}
// 응답 결과 받기.
nRet = ReadNTimeout(szRcvBuffer, DEFAULT_BUFFER_SIZE);
if( nRet == 0 )
{
// Remain이 0일 경우가 모두 받은 상황인데, 그것을 알 수 없다면,
// Ret==0일 때가 다 준 상황으로 판단해야 하지 않을까? 그렇다면 에러가 아니다.
LOG(LDBG, "read socket closed.");
}
else if( nRet == -1 )
{ // 단순 소켓 에러.
LOG(LERR, "read socket error.(%s)",strerror(errno));
Close();
return false;
}
else if( nRet == -2 )
{ // 타임아웃.
LOG(LERR, "read socket timed out.");
Close();
return false;
}
// 정상 결과는 아래와 같은 형태이다.
//----------------------------------------------------------------
// HTTP/1.1 200 OK
// Date: Thu, 10 Jun 2010 03:59:23 GMT
// Server: Apache/2.0.55 (Unix) DAV/2 PHP/5.2.1
// X-Powered-By: PHP/5.2.1
// Content-Length: 87
// Connection: close
// Content-Type: text/html; charset=EUC-KR
//
// [RAID:qcrts4.ktsh.co.kr]::2010-07-09 12:59:19:Controller#1: SW API Interface API Log In
//----------------------------------------------------------------
// 첫번째 라인만 출력하기 위해서 \n을 \0으로 바꾸고 출력한다.
char* pEnd = strchr(szRcvBuffer, '\n');
*pEnd = '\0';
LOG(LINF, "Result:%s", szRcvBuffer);
// Close()는 return값이 없음.
Close();
return true;
}