📄 utility.cpp.svn-base
字号:
/** \file Utility.cpp
** \date 2004-02-13
** \author grymse@alhem.net
**/
/*
Copyright (C) 2004-2007 Anders Hedstrom
This library is made available under the terms of the GNU GPL.
If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Utility.h"
#include "Parse.h"
#include "Ipv4Address.h"
#include "Ipv6Address.h"
#include "Base64.h"
#include <vector>
#ifdef _WIN32
#include <time.h>
#else
#include <netdb.h>
#include <pthread.h>
#endif
#include <map>
#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif
// defines for the random number generator
#define TWIST_IA 397
#define TWIST_IB (TWIST_LEN - TWIST_IA)
#define UMASK 0x80000000
#define LMASK 0x7FFFFFFF
#define MATRIX_A 0x9908B0DF
#define TWIST(b,i,j) ((b)[i] & UMASK) | ((b)[j] & LMASK)
#define MAGIC_TWIST(s) (((s) & 1) * MATRIX_A)
// statics
std::string Utility::m_host;
bool Utility::m_local_resolved = false;
ipaddr_t Utility::m_ip = 0;
std::string Utility::m_addr;
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
struct in6_addr Utility::m_local_ip6;
std::string Utility::m_local_addr6;
#endif
#endif
std::string Utility::base64(const std::string& str_in)
{
std::string str;
Base64 m_b;
m_b.encode(str_in, str, false); // , false == do not add cr/lf
return str;
}
std::string Utility::base64d(const std::string& str_in)
{
std::string str;
Base64 m_b;
m_b.decode(str_in, str);
return str;
}
std::string Utility::l2string(long l)
{
std::string str;
char tmp[100];
sprintf(tmp,"%ld",l);
str = tmp;
return str;
}
std::string Utility::bigint2string(uint64_t l)
{
std::string str;
uint64_t tmp = l;
while (tmp)
{
uint64_t a = tmp % 10;
str = (char)(a + 48) + str;
tmp /= 10;
}
if (str.empty())
{
str = "0";
}
return str;
}
uint64_t Utility::atoi64(const std::string& str)
{
uint64_t l = 0;
for (size_t i = 0; i < str.size(); i++)
{
l = l * 10 + str[i] - 48;
}
return l;
}
unsigned int Utility::hex2unsigned(const std::string& str)
{
unsigned int r = 0;
for (size_t i = 0; i < str.size(); i++)
{
r = r * 16 + str[i] - 48 - ((str[i] >= 'A') ? 7 : 0) - ((str[i] >= 'a') ? 32 : 0);
}
return r;
}
/*
* Encode string per RFC1738 URL encoding rules
* tnx rstaveley
*/
std::string Utility::rfc1738_encode(const std::string& src)
{
static char hex[] = "0123456789ABCDEF";
std::string dst;
for (size_t i = 0; i < src.size(); i++)
{
if (isalnum(src[i]))
{
dst += src[i];
}
else
if (src[i] == ' ')
{
dst += '+';
}
else
{
unsigned char c = static_cast<unsigned char>(src[i]);
dst += '%';
dst += hex[c / 16];
dst += hex[c % 16];
}
}
return dst;
} // rfc1738_encode
/*
* Decode string per RFC1738 URL encoding rules
* tnx rstaveley
*/
std::string Utility::rfc1738_decode(const std::string& src)
{
std::string dst;
for (size_t i = 0; i < src.size(); i++)
{
if (src[i] == '%' && isxdigit(src[i + 1]) && isxdigit(src[i + 2]))
{
char c1 = src[++i];
char c2 = src[++i];
c1 = c1 - 48 - ((c1 >= 'A') ? 7 : 0) - ((c1 >= 'a') ? 32 : 0);
c2 = c2 - 48 - ((c2 >= 'A') ? 7 : 0) - ((c2 >= 'a') ? 32 : 0);
dst += (char)(c1 * 16 + c2);
}
else
if (src[i] == '+')
{
dst += ' ';
}
else
{
dst += src[i];
}
}
return dst;
} // rfc1738_decode
bool Utility::isipv4(const std::string& str)
{
int dots = 0;
// %! ignore :port?
for (size_t i = 0; i < str.size(); i++)
{
if (str[i] == '.')
dots++;
else
if (!isdigit(str[i]))
return false;
}
if (dots != 3)
return false;
return true;
}
bool Utility::isipv6(const std::string& str)
{
size_t qc = 0;
size_t qd = 0;
for (size_t i = 0; i < str.size(); i++)
{
qc += (str[i] == ':') ? 1 : 0;
qd += (str[i] == '.') ? 1 : 0;
}
if (qc > 7)
{
return false;
}
if (qd && qd != 3)
{
return false;
}
Parse pa(str,":.");
std::string tmp = pa.getword();
while (!tmp.empty())
{
if (tmp.size() > 4)
{
return false;
}
for (size_t i = 0; i < tmp.size(); i++)
{
if (tmp[i] < '0' || (tmp[i] > '9' && tmp[i] < 'A') ||
(tmp[i] > 'F' && tmp[i] < 'a') || tmp[i] > 'f')
{
return false;
}
}
//
tmp = pa.getword();
}
return true;
}
bool Utility::u2ip(const std::string& str, ipaddr_t& l)
{
struct sockaddr_in sa;
bool r = Utility::u2ip(str, sa);
memcpy(&l, &sa.sin_addr, sizeof(l));
return r;
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
bool Utility::u2ip(const std::string& str, struct in6_addr& l)
{
struct sockaddr_in6 sa;
bool r = Utility::u2ip(str, sa);
l = sa.sin6_addr;
return r;
}
#endif
#endif
void Utility::l2ip(const ipaddr_t ip, std::string& str)
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
memcpy(&sa.sin_addr, &ip, sizeof(sa.sin_addr));
Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
}
void Utility::l2ip(const in_addr& ip, std::string& str)
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_addr = ip;
Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
void Utility::l2ip(const struct in6_addr& ip, std::string& str,bool mixed)
{
char slask[100]; // l2ip temporary
*slask = 0;
unsigned int prev = 0;
bool skipped = false;
bool ok_to_skip = true;
if (mixed)
{
unsigned short x;
unsigned short addr16[8];
memcpy(addr16, &ip, sizeof(addr16));
for (size_t i = 0; i < 6; i++)
{
x = ntohs(addr16[i]);
if (*slask && (x || !ok_to_skip || prev))
strcat(slask,":");
if (x || !ok_to_skip)
{
sprintf(slask + strlen(slask),"%x", x);
if (x && skipped)
ok_to_skip = false;
}
else
{
skipped = true;
}
prev = x;
}
x = ntohs(addr16[6]);
sprintf(slask + strlen(slask),":%u.%u",x / 256,x & 255);
x = ntohs(addr16[7]);
sprintf(slask + strlen(slask),".%u.%u",x / 256,x & 255);
}
else
{
struct sockaddr_in6 sa;
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_addr = ip;
Utility::reverse( (struct sockaddr *)&sa, sizeof(sa), str, NI_NUMERICHOST);
return;
}
str = slask;
}
int Utility::in6_addr_compare(in6_addr a,in6_addr b)
{
for (size_t i = 0; i < 16; i++)
{
if (a.s6_addr[i] < b.s6_addr[i])
return -1;
if (a.s6_addr[i] > b.s6_addr[i])
return 1;
}
return 0;
}
#endif
#endif
void Utility::ResolveLocal()
{
char h[256];
// get local hostname and translate into ip-address
*h = 0;
gethostname(h,255);
{
if (Utility::u2ip(h, m_ip))
{
Utility::l2ip(m_ip, m_addr);
}
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
memset(&m_local_ip6, 0, sizeof(m_local_ip6));
{
if (Utility::u2ip(h, m_local_ip6))
{
Utility::l2ip(m_local_ip6, m_local_addr6);
}
}
#endif
#endif
m_host = h;
m_local_resolved = true;
}
const std::string& Utility::GetLocalHostname()
{
if (!m_local_resolved)
{
ResolveLocal();
}
return m_host;
}
ipaddr_t Utility::GetLocalIP()
{
if (!m_local_resolved)
{
ResolveLocal();
}
return m_ip;
}
const std::string& Utility::GetLocalAddress()
{
if (!m_local_resolved)
{
ResolveLocal();
}
return m_addr;
}
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
const struct in6_addr& Utility::GetLocalIP6()
{
if (!m_local_resolved)
{
ResolveLocal();
}
return m_local_ip6;
}
const std::string& Utility::GetLocalAddress6()
{
if (!m_local_resolved)
{
ResolveLocal();
}
return m_local_addr6;
}
#endif
#endif
void Utility::SetEnv(const std::string& var,const std::string& value)
{
#if (defined(SOLARIS8) || defined(SOLARIS))
{
static std::map<std::string, char *> vmap;
if (vmap.find(var) != vmap.end())
{
delete[] vmap[var];
}
vmap[var] = new char[var.size() + 1 + value.size() + 1];
sprintf(vmap[var], "%s=%s", var.c_str(), value.c_str());
putenv( vmap[var] );
}
#elif defined _WIN32
{
std::string slask = var + "=" + value;
_putenv( (char *)slask.c_str());
}
#else
setenv(var.c_str(), value.c_str(), 1);
#endif
}
std::string Utility::Sa2String(struct sockaddr *sa)
{
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
if (sa -> sa_family == AF_INET6)
{
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
std::string tmp;
Utility::l2ip(sa6 -> sin6_addr, tmp);
return tmp + ":" + Utility::l2string(ntohs(sa6 -> sin6_port));
}
#endif
#endif
if (sa -> sa_family == AF_INET)
{
struct sockaddr_in *sa4 = (struct sockaddr_in *)sa;
ipaddr_t a;
memcpy(&a, &sa4 -> sin_addr, 4);
std::string tmp;
Utility::l2ip(a, tmp);
return tmp + ":" + Utility::l2string(ntohs(sa4 -> sin_port));
}
return "";
}
void Utility::GetTime(struct timeval *p)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -