📄 xml.cpp
字号:
// xml.cpp
#include "stdafx.h"
#ifdef XML_USE_NAMESPACE
namespace XMLPP
{
#endif
#ifdef USE_EXTERNAL_Z
#include "z.h"
#endif
#include "xml.h"
#ifdef __WATCOMC__
#define _atoi64(x) atoll(x)
#endif
#ifndef __SYMBIAN32__
#ifndef LINUX
#pragma comment(lib,"wininet.lib")
#endif
#endif
//#pragma warning (disable:4244)
//#pragma warning (disable:4267)
//#pragma warning (disable:4800)
#pragma warning (disable:4996)
#ifdef LINUX
#define strcmpi(a,b) strcmp(a,b)
#endif
#ifdef WINCE
#define strcmpi(a,b) strcmp(a,b)
#endif
#ifndef XML_MAX_INIT_CHILDREN
#define XML_MAX_INIT_CHILDREN 20
#endif
#ifndef XML_MAX_INIT_VARIABLES
#define XML_MAX_INIT_VARIABLES 20
#endif
#ifndef XML_MAX_INIT_CONTENTS
#define XML_MAX_INIT_CONTENTS 4
#endif
#ifndef XML_MAX_INIT_COMMENTS
#define XML_MAX_INIT_COMMENTS 10
#endif
#ifndef XML_MAX_INIT_CDATAS
#define XML_MAX_INIT_CDATAS 10
#endif
#ifndef XML_MAX_INIT_COMMENTS_HEADER
#define XML_MAX_INIT_COMMENTS_HEADER 5
#endif
// Help functions
#define MATCH_TRUE 1
#define MATCH_FALSE 0
#define MATCH_ABORT -1
#define NEGATE_CLASS
#define OPTIMIZE_JUST_STAR
#undef MATCH_TAR_PATTERN
// OPTI
/* Extra definitions
XML_OPTIONAL_WIN32
XML_OPTIONAL_IMPORTDB
XML_OPTIONAL_MIME
XML_OPTIONAL_IMPORTRKEY
*/
#ifdef XML_OPTIONAL_MIME
#include "mime.h"
#endif
int XML :: DoMatch(const char *text, char *p, bool IsCaseSensitive)
{
// probably the MOST DIFFICULT FUNCTION in TurboIRC
// Thanks to BitchX for copying this function
//int last;
int matched;
//int reverse;
int pT = 0;
int pP = 0;
for(; p[pP] != '\0'; pP++, pT++)
{
if (text[pT] == '\0' && p[pP] != '*')
return MATCH_ABORT;
switch (p[pP])
{
// case '\\': // Match with following char
// pP++;
// NO BREAK HERE
default:
if (IsCaseSensitive)
{
if (text[pT] != p[pP])
return MATCH_FALSE;
else
continue;
}
if (toupper(text[pT]) != toupper(p[pP]))
// if (DMtable[text[pT]] != DMtable[p[pP]])
return MATCH_FALSE;
continue;
case '?':
continue;
case '*':
if (p[pP] == '*')
pP++;
if (p[pP] == '\0')
return MATCH_TRUE;
while (text[pT])
{
matched = DoMatch(text + pT++, p + pP);
if (matched != MATCH_FALSE)
return matched;
}
return MATCH_ABORT;
}
}
#ifdef MATCH_TAR_PATTERN
if (text[pT] == '/')
return MATCH_TRUE;
#endif
return (text[pT] == '\0');
}
// This will be called from the other funcs
bool XML :: VMatching(const char *text, char *p, bool IsCaseSensitive)
{
#ifdef OPTIMIZE_JUST_STAR
if (p[0] == '*' && p[1] == '\0')
return MATCH_TRUE;
#endif
return (DoMatch(text, p, IsCaseSensitive) == MATCH_TRUE);
}
// XML class
void XML :: Version(XML_VERSION_INFO* x)
{
x->VersionLow = (XML_VERSION & 0xFF);
x->VersionHigh = (XML_VERSION >> 8);
strcpy(x->RDate,XML_VERSION_REVISION_DATE);
}
XML :: XML()
{
Init();
IsFileU = false;
}
void XML :: SetUnicode(bool x)
{
IsFileU = x;
}
XML :: XML(const char* file,XML_LOAD_MODE LoadMode,class XMLTransform* eclass,class XMLTransformData* edata)
{
Init();
Load(file,LoadMode,eclass,edata);
}
#ifndef LINUX
XML :: XML(const wchar_t* file,XML_LOAD_MODE LoadMode,class XMLTransform* eclass,class XMLTransformData* edata)
{
Init();
Load((char*)file,XML_LOAD_MODE_LOCAL_FILE_U,eclass,edata);
}
#endif
size_t XML :: LoadText(const char* txt)
{
return Load(txt,XML_LOAD_MODE_MEMORY_BUFFER,0,0);
}
size_t XML :: LoadText(const wchar_t* txt)
{
#ifdef _WIN32
size_t udsize = wcslen(txt);
size_t dsize = udsize*4 + 1000; // just for safety
Z<char> utfbuff(dsize);
// Conver the array
WideCharToMultiByte(CP_UTF8,0,txt,-1,utfbuff,(int)dsize,0,0);
return LoadText(utfbuff);
#else
return 0;
#endif
}
void XML :: Init()
{
SOnClose = 0;
hdr = 0;
root = 0;
f = 0;
}
void XML :: Clear()
{
if (SOnClose)
Save();
// root
if (root)
{
root->RemoveAllElements();
delete root;
}
root = 0;
// hdr
if (hdr)
delete hdr;
hdr = 0;
// item
if (f)
delete[] f;
f = 0;
}
XMLElement* XML :: GetRootElement()
{
return root;
}
void XML :: Lock(bool)
{
}
void XML :: SetRootElement(XMLElement* newroot)
{
delete root;
root = 0;
root = newroot;
return;
}
XMLElement* XML :: RemoveRootElementAndKeep()
{
XMLElement* x = root;
root = new XMLElement(0,"<root/>");
return x;
}
int XML :: RemoveTemporalElements()
{
if (!root)
return 0;
int iN = 0;
iN += root->RemoveTemporalElements(true);
iN += root->RemoveTemporalVariables(true);
return iN;
}
XMLHeader* XML :: GetHeader()
{
return hdr;
}
void XML :: SetHeader(XMLHeader* h)
{
if (hdr)
delete hdr;
hdr = 0;
hdr = h;
}
size_t XML :: XMLEncode(const char* src,char* trg)
{
if (!src)
return 0;
//*...
size_t Y = strlen(src);
size_t x = 0;
for(size_t i = 0 ; i < Y ; i++)
{
if (src[i] == '&' && src[i + 1] != '#')
{
if (trg)
strcat(trg + x,"&");
x += 5;
continue;
}
if (src[i] == '>')
{
if (trg)
strcat(trg + x,">");
x += 4;
continue;
}
if (src[i] == '<')
{
if (trg)
strcat(trg + x,"<");
x += 4;
continue;
}
if (src[i] == '\"')
{
if (trg)
strcat(trg + x,""");
x += 6;
continue;
}
if (src[i] == '\'')
{
if (trg)
strcat(trg + x,"'");
x += 6;
continue;
}
if (trg)
trg[x] = src[i];
x++;
}
if (trg)
trg[x] = 0;
return x;
}
#ifdef XML_OPTIONAL_IMPORTRKEY
XMLElement* XML :: ImportRKey(IMPORTRKEYDATA* d)
{
HKEY pK = d->pK;
int mode = d->StorageType;
XMLElement* x = new XMLElement(0,"<root />");
// Reads pK (Assumes it is open) and imports ALL children !
// if mode == 0 , native backup
// no name prefix, variable B,I,Y,E,Z,N,Q,S
//
// Reads Values of pK and writes it to myself
for(int i = 0 ; ; i++)
{
Z<char> tmp1(300);
DWORD ts = 20000;
DWORD ty = 0;
DWORD si = 0;
RegEnumValue(pK,i,tmp1,&ts,0,&ty,0,&si);
Z<char> tmp2(si + 10);
ts = 20000;
if (RegEnumValue(pK,i,tmp1,&ts,0,&ty,(unsigned char*)tmp2.operator char *() + 2,&si) != ERROR_SUCCESS)
break; // end of values
// write
if (ty == REG_BINARY)
tmp2[0] = 'B';
if (ty == REG_DWORD)
tmp2[0] = 'I';
if (ty == REG_DWORD_BIG_ENDIAN)
tmp2[0] = 'Y';
if (ty == REG_EXPAND_SZ)
tmp2[0] = 'E';
if (ty == REG_MULTI_SZ)
tmp2[0] = 'Z';
if (ty == REG_NONE)
tmp2[0] = 'N';
if (ty == REG_QWORD)
tmp2[0] = 'Q';
if (ty == REG_SZ)
tmp2[0] = 'S';
if (mode == 0)
tmp2[1] = '_';
XMLVariable* v = new XMLVariable(tmp1,tmp2);
x->AddVariable(v);
}
// Now enum children keys and do the same
for(int i = 0 ; ; i++)
{
Z<char> tmp1(300);
Z<char> tmp2(300);
DWORD si = 300;
if (RegEnumKeyEx(pK,i,tmp1,&si,0,0,0,0) != ERROR_SUCCESS)
break; // end of values
sprintf(tmp2,"<%s />",tmp1.operator char*());
XMLElement* child = new XMLElement(x,tmp2);
HKEY NewPK = 0;
RegOpenKeyEx(pK,tmp1,0,KEY_ALL_ACCESS,&NewPK);
if (NewPK)
{
IMPORTRKEYDATA d2 = {0};
d2.pK = NewPK;
d2.StorageType = mode;
ImportRKey(&d2);
x->AddElement(child);
RegCloseKey(NewPK);
}
}
return x;
}
#endif
#ifdef XML_OPTIONAL_IMPORTDB
#include <exdisp.h>
#include <urlmon.h>
#include <shlobj.h>
//#include <adoid.h>
#include <adoint.h>
#define ADOGUID(name, l) extern "C" const GUID name = \
{l, 0, 0x10, 0x80,0,0,0xAA,0,0x6D,0x2E,0xA4}
ADOGUID(CLSID_CADOConnection,0x00000514);
ADOGUID(IID_IADOConnection,0x00000550);
XMLElement* XML :: ImportDB(IMPORTDBPARAMS* db)
{
// Imports an MDB database with ADO
XMLElement* r = 0;
Z<char> str(1000);
Z<wchar_t> wstr(1000);
ADOConnection* aC = 0;
HRESULT hr;
BSTR b1 = 0,b2 = 0,b3 = 0;
// Open Database
CoCreateInstance(CLSID_CADOConnection,0,CLSCTX_ALL,IID_IADOConnection,(void**)&aC);
if (!aC)
goto E_0;
if (db->provstr == 0)
sprintf(str,"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s",db->dbname);
else
sprintf(str,db->provstr,db->dbname);
MultiByteToWideChar(CP_ACP,0,str,-1,wstr,1000);
b1 = SysAllocString(L"");
b2 = SysAllocString(L"");
b3 = SysAllocString(wstr);
hr = aC->Open(b3,b1,b2,0);
SysFreeString(b1);
SysFreeString(b2);
SysFreeString(b3);
if (hr)
goto E_1;
r = new XMLElement(0,"<db />");
// Loop for all tables
for(int iTable = 0 ; iTable < db->nTables ; iTable++)
{
ADORecordset* aR = 0;
VARIANT* RecordsAffected = 0;
sprintf(str,"SELECT * FROM %s",db->Tables[iTable].name);
MultiByteToWideChar(CP_ACP,0,str,-1,wstr,1000);
b1 = SysAllocString(wstr);
hr = aC->Execute(b1,RecordsAffected,0,&aR);
SysFreeString(b1);
if (hr)
continue;
// Add this table to r
sprintf(str,"<%s />",db->Tables[iTable].name);
XMLElement* rT = new XMLElement(r,str);
r->AddElement(rT);
aR->MoveFirst();
long TotalRecords = 0;
aR->get_RecordCount(&TotalRecords);
for(unsigned int y = 0 ; y < (unsigned)TotalRecords ; y++)
{
// We are looping the items now
short IsEOF;
aR->get_EOF(&IsEOF);
if (IsEOF == VARIANT_TRUE)
break;
long RecordCount = 0;
ADOFields* aFS = 0;
aR->get_Fields(&aFS);
aFS->get_Count(&RecordCount);
// Add this item
sprintf(str,"<%s />",db->Tables[iTable].itemname);
XMLElement* rItem = new XMLElement(rT,str);
rT->AddElement(rItem);
for(int iVariables = 0 ; iVariables < RecordCount ; iVariables++)
{
// We are loopting the variables now, get only what we actually need
ADOField* aF = 0;
VARIANT vt;
vt.vt= VT_I4;
vt.intVal = iVariables;
aFS->get_Item(vt,&aF);
if (!aF)
continue;
wchar_t* Name;
aF->get_Name(&Name);
VARIANT Value;
aF->get_Value(&Value);
if (Value.vt == VT_BSTR)
WideCharToMultiByte(CP_UTF8, 0, Value.bstrVal, -1, str, 1000,0,0);
else
if (Value.vt == VT_I4)
sprintf(str,"%u",Value.lVal);
// Should we add this variable to the rItem ?
int SL = wcslen(Name);
Z<char> nam(SL*2 + 100);
WideCharToMultiByte(CP_UTF8, 0, Name, -1, nam, SL*2 + 100,0,0);
int IsToAdd = -1;
for(int yAdds = 0; yAdds < db->Tables[iTable].nVariables ; yAdds++)
{
if (strcmpi(db->Tables[iTable].Variables[yAdds],nam) == 0)
{
IsToAdd = yAdds;
break;
}
}
if (IsToAdd != -1)
{
char* thename = nam;
if (db->Tables[iTable].ReplaceVariables[IsToAdd])
thename = db->Tables[iTable].ReplaceVariables[IsToAdd];
XMLVariable* var = new XMLVariable(thename,str);
rItem->AddVariable(var);
}
if (Name)
SysFreeString(Name);
if (Value.vt == VT_BSTR)
SysFreeString(Value.bstrVal);
aF->Release();
}
aFS->Release();
aR->MoveNext();
}
}
E_1:
aC->Release();
E_0:
return r;
}
#endif
int XMLHelper :: pow(int P,int z)
{
if (z == 0)
return 1;
int x = P;
for(int i = 1 ; i < z ; i++)
x*= P;
return x;
}
size_t XML :: XMLDecode(const char* src,char* trg)
{
size_t Y = strlen(src);
if (!trg)
return Y;
size_t x = 0;
for(size_t i = 0 ; i < Y ; )
{
char* fo = strchr((char*)src + i,'&');
if (!fo)
{
// end of &s
strcpy(trg + x,src + i);
x = strlen(trg);
break;
}
if (fo)
{
size_t untilfo = fo - (src + i);
strncpy(trg + x,src + i,untilfo);
i += untilfo;
x += untilfo;
}
if (src[i] == '&' && src[i + 1] == '#' && tolower(src[i + 2]) == 'x')
{
i += 3;
int dig[10] = {0};
int y = 0;
while ((src[i] >= 0x30 && src[i] <= 0x39) || (src[i] >= 'a' && src[i] <= 'f') || (src[i] >= 'A' && src[i] <= 'F'))
{
char C = src[i];
if (C >= 0x30 && C <= 0x39)
C -= 0x30;
else
if (C >= 0x41 && C <= 0x46)
C -= 55;
else
if (C >= 0x61 && C <= 0x66)
C -= 87;
dig[y] = C;
y++;
i++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -