strip added smb:// shares of their user/pass when adding, and instead store that...
[vuplus_xbmc] / xbmc / utils / XBMCTinyXML.cpp
1 /*
2  *      Copyright (C) 2005-2011 Team XBMC
3  *      http://www.xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19
20 #include "XBMCTinyXML.h"
21 #include "filesystem/File.h"
22 #include "RegExp.h"
23
24 #define MAX_ENTITY_LENGTH 8 // size of largest entity "&#xNNNN;"
25 #define BUFFER_SIZE 4096
26
27 CXBMCTinyXML::CXBMCTinyXML()
28 : TiXmlDocument()
29 {
30 }
31
32 CXBMCTinyXML::CXBMCTinyXML(const char *documentName)
33 : TiXmlDocument()
34 {
35   LoadFile(documentName);
36 }
37
38 CXBMCTinyXML::CXBMCTinyXML(const CStdString &documentName)
39 : TiXmlDocument()
40 {
41   LoadFile(documentName);
42 }
43
44 bool CXBMCTinyXML::LoadFile(TiXmlEncoding encoding)
45 {
46   return TiXmlDocument::LoadFile(encoding);
47 }
48
49 bool CXBMCTinyXML::LoadFile(const char *_filename, TiXmlEncoding encoding)
50 {
51   CStdString filename(_filename);
52   return LoadFile(filename, encoding);
53 }
54
55 bool CXBMCTinyXML::LoadFile(const CStdString &_filename, TiXmlEncoding encoding)
56 {
57   // There was a really terrifying little bug here. The code:
58   //    value = filename
59   // in the STL case, cause the assignment method of the std::string to
60   // be called. What is strange, is that the std::string had the same
61   // address as it's c_str() method, and so bad things happen. Looks
62   // like a bug in the Microsoft STL implementation.
63   // Add an extra string to avoid the crash.
64   CStdString filename(_filename);
65   value = filename;
66
67   XFILE::CFileStream file;
68   if (!file.Open(value))
69   {
70     SetError(TIXML_ERROR_OPENING_FILE, NULL, NULL, TIXML_ENCODING_UNKNOWN);
71     return false;
72   }
73
74   // Delete the existing data:
75   Clear();
76   location.Clear();
77
78   CStdString data;
79   data.reserve(8 * 1000);
80   StreamIn(&file, &data);
81   file.Close();
82
83   Parse(data, NULL, encoding);
84
85   if (Error())
86     return false;
87   return true;
88 }
89
90 bool CXBMCTinyXML::LoadFile(FILE *f, TiXmlEncoding encoding)
91 {
92   CStdString data("");
93   char buf[BUFFER_SIZE];
94   int result, count = 0;
95   while ((result = fread(buf, 1, BUFFER_SIZE, f)) > 0)
96   {
97     data.reserve(BUFFER_SIZE * (++count));
98     data.append(buf);
99   }
100   return Parse(data, NULL, encoding) != NULL;
101 }
102
103 bool CXBMCTinyXML::SaveFile(const char *_filename) const
104 {
105   CStdString filename(_filename);
106   return SaveFile(filename);
107 }
108
109 bool CXBMCTinyXML::SaveFile(const CStdString &filename) const
110 {
111   XFILE::CFile file;
112   if (file.OpenForWrite(filename, true))
113   {
114     TiXmlPrinter printer;
115     Accept(&printer);
116     file.Write(printer.CStr(), printer.Size());
117     return true;
118   }
119   return false;
120 }
121
122 const char *CXBMCTinyXML::Parse(const char *_data, TiXmlParsingData *prevData, TiXmlEncoding encoding)
123 {
124   CStdString data(_data);
125   return Parse(data, prevData, encoding);
126 }
127
128 const char *CXBMCTinyXML::Parse(CStdString &data, TiXmlParsingData *prevData, TiXmlEncoding encoding)
129 {
130   // Preprocess string, replacing '&' with '&amp; for invalid XML entities
131   size_t pos = 0;
132   CRegExp re(true);
133   re.RegComp("^&(amp|lt|gt|quot|apos|#x[a-fA-F0-9]{1,4}|#[0-9]{1,5});.*");
134   while ((pos = data.find("&", pos)) != CStdString::npos)
135   {
136     CStdString tmp = data.substr(pos, pos + MAX_ENTITY_LENGTH);
137     if (re.RegFind(tmp) < 0)
138       data.insert(pos + 1, "amp;");
139     pos++;
140   }
141   return TiXmlDocument::Parse(data.c_str(), prevData, encoding);
142 }
143
144 bool CXBMCTinyXML::Test()
145 {
146   // scraper results with unescaped &
147   CXBMCTinyXML doc;
148   CStdString data("<details><url function=\"ParseTMDBRating\" "
149                   "cache=\"tmdb-en-12244.json\">"
150                   "http://api.themoviedb.org/3/movie/12244"
151                   "?api_key=57983e31fb435df4df77afb854740ea9"
152                   "&language=en&#x3f;&#x003F;&#0063;</url></details>");
153   doc.Parse(data.c_str());
154   TiXmlNode *root = doc.RootElement();
155   if (root && root->ValueStr() == "details")
156   {
157     TiXmlElement *url = root->FirstChildElement("url");
158     if (url && url->FirstChild())
159     {
160       return (url->FirstChild()->ValueStr() == "http://api.themoviedb.org/3/movie/12244?api_key=57983e31fb435df4df77afb854740ea9&language=en???");
161     }
162   }
163   return false;
164 }