CXmlItem* CXmlItem::AddItem(const CXmlItem& xi, BOOL bCopySiblings) { CXmlItem* pXI = new CXmlItem(this); pXI->Copy(xi, bCopySiblings); return AddItem(pXI); }
CXmlItem* CXmlItem::GetItem(const CString& sItemName, int nIndex) { CXmlItem* pXI = GetItem(sItemName); while (pXI && nIndex--) pXI = pXI->GetSibling(); return pXI; }
BOOL CXmlItem::DeleteItem(const CString& sItemName, const CString& sSubItemName) { CXmlItem* pXI = GetItem(sItemName, sSubItemName); if (pXI) { pXI->Reset(); // delete children and siblings DeleteItem(pXI); // delete pXI } return (pXI != NULL); }
CXmlItem* CXmlItem::SetItemValue(const CString& sName, const CString& sValue, XI_TYPE nType) { CXmlItem* pXI = GetItem(sName); if (!pXI) return AddItem(sName, sValue, nType); // else already exists pXI->SetValue(sValue); pXI->SetType(nType); return pXI; }
BOOL CXmlItem::RemoveItem(CXmlItem* pXI) { if (!pXI) return FALSE; // lookup by name first const CString& sName = pXI->GetName(); CXmlItem* pXIMatch = GetItem(sName); if (!pXIMatch) return FALSE; // now search the sibling chain looking for exact match CXmlItem* pXIPrevSibling = NULL; while (pXIMatch != pXI) { pXIPrevSibling = pXIMatch; pXIMatch = pXIMatch->GetSibling(); } if (!pXIMatch) // no match return FALSE; // else ASSERT (pXIMatch == pXI); CXmlItem* pNextSibling = pXI->GetSibling(); if (!pXIPrevSibling) // head of the chain { POSITION pos = m_lstItems.Find(pXI); if (!pNextSibling) m_lstItems.RemoveAt(pos); else m_lstItems.SetAt(pos, pNextSibling); } else // somewhere else in the chain { pXIPrevSibling->m_pSibling = pNextSibling; // can be NULL } // clear item's sibling pXI->m_pSibling = NULL; // and parent pXI->m_pParent = NULL; return TRUE; }
void CImageInfo::Parse(const CXmlItem &item) { ParseTime(item, CTimeDefined, CTime, "CREATIONTIME"); ParseTime(item, MTimeDefined, MTime, "LASTMODIFICATIONTIME"); NameDefined = ConvertUTF8ToUnicode(item.GetSubStringForTag("NAME"), Name); // IndexDefined = ParseNumber32(item.GetPropertyValue("INDEX"), Index); }
CXmlItem* CXmlItem::AddItem(CXmlItem* pXI) { CXmlItem* pXIParent = pXI->GetParent(); if (pXIParent && pXIParent != this) pXIParent->RemoveItem(pXI); pXI->m_pParent = this; // if an item of the same name already exists then add this // item as a sibling to the existing item else its a new item // so add and map name to this object CXmlItem* pXPExist = GetItem(pXI->GetName()); if (pXPExist) pXPExist->AddSibling(pXI); else m_lstItems.AddTail(pXI); return pXI; }
void CXmlItem::Copy(const CXmlItem& xi, BOOL bCopySiblings) { Reset(); // copy own name and value m_sName = xi.GetName(); m_sValue = xi.GetValue(); m_nType = xi.GetType(); // copy siblings if (bCopySiblings) { const CXmlItem* pXISibling = xi.GetSibling(); if (pXISibling) m_pSibling = new CXmlItem(*pXISibling, m_pParent); } // copy children POSITION pos = xi.GetFirstItemPos(); while (pos) { const CXmlItem* pXIChild = xi.GetNextItem(pos); ASSERT (pXIChild); AddItem(*pXIChild, TRUE); } }
IMP_IInArchive_Props IMP_IInArchive_ArcProps #define PARSE_NUM(_num_, _dest_) \ { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \ if ((unsigned)(end - p) != _num_) return 0; p += _num_ + 1; } static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) { const AString s = item.GetSubStringForTag(name); if (s.IsEmpty()) return false; const char *end; res = ConvertStringToUInt64(s, &end); return *end == 0; }
static UInt64 ParseTime(const CXmlItem &item, const char *name) { AString s = item.GetSubStringForTag(name); if (s.Length() < 20) return 0; const char *p = s; if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' || p[13] != ':' || p[16] != ':' || p[19] != 'Z') return 0; UInt32 year, month, day, hour, min, sec; if (!ParseNumber(p, 4, year )) return 0; if (!ParseNumber(p + 5, 2, month)) return 0; if (!ParseNumber(p + 8, 2, day )) return 0; if (!ParseNumber(p + 11, 2, hour )) return 0; if (!ParseNumber(p + 14, 2, min )) return 0; if (!ParseNumber(p + 17, 2, sec )) return 0; UInt64 numSecs; if (!NWindows::NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) return 0; return numSecs * 10000000; }
static UInt64 ParseTime(const CXmlItem &item, const char *name) { const AString s = item.GetSubStringForTag(name); if (s.Len() < 20) return 0; const char *p = s; if (p[ 4] != '-' || p[ 7] != '-' || p[10] != 'T' || p[13] != ':' || p[16] != ':' || p[19] != 'Z') return 0; UInt32 year, month, day, hour, min, sec; PARSE_NUM(4, year) PARSE_NUM(2, month) PARSE_NUM(2, day) PARSE_NUM(2, hour) PARSE_NUM(2, min) PARSE_NUM(2, sec) UInt64 numSecs; if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) return 0; return numSecs * 10000000; }
static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) { int index = item.FindSubTag(name); if (index < 0) return false; const CXmlItem &checkItem = item.SubItems[index]; AString style = checkItem.GetPropertyValue("style"); if (style == "SHA1") { AString s = checkItem.GetSubString(); if (s.Length() != 40) return false; for (int i = 0; i < s.Length(); i += 2) { Byte b0, b1; if (!HexToByte(s[i], b0) || !HexToByte(s[i + 1], b1)) return false; digest[i / 2] = (b0 << 4) | b1; } return true; } return false; }
static bool ParseSha1(const CXmlItem &item, const char *name, Byte *digest) { int index = item.FindSubTag(name); if (index < 0) return false; const CXmlItem &checkItem = item.SubItems[index]; const AString style = checkItem.GetPropVal("style"); if (style == "SHA1") { const AString s = checkItem.GetSubString(); if (s.Len() != SHA1_DIGEST_SIZE * 2) return false; for (unsigned i = 0; i < s.Len(); i += 2) { int b0 = HexToByte(s[i]); int b1 = HexToByte(s[i + 1]); if (b0 < 0 || b1 < 0) return false; digest[i / 2] = (Byte)((b0 << 4) | b1); } return true; } return false; }
static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent) { if (!item.IsTag) return true; if (item.Name == "file") { CFile file; file.Parent = parent; parent = files.Size(); file.Name = item.GetSubStringForTag("name"); AString type = item.GetSubStringForTag("type"); if (type == "directory") file.IsDir = true; else if (type == "file") file.IsDir = false; else return false; int dataIndex = item.FindSubTag("data"); if (dataIndex >= 0 && !file.IsDir) { file.HasData = true; const CXmlItem &dataItem = item.SubItems[dataIndex]; if (!ParseUInt64(dataItem, "size", file.Size)) return false; if (!ParseUInt64(dataItem, "length", file.PackSize)) return false; if (!ParseUInt64(dataItem, "offset", file.Offset)) return false; file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1); // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum", file.packSha1); int encodingIndex = dataItem.FindSubTag("encoding"); if (encodingIndex >= 0) { const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; if (encodingItem.IsTag) { AString s = encodingItem.GetPropVal("style"); if (!s.IsEmpty()) { const AString appl = "application/"; if (s.IsPrefixedBy(appl)) { s.DeleteFrontal(appl.Len()); const AString xx = "x-"; if (s.IsPrefixedBy(xx)) { s.DeleteFrontal(xx.Len()); if (s == "gzip") s = METHOD_NAME_ZLIB; } } file.Method = s; } } } } file.CTime = ParseTime(item, "ctime"); file.MTime = ParseTime(item, "mtime"); file.ATime = ParseTime(item, "atime"); { const AString s = item.GetSubStringForTag("mode"); if (s[0] == '0') { const char *end; file.Mode = ConvertOctStringToUInt32(s, &end); file.ModeDefined = (*end == 0); } } file.User = item.GetSubStringForTag("user"); file.Group = item.GetSubStringForTag("group"); files.Add(file); } FOR_VECTOR (i, item.SubItems) if (!AddItem(item.SubItems[i], files, parent)) return false; return true; }
void CXmlItem::SortItems(const CString& sItemName, const CString& sKeyName, XI_SORTKEY nKey, BOOL bAscending) { if (!sItemName || !sKeyName) return; // 1. sort immediate children first CXmlItem* pXIItem = GetItem(sItemName); if (!pXIItem) return; // make sure item has key value if (!pXIItem->GetItem(sKeyName)) return; // make sure at least one sibling exists BOOL bContinue = (pXIItem->GetSibling() != NULL); while (bContinue) { CXmlItem* pXIPrev = NULL; CXmlItem* pXISibling = NULL; // get this again because we have to anyway // for subsequent loops pXIItem = GetItem(sItemName); POSITION pos = m_lstItems.Find(pXIItem); // reset continue flag so that if there are no // switches then the sorting is done bContinue = FALSE; pXISibling = pXIItem->GetSibling(); while (pXISibling) { int nCompare = CompareItems(pXIItem, pXISibling, sKeyName, nKey); if (!bAscending) nCompare = -nCompare; if (nCompare > 0) { // switch items if (pXIPrev) pXIPrev->m_pSibling = pXISibling; else // we're at the head of the chain { m_lstItems.SetAt(pos, pXISibling); // m_mapItems[sItemName] = pXISibling; } pXIItem->m_pSibling = pXISibling->m_pSibling; pXISibling->m_pSibling = pXIItem; pXIPrev = pXISibling; bContinue = TRUE; // loop once more } else { pXIPrev = pXIItem; pXIItem = pXISibling; } pXISibling = pXIItem->GetSibling(); // next } } // 2. sort children's children pXIItem = GetItem(sItemName); while (pXIItem) { pXIItem->SortItems(sItemName, sKeyName, nKey, bAscending); pXIItem = pXIItem->GetSibling(); } }
static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent) { if (!item.IsTag) return true; if (item.Name == "file") { CFile file; file.Parent = parent; parent = files.Size(); file.Name = item.GetSubStringForTag("name"); AString type = item.GetSubStringForTag("type"); if (type == "directory") file.IsDir = true; else if (type == "file") file.IsDir = false; else return false; int dataIndex = item.FindSubTag("data"); if (dataIndex >= 0 && !file.IsDir) { file.HasData = true; const CXmlItem &dataItem = item.SubItems[dataIndex]; if (!ParseUInt64(dataItem, "size", file.Size)) return false; if (!ParseUInt64(dataItem, "length", file.PackSize)) return false; if (!ParseUInt64(dataItem, "offset", file.Offset)) return false; file.Sha1IsDefined = ParseSha1(dataItem, "extracted-checksum", file.Sha1); // file.packSha1IsDefined = ParseSha1(dataItem, "archived-checksum", file.packSha1); int encodingIndex = dataItem.FindSubTag("encoding"); if (encodingIndex >= 0) { const CXmlItem &encodingItem = dataItem.SubItems[encodingIndex]; if (encodingItem.IsTag) { AString s = encodingItem.GetPropertyValue("style"); if (s.Length() >= 0) { AString appl = "application/"; if (s.Left(appl.Length()) == appl) { s = s.Mid(appl.Length()); AString xx = "x-"; if (s.Left(xx.Length()) == xx) { s = s.Mid(xx.Length()); if (s == "gzip") s = METHOD_NAME_ZLIB; } } file.Method = s; } } } } file.CTime = ParseTime(item, "ctime"); file.MTime = ParseTime(item, "mtime"); file.ATime = ParseTime(item, "atime"); files.Add(file); } for (int i = 0; i < item.SubItems.Size(); i++) if (!AddItem(item.SubItems[i], files, parent)) return false; return true; }
BOOL CXmlFileEx::Decrypt(LPCTSTR szPassword) { if (!IsEncrypted()) return TRUE; // nothing to do // we don't try to decrypt if no encryption capabilities if (!CanEncrypt()) { m_nFileError = XFL_NOENCRYPTIONDLL; return FALSE; } // use existing password if required if (!szPassword) szPassword = m_sPassword; CXmlItem* pXI = GetEncryptedBlock(); if (pXI && !pXI->GetSibling()) { // else keep getting password till success or user cancels while (TRUE) { CString sPassword(szPassword); if (sPassword.IsEmpty()) { CString sExplanation(s_sPasswordExplanation); if (sExplanation.Find(_T("%s")) != -1) sExplanation.Format(s_sPasswordExplanation, GetFileName()); if (!CPasswordDialog::RetrievePassword(FALSE, sPassword, sExplanation)) { // RB - Set m_nFileError to avoid "The selected task list could not be opened..." message when cancelling m_nFileError = XFL_CANCELLED; return FALSE; } } CString sFile; if (Decrypt(pXI->GetValue(), sFile, sPassword)) { m_sPassword = sPassword; sFile.TrimLeft(); sFile.TrimRight(); sFile = _T("<ROOT>") + sFile + _T("</ROOT>"); // delete the cdata item m_xiRoot.DeleteItem(pXI); try { CXmlDocumentWrapper doc; // reparse decrypted xml if (doc.LoadXML(sFile)) { CXmlNodeWrapper node(doc.AsNode()); return ParseItem(m_xiRoot, &node); } } catch (...) { m_nFileError = XFL_BADMSXML; } return FALSE; } // RB - Added code to format the error message before calling AfxMessage else { CEnString sMessage(s_sDecryptFailed, GetFileName()); if (IDNO == AfxMessageBox(sMessage, MB_YESNO)) { m_nFileError = XFL_CANCELLED; return FALSE; } // else user will try again } } } // else m_nFileError = XFL_UNKNOWNENCRYPTION; return FALSE; }
BOOL CXmlFile::ParseItem(CXmlItem& xi, CXmlNodeWrapper* pNode) { CStringArray aNames, aValues; int nNumAttrib = pNode->GetAttributes(aNames, aValues); for (int nAttrib = 0; nAttrib < nNumAttrib; nAttrib++) { const CString& sName = aNames[nAttrib]; const CString& sVal = aValues[nAttrib]; xi.AddItem(sName, sVal); if (!ContinueParsing(sName, sVal)) return TRUE; } CXmlNodeWrapper nodeChild(pNode->GetFirstChildNode()); //for (int nNode = 0; nNode < nNumNodes; nNode++) while (nodeChild.IsValid()) { CString sName(nodeChild.Name()); CString sVal(nodeChild.GetText()); // Valik - Fully qualify NODE_CDATA_SECTION to prevent an ambiguous symbol error (C2872) in VC 7.1 int nNodeType = nodeChild.NodeTypeVal(); XI_TYPE nType = XIT_ELEMENT; if (nNodeType == MSXML2::NODE_CDATA_SECTION) nType = XIT_CDATA; else if (nNodeType == MSXML2::NODE_ATTRIBUTE) nType = XIT_ATTRIB; // if sName is empty then sVal relates to pNode if (!sName.IsEmpty()) { CXmlItem* pXI = xi.AddItem(sName, sVal, nType); if (!ContinueParsing(sName, sVal)) return TRUE; ParseItem(*pXI, &nodeChild); } // need to take care here not to overwrite a node's value by carriage returns // which can result if we load the XML preserving whitespace else { //BOOL bHasValue = (xi.GetValueLen() != 0); //BOOL bValueIsCR = (sVal == "\n"); //if (nodeChild.IsPreservingWhiteSpace() && bHasValue && bValueIsCR) if (nodeChild.IsPreservingWhiteSpace() && (xi.GetValueLen() != 0) && (sVal == "\n")) { // ignore ASSERT(1); // for debugging } else { xi.SetValue(sVal); xi.SetType(nType); } } nodeChild = nodeChild.GetNextSibling(); } return TRUE; }