W3C Log Handler Example for C++

enum 
{ 
   W3CLOG_date = 0x00000001, 
   W3CLOG_time = 0x00000002, 
   W3CLOG_c_ip = 0x00000004, 
   W3CLOG_cs_username = 0x00000008, 
   W3CLOG_s_sitename = 0x00000010, 
   W3CLOG_s_computername = 0x00000020, 
   W3CLOG_s_ip = 0x00000040, 
   W3CLOG_s_port = 0x00000080, 
   W3CLOG_cs_method = 0x00000100, 
   W3CLOG_cs_uri_stem = 0x00000200, 
   W3CLOG_cs_uri_query = 0x00000400, 
   W3CLOG_sc_status = 0x00000800, 
   W3CLOG_sc_win32_status = 0x00001000, 
   W3CLOG_sc_bytes = 0x00002000, 
   W3CLOG_cs_bytes = 0x00004000, 
   W3CLOG_time_taken = 0x00008000, 
   W3CLOG_cs_version = 0x00010000, 
   W3CLOG_cs_host = 0x00020000, 
   W3CLOG_cs_user_agent = 0x00040000, 
   W3CLOG_cs_cookie = 0x00080000, 
   W3CLOG_cs_referer = 0x00100000, 
   W3CLOG_sc_substatus = 0x00200000, 
}; 
 
class CW3CLogHandler : 
   public IltmsLogHandler 
{ 
protected: 
   BOOL m_enable; 
   CAtlFile m_file; 
   DWORD m_fields; 
   BOOL m_localtime; 
   COleDateTime m_dtfile; 
   CString m_software; 
   CString m_folder; 
   CString m_prefix; 
   CString escape(LPCOLESTR s); 
   BOOL CreateLog(DATE timestamp); 
   CString GetLogPath(DATE timestamp); 
   HRESULT WriteString(LPCTSTR s); 
   COleDateTime GetTime(DATE timestamp); 
   HRESULT ResolvePath(LPCTSTR key, CString& resolved); 
 
public: 
   CW3CLogHandler(LPCTSTR prefix = _T("ltms_"), LPCTSTR software = _T("LEAD Media Server"), BOOL enable = TRUE, LPCTSTR folder = _T("%ltmsLogFolder%"), DWORD fields = 0xffffffffUL, BOOL localtime = FALSE); 
   virtual ~CW3CLogHandler(void); 
   virtual HRESULT STDMETHODCALLTYPE QueryInterface(/* [in] */ REFIID riid, /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject); 
   virtual ULONG STDMETHODCALLTYPE AddRef( void); 
   virtual ULONG STDMETHODCALLTYPE Release( void); 
   virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE InitializeLog(DATE timestamp); 
   virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TerminateLog(void); 
   virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE LogInformation(/* [in] */ IltmsLogInformation *info); 
}; 
 
CW3CLogHandler::CW3CLogHandler(LPCTSTR prefix, LPCTSTR software, BOOL enable, LPCTSTR folder, DWORD fields, BOOL localtime) : m_fields(fields), 
   m_enable(enable), m_prefix(prefix), m_folder(folder), m_software(software), m_localtime(localtime) 
{ 
} 
 
CW3CLogHandler::~CW3CLogHandler(void) 
{ 
} 
 
HRESULT STDMETHODCALLTYPE CW3CLogHandler::QueryInterface(/* [in] */ REFIID riid, /* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) 
{ 
   if(riid == IID_IUnknown || riid == __uuidof(IltmsLogHandler)) 
   { 
      *ppvObject = (void*) (IltmsLogHandler*) this; 
      return S_OK; 
   } 
 
   return E_NOINTERFACE; 
} 
 
ULONG STDMETHODCALLTYPE CW3CLogHandler::AddRef( void) 
{ 
   return 1; 
} 
 
ULONG STDMETHODCALLTYPE CW3CLogHandler::Release( void) 
{ 
   return 1; 
} 
 
HRESULT CW3CLogHandler::WriteString(LPCTSTR s) 
{ 
   CStringA t(s); 
   return m_file.Write(t, t.GetLength()); 
} 
 
COleDateTime CW3CLogHandler::GetTime(DATE timestamp) 
{ 
  COleDateTime dt(timestamp); 
  if(m_localtime) 
  { 
     SYSTEMTIME timeUTC;  
     dt.GetAsSystemTime(timeUTC); 
     SYSTEMTIME timeLocal; 
     SystemTimeToTzSpecificLocalTime(NULL, &timeUTC, &timeLocal); 
     dt = COleDateTime(timeLocal); 
  } 
 
  return dt; 
} 
 
HRESULT CW3CLogHandler::ResolvePath(LPCTSTR key, CString& resolved) 
{ 
   HRESULT hr; 
   CComPtr<IltmsPathResolver> resolver; 
   hr = CoCreateInstance(__uuidof(ltmsPathResolver), NULL, CLSCTX_ALL, __uuidof(IltmsPathResolver), (void**) &resolver); 
   if(FAILED(hr)) 
      return hr; 
 
   CComBSTR v; 
   hr = resolver->Resolve(CComBSTR(key), &v); 
   if(FAILED(hr)) 
      return hr; 
 
   resolved = v; 
   return S_OK; 
} 
 
CString CW3CLogHandler::GetLogPath(DATE timestamp) 
{ 
   COleDateTime dt = GetTime(timestamp); 
 
   CString fullpath; 
   HRESULT hr = ResolvePath(m_folder, fullpath); 
   if(FAILED(hr)) 
      return _T(""); 
 
   fullpath += _T("\\"); 
   fullpath += m_prefix; 
 
   if(!m_localtime) 
      fullpath += dt.Format(_T("%y%m%d%H%M%SUTC.log")); 
   else 
      fullpath += dt.Format(_T("%y%m%d%H%M%S.log")); 
 
   return fullpath; 
} 
 
BOOL CW3CLogHandler::CreateLog(DATE timestamp) 
{ 
   if(m_file.m_h != NULL) 
      m_file.Close(); 
 
   if(!m_enable) 
      return FALSE; 
 
   HRESULT hr = m_file.Create(GetLogPath(timestamp), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, OPEN_ALWAYS); 
   if(FAILED(hr)) 
      return FALSE; 
 
   CString s; 
 
   m_dtfile = GetTime(timestamp); 
   m_file.Seek(0, FILE_END); 
   s.Format(_T("#Software: %s\r\n"), (LPCTSTR) m_software); 
   WriteString(s); 
   WriteString(_T("#Version: 1.0\r\n")); 
   COleDateTime dt = GetTime(timestamp); 
   s = dt.Format(_T("#Date: %Y-%m-%d %H:%M:%S\r\n")); 
   WriteString(s); 
 
   s = _T("#Fields:"); 
 
   if(m_fields & W3CLOG_date) 
   { 
      s += _T(" date"); 
   } 
 
   if(m_fields & W3CLOG_time) 
   { 
      s += _T(" time"); 
   } 
 
   if(m_fields & W3CLOG_s_sitename) 
   { 
      s += _T(" s-sitename"); 
   } 
 
   if(m_fields & W3CLOG_s_computername) 
   { 
      s += _T(" s-computername"); 
   } 
 
   if(m_fields & W3CLOG_s_ip) 
   { 
      s += _T(" s-ip"); 
   } 
 
   if(m_fields & W3CLOG_cs_method) 
   { 
      s += _T(" cs-method"); 
   } 
 
   if(m_fields & W3CLOG_cs_uri_stem) 
   { 
      s += _T(" cs-uri-stem"); 
   } 
 
   if(m_fields & W3CLOG_cs_uri_query) 
   { 
      s += _T(" cs-uri-query"); 
   } 
 
   if(m_fields & W3CLOG_s_port) 
   { 
      s += _T(" s-port"); 
   } 
 
   if(m_fields & W3CLOG_cs_username) 
   { 
      s += _T(" cs-username"); 
   } 
 
   if(m_fields & W3CLOG_c_ip) 
   { 
      s += _T(" c-ip"); 
   } 
 
   if(m_fields & W3CLOG_cs_version) 
   { 
      s += _T(" cs-version"); 
   } 
 
   if(m_fields & W3CLOG_cs_user_agent) 
   { 
      s += _T(" cs(User-Agent)"); 
   } 
 
   if(m_fields & W3CLOG_cs_cookie) 
   { 
      s += _T(" cs(Cookie)"); 
   } 
 
   if(m_fields & W3CLOG_cs_referer) 
   { 
      s += _T(" cs(Referer)"); 
   } 
 
   if(m_fields & W3CLOG_cs_host) 
   { 
      s += _T(" cs-host"); 
   } 
 
   if(m_fields & W3CLOG_sc_status) 
   { 
      s += _T(" sc-status"); 
   } 
 
   if(m_fields & W3CLOG_sc_substatus) 
   { 
      s += _T(" sc-substatus"); 
   } 
 
   if(m_fields & W3CLOG_sc_win32_status) 
   { 
      s += _T(" sc-win32-status"); 
   } 
 
   if(m_fields & W3CLOG_sc_bytes) 
   { 
      s += _T(" sc-bytes"); 
   } 
 
   if(m_fields & W3CLOG_cs_bytes) 
   { 
      s += _T(" cs-bytes"); 
   } 
 
   if(m_fields & W3CLOG_time_taken) 
   { 
      s += _T(" time-taken"); 
   } 
 
   s += _T("\r\n"); 
   WriteString(s); 
   m_file.Flush(); 
 
   return TRUE; 
} 
 
CString CW3CLogHandler::escape(LPCOLESTR s) 
{ 
   CStringW t; 
   for(; *s; s++) 
   { 
      if(iswprint(*s) && !iswspace(*s)) 
         t += *s; 
      else 
         t += L"+"; 
   } 
 
   return CString(t); 
} 
 
HRESULT STDMETHODCALLTYPE CW3CLogHandler::InitializeLog(DATE timestamp) 
{ 
   CreateLog(timestamp); 
   return S_OK; 
} 
 
HRESULT STDMETHODCALLTYPE CW3CLogHandler::TerminateLog(void) 
{ 
   if(m_file.m_h != NULL) 
      m_file.Close(); 
 
   return S_OK; 
} 
 
HRESULT STDMETHODCALLTYPE CW3CLogHandler::LogInformation(/* [in] */ IltmsLogInformation *info) 
{ 
   CString s; 
 
   if(!m_enable) 
      return S_OK; 
 
   // check if we need to roll to a new file 
   { 
      DATE v; 
      info->get_TimeStamp(&v); 
      COleDateTime dt = GetTime(v); 
      if(m_file.m_h == NULL || dt.GetDay() != m_dtfile.GetDay() 
         || dt.GetMonth() != m_dtfile.GetMonth() 
         || dt.GetYear() != m_dtfile.GetYear()) 
      { 
         if(!CreateLog(v)) 
            return S_OK; 
      } 
   } 
 
   if(m_fields & W3CLOG_date) 
   { 
      DATE v; 
      info->get_TimeStamp(&v); 
      COleDateTime dt = GetTime(v); 
 
      if(!s.IsEmpty()) 
         s += L" "; 
 
      s += dt.Format(_T("%Y-%m-%d")); 
   } 
 
   if(m_fields & W3CLOG_time) 
   { 
      DATE v; 
      info->get_TimeStamp(&v); 
      COleDateTime dt = GetTime(v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      s += dt.Format(_T("%H:%M:%S")); 
   } 
 
   if(m_fields & W3CLOG_s_sitename) 
   { 
      CComBSTR v; 
      info->get_SiteName(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_s_computername) 
   { 
      CComBSTR v; 
      info->get_ComputerName(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_s_ip) 
   { 
      CComBSTR v; 
      info->get_ServerIP(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += v; 
   } 
 
   if(m_fields & W3CLOG_cs_method) 
   { 
      CComBSTR v; 
      info->get_Method(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_uri_stem) 
   { 
      CComBSTR v; 
      info->get_URIStem(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_uri_query) 
   { 
      CComBSTR v; 
      info->get_URIQuery(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_s_port) 
   { 
      LONG v; 
      info->get_ServerPort(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      CString t; 
      t.Format(_T("%u"), (UINT) v); 
      s += t; 
   } 
 
   if(m_fields & W3CLOG_cs_username) 
   { 
      CComBSTR v; 
      info->get_UserName(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_c_ip) 
   { 
      CComBSTR v; 
      info->get_ClientIP(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(s.IsEmpty()) 
         s += _T("-"); 
      else 
         s += v; 
   } 
 
   if(m_fields & W3CLOG_cs_version) 
   { 
      CComBSTR v; 
      info->get_ProtocolVersion(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_user_agent) 
   { 
      CComBSTR v; 
      info->get_UserAgent(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_cookie) 
   { 
      CComBSTR v; 
      info->get_Cookie(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_referer) 
   { 
      CComBSTR v; 
      info->get_Referrer(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_cs_host) 
   { 
      CComBSTR v; 
      info->get_Host(&v); 
 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v.Length() == 0) 
         s += _T("-"); 
      else 
         s += escape(v); 
   } 
 
   if(m_fields & W3CLOG_sc_status) 
   { 
      LONG v; 
      info->get_Status(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      CString t; 
      t.Format(_T("%u"), (UINT) v); 
      s += t; 
   } 
 
   if(m_fields & W3CLOG_sc_substatus) 
   { 
      LONG v; 
      info->get_ProtocolSubStatus(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      CString t; 
      t.Format(_T("%u"), (UINT) v); 
      s += t; 
   } 
 
   if(m_fields & W3CLOG_sc_win32_status) 
   { 
      LONG v; 
      info->get_Win32Status(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      CString t; 
      t.Format(_T("%u"), (UINT) v); 
      s += t; 
   } 
 
   if(m_fields & W3CLOG_sc_bytes) 
   { 
      LONG v; 
      info->get_BytesSent(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v < 0) 
      { 
         s += _T("-"); 
      } 
      else 
      { 
         CString t; 
         t.Format(_T("%u"), (UINT) v); 
         s += t; 
      } 
   } 
 
   if(m_fields & W3CLOG_cs_bytes) 
   { 
      LONG v; 
      info->get_BytesReceived(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v < 0) 
      { 
         s += _T("-"); 
      } 
      else 
      { 
         CString t; 
         t.Format(_T("%u"), (UINT) v); 
         s += t; 
      } 
   } 
 
   if(m_fields & W3CLOG_time_taken) 
   { 
      LONG v; 
      info->get_TimeTaken(&v); 
      if(!s.IsEmpty()) 
         s += _T(" "); 
 
      if(v < 0) 
      { 
         s += _T("-"); 
      } 
      else 
      { 
         CString t; 
         t.Format(_T("%u"), (UINT) v); 
         s += t; 
      } 
   } 
 
   s += _T("\r\n"); 
   WriteString(s); 
   m_file.Flush(); 
 
   return S_OK; 
} 
 
HRESULT RunServerWithLogging(void) 
{ 
   CComPtr<IltmsServer> server; 
   HRESULT hr; 
   CW3CLogHandler loghandler; 
 
   // create an instance of the server object 
   hr = CoCreateInstance(__uuidof(ltmsServer), NULL, CLSCTX_ALL, __uuidof(IltmsServer), (void**) &server); 
   if(FAILED(hr)) 
      goto error; 
 
   // set the log handler 
   hr = server->putref_LogHandler(&loghandler); 
   if(FAILED(hr)) 
      goto error; 
 
   { 
      // for demonstration, compare the interface we just set 
      CComPtr<IltmsLogHandler> ihandler; 
      hr = server->get_LogHandler(&ihandler); 
      if(FAILED(hr)) 
         goto error; 
 
      if(ihandler != (IltmsLogHandler*) &loghandler) 
      { 
         hr = E_UNEXPECTED; 
         goto error; 
      } 
   } 
    
   // load the configuration file located in the config subfolder under the executable folder 
   // or comment this section out to run with the server's default settings 
   hr = server->ImportConfigFile(CComBSTR(L"%ltmsConfigFolder%\\ltmsServer.xml")); 
   if(FAILED(hr)) 
      goto error; 
 
   // start the server 
   hr = server->Start(); 
   if(FAILED(hr)) 
      goto error; 
 
   // display a message that the server is running and wait for a key 
   _tprintf(_T("The server has started. Hit any key to stop.\n")); 
   _gettc(stdin); 
 
   // stop the server 
   hr = server->Stop(); 
   if(FAILED(hr)) 
      goto error; 
 
   // remove the log handler 
   hr = server->putref_LogHandler(NULL); 
   if(FAILED(hr)) 
      return hr; 
 
error: 
   return hr; 
} 
Help Version 21.0.2021.7.2
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.

LEADTOOLS Media Streaming C API Help
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2021 LEAD Technologies, Inc. All Rights Reserved.