Back

// PSLIPv4.cpp : Implementation of CPSLIPv4

#include "stdafx.h"
#include "PSLIPv4.h"

CPSLIPv4::CPSLIPv4()
{
   ::memset(m_uAddr, 0, sizeof(m_uAddr));
   m_uPort = 0;
   m_Format = ip4Default;
}

HRESULT CPSLIPv4::FinalConstruct()
{
   return S_OK;
}

void CPSLIPv4::FinalRelease()
{
}

/*
Accepted format: x.x.x.x:x
Numbers can be decimal, hex or combination;
Any hex must have 0x or 0X in front of it;
An empty string is a valid zero address
when passed during object initialization,
i.e. bCreating = true;
*/
bool CPSLIPv4::Initialize(LPCTSTR sIP, bool bCreating)
{
   tstring s(sIP);
   remove_chars(s, SPACES);
   size_t size = s.length();
   if(!size)
   {
      if(bCreating)
      {
         // It is Ok to pass an empty string
         // to create a zero-address object;
         Clear(VARIANT_FALSE);
         return true;
      }
      return false;
   }

   if(size < 7) // 7 is the smallest size of a valid IP address;
      return false; // Invalid IP address;

   make_upper(s);

   LPCTSTR text = s.c_str();
   TCHAR buffer[10];
   short addr[4] = {0, 0, 0, 0};
   size_t idx = 0, last_idx = 0;
   size_t n = 0;
   TCHAR separator = '.';
   for(int i = 0; i < 4;i ++)
   {
      if(i == 3)
         separator = ':';
      last_idx = idx;
      idx = s.find_first_of(separator, idx);
      if(i == 3)
      {
         if(idx == -1)
            idx = size;
         else
            if(idx == size - 1) // Has double column in the end but nothing else;
               return false;
      }
      n = idx - last_idx;
      if(idx == -1 || n > 4 || n < 1)
         return false;
      _tcsncpy_s(buffer, 10, text, n);
      if(buffer[0] == '0' && buffer[1] == 'X')
      {
         if(!fromhex(buffer, addr[i]))
            return false;
      }
      else
      {
         if(!fromint(buffer, addr[i]))
            return false;
      }
      idx ++;
      text += n + 1;
      if(addr[i] > 255)
         return false; // Cannot have more than 255 for any octet;
   }

   if(idx + 6 < size)
      return false; // Cannot have more than 6 digits in the port address (0xFFFF);

   if(idx < size) // If has port in the address;
   {
      _tcscpy_s(buffer, 10, text);
      long lValue;
      bool bValid = false;
      if(buffer[0] == '0' && buffer[1] == 'X')
         bValid = fromhex(buffer, lValue)?true:false;
      else
         bValid = fromint(buffer, lValue)?true:false;
      if(!bValid || lValue > 65535)
         return false;
      m_uPort = (short)lValue;
   }
   else
      m_uPort = 0;

   ::memcpy(m_uAddr, addr, sizeof(addr));

   return true;
}

void CPSLIPv4::GetAddrValue(tstring & s, USHORT uValue, long PaddingBase)
{
   if(m_Format & ip4Hex)
   {
      tstring tmp;
      s = _T("0x");
      if(m_Format & ip4Padded)
         tohexfill(tmp, uValue, PaddingBase);
      else
         tohex(tmp, uValue);
      if(m_Format & ip4UpperCase)
         make_upper(tmp);
      s += tmp;
   }
   else
   {
      if(m_Format & ip4Padded)
         tointfill(s, uValue, PaddingBase + 1);
      else
         toint(s, uValue);
   }
}

_bstr_t CPSLIPv4::GetIPName()
{
   tstring s, s1, s2, s3, s4;
   GetAddrValue(s1, m_uAddr[0]);
   GetAddrValue(s2, m_uAddr[1]);
   GetAddrValue(s3, m_uAddr[2]);
   GetAddrValue(s4, m_uAddr[3]);
   s.resize(20);
   ::wsprintf((LPTSTR)s.c_str(), _T("%s.%s.%s.%s"), s1.c_str(), s2.c_str(), s3.c_str(), s4.c_str());
   shrink(s);
   if(m_uPort)
   {
      tstring sPort;
      GetAddrValue(sPort, m_uPort, 4);
      s += _T(":");
      s += sPort.c_str();
   }
   return s.c_str();
}

////////////////////////////////////////////////////////////////////////
// Interface Implementation;
////////////////////////////////////////////////////////////////////////

STDMETHODIMP CPSLIPv4::get_A1(short * pValue)
{
   PSL_BEGIN

   *pValue = m_uAddr[0];

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_A1(short newValue)
{
   PSL_BEGIN

   if(newValue < 0 || newValue > 255)
      return MakeException(EX_INVALIDPARAMETER);

   m_uAddr[0] = newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_A2(short * pValue)
{
   PSL_BEGIN

   *pValue = m_uAddr[1];

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_A2(short newValue)
{
   PSL_BEGIN

   if(newValue < 0 || newValue > 255)
      return MakeException(EX_INVALIDPARAMETER);

   m_uAddr[1] = newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_A3(short * pValue)
{
   PSL_BEGIN

   *pValue = m_uAddr[2];

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_A3(short newValue)
{
   PSL_BEGIN

   if(newValue < 0 || newValue > 255)
      return MakeException(EX_INVALIDPARAMETER);

   m_uAddr[2] = newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_A4(short * pValue)
{
   PSL_BEGIN

   *pValue = m_uAddr[3];

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_A4(short newValue)
{
   PSL_BEGIN

   if(newValue < 0 || newValue > 255)
      return MakeException(EX_INVALIDPARAMETER);

   m_uAddr[3] = newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_Port(long * pValue)
{
   PSL_BEGIN

   *pValue = m_uPort;

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_Port(long newValue)
{
   PSL_BEGIN

   if(newValue < 0 || newValue > 0xFFFF)
      return MakeException(EX_INVALIDPARAMETER);

   m_uPort = (USHORT)newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_Address(long * pValue)
{
   PSL_BEGIN

   *pValue = MAKELONG(MAKEWORD(m_uAddr[0], m_uAddr[1]), MAKEWORD(m_uAddr[2], m_uAddr[3]));

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_Address(long newValue)
{
   PSL_BEGIN

   m_uAddr[0] = LOBYTE(LOWORD(newValue));
   m_uAddr[1] = HIBYTE(LOWORD(newValue));
   m_uAddr[2] = LOBYTE(HIWORD(newValue));
   m_uAddr[3] = HIBYTE(HIWORD(newValue));

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_Text(BSTR * pValue)
{
   PSL_BEGIN

   *pValue = GetIPName().copy();

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_Text(BSTR newValue)
{
   PSL_BEGIN

   if(!newValue)
      return MakeException(EX_INVALIDPARAMETER);

   if(!Initialize(_bstr_t(newValue), false))
      SetException(EX_INVALIDPARAMETER);

   PSL_END
}

STDMETHODIMP CPSLIPv4::get_Format(PSLIPv4Format * pValue)
{
   PSL_BEGIN

   *pValue = m_Format;

   PSL_END
}

STDMETHODIMP CPSLIPv4::put_Format(PSLIPv4Format newValue)
{
   PSL_BEGIN

   m_Format = newValue;

   PSL_END
}

STDMETHODIMP CPSLIPv4::Clear(VARIANT_BOOL bClearFormat)
{
   PSL_BEGIN

   ::memset(m_uAddr, 0, sizeof(m_uAddr));
   m_uPort = 0;
   if(bClearFormat)
      m_Format = ip4Default;

   PSL_END
}

Top