1 /**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 XMLTagHandler.cpp
6
7 Dominic Mazzoni
8 Vaughan Johnson
9
10
11 *//****************************************************************//**
12
13 \class XMLTagHandler
14 \brief This class is an interface which should be implemented by
15 classes which wish to be able to load and save themselves
16 using XML files.
17
18 \class XMLValueChecker
19 \brief XMLValueChecker implements static bool methods for checking
20 input values from XML files.
21
22 *//*******************************************************************/
23
24 #include "XMLTagHandler.h"
25
26 #ifdef _WIN32
27 #include <windows.h>
28 #include <wx/msw/winundef.h>
29 #endif
30
31 #include <wx/defs.h>
32 #include <wx/arrstr.h>
33 #include <wx/filename.h>
34
35 #include "FileNames.h"
36
37
38 // "Good" means the name is well-formed and names an existing file or folder.
IsGoodFileName(const FilePath & strFileName,const FilePath & strDirName)39 bool XMLValueChecker::IsGoodFileName(const FilePath & strFileName, const FilePath & strDirName /* = "{} */)
40 {
41 // Test strFileName.
42 if (!IsGoodFileString(strFileName) ||
43 (strDirName.length() + 1 + strFileName.length() > PLATFORM_MAX_PATH))
44 return false;
45
46 // Test the corresponding wxFileName.
47 wxFileName fileName(strDirName, strFileName);
48 return (fileName.IsOk() && fileName.FileExists());
49 }
50
IsGoodFileString(const FilePath & str)51 bool XMLValueChecker::IsGoodFileString(const FilePath &str)
52 {
53 return (!str.empty() &&
54
55 // FILENAME_MAX is 260 in MSVC, but inconsistent across platforms,
56 // sometimes huge, but we use 260 for all platforms.
57 (str.length() <= 260) &&
58
59 (str.Find(wxFileName::GetPathSeparator()) == -1)); // No path separator characters.
60 }
61
IsGoodSubdirName(const FilePath & strSubdirName,const FilePath & strDirName)62 bool XMLValueChecker::IsGoodSubdirName(const FilePath & strSubdirName, const FilePath & strDirName /* = {} */)
63 {
64 // Test strSubdirName.
65 // Note this prevents path separators, and relative path to parents (strDirName),
66 // so fixes vulnerability #3 in the NGS report for UmixIt,
67 // where an attacker could craft an AUP file with relative pathnames to get to system files, for example.
68 if (!IsGoodFileString(strSubdirName) ||
69 (strSubdirName == wxT(".")) || (strSubdirName == wxT("..")) ||
70 (strDirName.length() + 1 + strSubdirName.length() > PLATFORM_MAX_PATH))
71 return false;
72
73 // Test the corresponding wxFileName.
74 wxFileName fileName(strDirName, strSubdirName);
75 return (fileName.IsOk() && fileName.DirExists());
76 }
77
IsGoodPathName(const FilePath & strPathName)78 bool XMLValueChecker::IsGoodPathName(const FilePath & strPathName)
79 {
80 // Test the corresponding wxFileName.
81 wxFileName fileName(strPathName);
82 return XMLValueChecker::IsGoodFileName(fileName.GetFullName(), fileName.GetPath(wxPATH_GET_VOLUME));
83 }
84
IsGoodPathString(const FilePath & str)85 bool XMLValueChecker::IsGoodPathString(const FilePath &str)
86 {
87 return (!str.empty() &&
88 (str.length() <= PLATFORM_MAX_PATH));
89 }
90
ReadXMLTag(const char * tag,const char ** attrs)91 bool XMLTagHandler::ReadXMLTag(const char *tag, const char **attrs)
92 {
93 mCurrentTagAttributes.clear();
94
95 while (*attrs) {
96 const char* name = *attrs++;
97 const char* value = *attrs++;
98
99 mCurrentTagAttributes.emplace_back(
100 std::string_view(name), XMLAttributeValueView(std::string_view(value)));
101 }
102
103 bool result = HandleXMLTag(tag, mCurrentTagAttributes);
104
105 return result;
106 }
107
ReadXMLEndTag(const char * tag)108 void XMLTagHandler::ReadXMLEndTag(const char *tag)
109 {
110 HandleXMLEndTag(tag);
111 }
112
ReadXMLContent(const char * s,int len)113 void XMLTagHandler::ReadXMLContent(const char *s, int len)
114 {
115 HandleXMLContent(std::string_view(s, len));
116 }
117
ReadXMLChild(const char * tag)118 XMLTagHandler *XMLTagHandler::ReadXMLChild(const char *tag)
119 {
120 return HandleXMLChild(tag);
121 }
122