void UrlDecode(chartype* str)
{
chartype* s = str, *d = str;
while (*s) {
if (*s == '%') {
int digit1 = SingleHexToDecimal(s[1]);
if (digit1 != -1) {
int digit2 = SingleHexToDecimal(s[2]);
if (digit2 != -1) {
s += 3;
*d++ = (char)((digit1 << 4) | digit2);
continue;
}
}
}
*d++ = *s++;
}
*d = 0;
}
void HtmlDecode(char *str)
{
if (str == nullptr)
return;
char* p, *q;
for (p = q = str; *p != '\0'; p++, q++) {
if (*p == '&') {
if (!strncmp(p, "&", 5)) { *q = '&'; p += 4; }
else if (!strncmp(p, "'", 6)) { *q = '\''; p += 5; }
else if (!strncmp(p, ">", 4)) { *q = '>'; p += 3; }
else if (!strncmp(p, "<", 4)) { *q = '<'; p += 3; }
else if (!strncmp(p, """, 6)) { *q = '"'; p += 5; }
else { *q = *p; }
}
else *q = *p;
}
*q = '\0';
}
char* HtmlEncode(const char *str)
{
char* s, *p, *q;
int c;
if (str == nullptr)
return nullptr;
for (c = 0, p = (char*)str; *p != '\0'; p++) {
switch (*p) {
case '&': c += 5; break;
case '\'': c += 6; break;
case '>': c += 4; break;
case '<': c += 4; break;
case '"': c += 6; break;
default: c++; break;
}
}
if ((s = (char*)mir_alloc(c + 1)) != nullptr) {
for (p = (char*)str, q = s; *p != '\0'; p++) {
switch (*p) {
case '&': mir_strcpy(q, "&"); q += 5; break;
case '\'': mir_strcpy(q, "'"); q += 6; break;
case '>': mir_strcpy(q, ">"); q += 4; break;
case '<': mir_strcpy(q, "<"); q += 4; break;
case '"': mir_strcpy(q, """); q += 6; break;
default: *q = *p; q++; break;
}
}
*q = '\0';
}
return s;
}
/////////////////////////////////////////////////////////////////////////////////////////
void stripBBCode(char* src)
{
bool tag = false;
char *ps = src;
char *pd = src;
while (*ps != 0) {
if (!tag && *ps == '[') {
char ch = ps[1];
if (ch == '/') ch = ps[2];
tag = ch == 'b' || ch == 'u' || ch == 'i' || ch == 'c' || ch == 'a' || ch == 's';
}
if (!tag) *(pd++) = *ps;
else tag = *ps != ']';
++ps;
}
*pd = 0;
}
void stripColorCode(char* src)
{
unsigned char* ps = (unsigned char*)src;
unsigned char* pd = (unsigned char*)src;
while (*ps != 0) {
if (ps[0] == 0xc2 && ps[1] == 0xb7) {
char ch = ps[2];
switch (ch) {
case '#':
case '&':
case '\'':
case '@':
case '0':
ps += 3;
continue;
case '$':
if (isdigit(ps[3])) {
ps += 3;
if (isdigit(ps[1]))
ps += 2;
else
++ps;
if (ps[0] == ',' && isdigit(ps[1])) {
ps += 2;
if (isdigit(ps[1]))
ps += 2;
else
++ps;
}
continue;
}
else if (ps[3] == '#') {
ps += 4;
for (int i = 0; i < 6; ++i) {
if (isxdigit(*ps)) ++ps;
else break;
}
continue;
}
break;
}
}
*(pd++) = *(ps++);
}
*pd = 0;
}
void stripHTML(char* str)
{
char *p, *q;
for ( p=q=str; *p!='\0'; p++,q++ )
{
if ( *p == '<' )
{
if ( !strnicmp( p, "", 3 )) { mir_strcpy(q, "\r\n\r\n"); q += 3; p += 2; }
else if ( !strnicmp( p, "
", 4 )) { mir_strcpy(q, "\r\n\r\n"); q += 3; p += 3; }
else if ( !strnicmp( p, "
", 4 )) { mir_strcpy(q, "\r\n"); ++q; p += 3; }
else if ( !strnicmp( p, "
", 6 )) { mir_strcpy(q, "\r\n"); ++q; p += 5; }
else if ( !strnicmp( p, "
", 4 )) { mir_strcpy(q, "\r\n"); ++q; p += 3; }
else if ( !strnicmp( p, "
", 6 )) { mir_strcpy(q, "\r\n"); ++q; p += 5; }
else {
char *l = strchr(p, '>');
if (l) { p = l; --q; } else *q = *p;
}
}
else
*q = *p;
}
*q = '\0';
}
// Process a string, and double all % characters, according to chat.dll's restrictions
// Returns a pointer to the new string (old one is not freed)
wchar_t* EscapeChatTags(const wchar_t* pszText)
{
int nChars = 0;
for (const wchar_t* p = pszText; (p = wcschr(p, '%')) != nullptr; p++)
nChars++;
if (nChars == 0)
return mir_wstrdup(pszText);
wchar_t *pszNewText = (wchar_t*)mir_alloc(sizeof(wchar_t)*(mir_wstrlen(pszText) + 1 + nChars));
if (pszNewText == nullptr)
return mir_wstrdup(pszText);
const wchar_t *s = pszText;
wchar_t *d = pszNewText;
while (*s) {
if (*s == '%')
*d++ = '%';
*d++ = *s++;
}
*d = 0;
return pszNewText;
}
#pragma comment(lib, "Rpcrt4.lib")
char* getNewUuid(void)
{
UUID id;
UuidCreate(&id);
BYTE *p;
UuidToStringA(&id, &p);
size_t len = mir_strlen((char*)p) + 3;
char *result = (char*)mir_alloc(len);
mir_snprintf(result, len, "{%s}", p);
_strupr(result);
RpcStringFreeA(&p);
return result;
}
time_t IsoToUnixTime(const char *stamp)
{
char date[9];
int i, y;
if (stamp == nullptr)
return 0;
char *p = NEWSTR_ALLOCA(stamp);
// skip '-' chars
int si = 0, sj = 0;
while (true) {
if (p[si] == '-')
si++;
else if (!(p[sj++] = p[si++]))
break;
}
// Get the date part
for (i = 0; *p != '\0' && i < 8 && isdigit(*p); p++, i++)
date[i] = *p;
// Parse year
if (i == 6) {
// 2-digit year (1970-2069)
y = (date[0] - '0') * 10 + (date[1] - '0');
if (y < 70) y += 100;
}
else if (i == 8) {
// 4-digit year
y = (date[0] - '0') * 1000 + (date[1] - '0') * 100 + (date[2] - '0') * 10 + date[3] - '0';
y -= 1900;
}
else return 0;
struct tm timestamp;
timestamp.tm_year = y;
// Parse month
timestamp.tm_mon = (date[i - 4] - '0') * 10 + date[i - 3] - '0' - 1;
// Parse date
timestamp.tm_mday = (date[i - 2] - '0') * 10 + date[i - 1] - '0';
// Skip any date/time delimiter
for (; *p != '\0' && !isdigit(*p); p++);
// Parse time
if (sscanf(p, "%d:%d:%d", ×tamp.tm_hour, ×tamp.tm_min, ×tamp.tm_sec) != 3)
return (time_t)0;
timestamp.tm_isdst = 0; // DST is already present in _timezone below
time_t t = mktime(×tamp);
_tzset();
t -= _timezone;
return (t >= 0) ? t : 0;
}
time_t MsnTSToUnixtime(const char *pszTS)
{
char szTS[16];
if (!*pszTS) return time(nullptr);
strncpy(szTS, pszTS, 10);
return (time_t)atoi(szTS);
}