60c302f80e0fc9a96c4970364b93e6e395073f68
[vuplus_xbmc] / xbmc / utils / HTMLUtil.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://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 XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "HTMLUtil.h"
22
23 using namespace std;
24 using namespace HTML;
25
26
27 CHTMLUtil::CHTMLUtil(void)
28 {}
29
30 CHTMLUtil::~CHTMLUtil(void)
31 {}
32
33 int CHTMLUtil::FindTag(const CStdString& strHTML, const CStdString& strTag, CStdString& strtagFound, int iPos) const
34 {
35   CStdString strHTMLLow = strHTML;
36   CStdString strTagLow = strTag;
37   strHTMLLow.ToLower();
38   strTagLow.ToLower();
39   strtagFound = "";
40   int iStart = strHTMLLow.Find(strTag, iPos);
41   if (iStart < 0) return -1;
42   int iEnd = strHTMLLow.Find(">", iStart);
43   if (iEnd < 0) iEnd = (int)strHTMLLow.size();
44   strtagFound = strHTMLLow.Mid(iStart, (iEnd + 1) - iStart);
45   return iStart;
46 }
47
48 int CHTMLUtil::FindClosingTag(const CStdString& strHTML, const CStdString& strTag, CStdString& strtagFound, int iPos) const
49 {
50   CStdString strHTMLLow = strHTML;
51   CStdString strTagLow = strTag;
52   strHTMLLow.ToLower();
53   strTagLow.ToLower();
54   strtagFound = "";
55   int iStart = strHTMLLow.Find("</" + strTag, iPos);
56   if (iStart < 0) return -1;
57   int iOpenStart = strHTMLLow.Find("<" + strTag, iPos);
58   while (iOpenStart < iStart && iOpenStart != -1)
59   {
60     iStart = strHTMLLow.Find("</" + strTag, iStart + 1);
61     iOpenStart = strHTMLLow.Find("<" + strTag, iOpenStart + 1);
62   }
63
64   int iEnd = strHTMLLow.Find(">", iStart);
65   if (iEnd < 0) iEnd = (int)strHTMLLow.size();
66   strtagFound = strHTMLLow.Mid(iStart, (iEnd + 1) - iStart);
67   return iStart;
68 }
69
70 void CHTMLUtil::getValueOfTag(const CStdString& strTagAndValue, CStdString& strValue)
71 {
72   // strTagAndValue contains:
73   // like <a href=blablabla.....>value</a>
74   strValue = strTagAndValue;
75   int iStart = strTagAndValue.Find(">");
76   int iEnd = strTagAndValue.Find("<", iStart + 1);
77   if (iStart >= 0 && iEnd >= 0)
78   {
79     iStart++;
80     strValue = strTagAndValue.Mid(iStart, iEnd - iStart);
81   }
82 }
83
84 void CHTMLUtil::getAttributeOfTag(const CStdString& strTagAndValue, const CStdString& strTag, CStdString& strValue)
85 {
86   // strTagAndValue contains:
87   // like <a href=""value".....
88   strValue = strTagAndValue;
89   int iStart = strTagAndValue.Find(strTag);
90   if (iStart < 0) return ;
91   iStart += (int)strTag.size();
92   while (strTagAndValue[iStart + 1] == 0x20 || strTagAndValue[iStart + 1] == 0x27 || strTagAndValue[iStart + 1] == 34) iStart++;
93   int iEnd = iStart + 1;
94   while (strTagAndValue[iEnd] != 0x27 && strTagAndValue[iEnd] != 0x20 && strTagAndValue[iEnd] != 34 && strTagAndValue[iEnd] != '>') iEnd++;
95   if (iStart >= 0 && iEnd >= 0)
96   {
97     strValue = strTagAndValue.Mid(iStart, iEnd - iStart);
98   }
99 }
100
101 void CHTMLUtil::RemoveTags(CStdString& strHTML)
102 {
103   int iNested = 0;
104   CStdString strReturn = "";
105   for (int i = 0; i < (int) strHTML.size(); ++i)
106   {
107     if (strHTML[i] == '<') iNested++;
108     else if (strHTML[i] == '>') iNested--;
109     else
110     {
111       if (!iNested)
112       {
113         strReturn += strHTML[i];
114       }
115     }
116   }
117
118   strHTML = strReturn;
119 }
120
121 typedef struct
122 {
123   const wchar_t* html;
124   const wchar_t  w;
125 } HTMLMapping;
126
127 static const HTMLMapping mappings[] =
128   {{L"&amp;",     0x0026},
129    {L"&apos;",    0x0027},
130    {L"&acute;",   0x00B4},
131    {L"&agrave;",  0x00E0},
132    {L"&aacute;",  0x00E1},
133    {L"&acirc;",   0x00E2},
134    {L"&atilde;",  0x00E3},
135    {L"&auml;",    0x00E4},
136    {L"&aring;",   0x00E5},
137    {L"&aelig;",   0x00E6},
138    {L"&Agrave;",  0x00C0},
139    {L"&Aacute;",  0x00C1},
140    {L"&Acirc;",   0x00C2},
141    {L"&Atilde;",  0x00C3},
142    {L"&Auml;",    0x00C4},
143    {L"&Aring;",   0x00C5},
144    {L"&AElig;",   0x00C6},
145    {L"&bdquo;",   0x201E},
146    {L"&brvbar;",  0x00A6},
147    {L"&bull;",    0x2022},
148    {L"&bullet;",  0x2022},
149    {L"&cent;",    0x00A2},
150    {L"&circ;",    0x02C6},
151    {L"&curren;",  0x00A4},
152    {L"&copy;",    0x00A9},
153    {L"&cedil;",   0x00B8},
154    {L"&Ccedil;",  0x00C7},
155    {L"&ccedil;",  0x00E7},
156    {L"&dagger;",  0x2020},
157    {L"&deg;",     0x00B0},
158    {L"&divide;",  0x00F7},
159    {L"&Dagger;",  0x2021},
160    {L"&egrave;",  0x00E8},
161    {L"&eacute;",  0x00E9},
162    {L"&ecirc;",   0x00EA},
163    {L"&emsp;",    0x2003},
164    {L"&ensp;",    0x2002},
165    {L"&euml;",    0x00EB},
166    {L"&eth;",     0x00F0},
167    {L"&euro;",    0x20AC},
168    {L"&Egrave;",  0x00C8},
169    {L"&Eacute;",  0x00C9},
170    {L"&Ecirc;",   0x00CA},
171    {L"&Euml;",    0x00CB},
172    {L"&ETH;",     0x00D0},
173    {L"&quot;",    0x0022},
174    {L"&frasl;",   0x2044},
175    {L"&frac14;",  0x00BC},
176    {L"&frac12;",  0x00BD},
177    {L"&frac34;",  0x00BE},
178    {L"&gt;",      0x003E},
179    {L"&hellip;",  0x2026},
180    {L"&iexcl;",   0x00A1},
181    {L"&iquest;",  0x00BF},
182    {L"&igrave;",  0x00EC},
183    {L"&iacute;",  0x00ED},
184    {L"&icirc;",   0x00EE},
185    {L"&iuml;",    0x00EF},
186    {L"&Igrave;",  0x00CC},
187    {L"&Iacute;",  0x00CD},
188    {L"&Icirc;",   0x00CE},
189    {L"&Iuml;",    0x00CF},
190    {L"&lrm;",     0x200E},
191    {L"&lt;",      0x003C},
192    {L"&laquo;",   0x00AB},
193    {L"&ldquo;",   0x201C},
194    {L"&lsaquo;",  0x2039},
195    {L"&lsquo;",   0x2018},
196    {L"&macr;",    0x00AF},
197    {L"&micro;",   0x00B5},
198    {L"&middot;",  0x00B7},
199    {L"&mdash;",   0x2014},
200    {L"&nbsp;",    0x00A0},
201    {L"&ndash;",   0x2013},
202    {L"&ntilde;",  0x00F1},
203    {L"&not;",     0x00AC},
204    {L"&Ntilde;",  0x00D1},
205    {L"&ordf;",    0x00AA},
206    {L"&ordm;",    0x00BA},
207    {L"&oelig;",   0x0153},
208    {L"&ograve;",  0x00F2},
209    {L"&oacute;",  0x00F3},
210    {L"&ocirc;",   0x00F4},
211    {L"&otilde;",  0x00F5},
212    {L"&ouml;",    0x00F6},
213    {L"&oslash;",  0x00F8},
214    {L"&OElig;",   0x0152},
215    {L"&Ograve;",  0x00D2},
216    {L"&Oacute;",  0x00D3},
217    {L"&Ocirc;",   0x00D4},
218    {L"&Otilde;",  0x00D5},
219    {L"&Ouml;",    0x00D6},
220    {L"&Oslash;",  0x00D8},
221    {L"&para;",    0x00B6},
222    {L"&permil;",  0x2030},
223    {L"&plusmn;",  0x00B1},
224    {L"&pound;",   0x00A3},
225    {L"&raquo;",   0x00BB},
226    {L"&rdquo;",   0x201D},
227    {L"&reg;",     0x00AE},
228    {L"&rlm;",     0x200F},
229    {L"&rsaquo;",  0x203A},
230    {L"&rsquo;",   0x2019},
231    {L"&sbquo;",   0x201A},
232    {L"&scaron;",  0x0161},
233    {L"&sect;",    0x00A7},
234    {L"&shy;",     0x00AD},
235    {L"&sup1;",    0x00B9},
236    {L"&sup2;",    0x00B2},
237    {L"&sup3;",    0x00B3},
238    {L"&szlig;",   0x00DF},
239    {L"&Scaron;",  0x0160},
240    {L"&thinsp;",  0x2009},
241    {L"&thorn;",   0x00FE},
242    {L"&tilde;",   0x02DC},
243    {L"&times;",   0x00D7},
244    {L"&trade;",   0x2122},
245    {L"&THORN;",   0x00DE},
246    {L"&uml;",     0x00A8},
247    {L"&ugrave;",  0x00F9},
248    {L"&uacute;",  0x00FA},
249    {L"&ucirc;",   0x00FB},
250    {L"&uuml;",    0x00FC},
251    {L"&Ugrave;",  0x00D9},
252    {L"&Uacute;",  0x00DA},
253    {L"&Ucirc;",   0x00DB},
254    {L"&Uuml;",    0x00DC},
255    {L"&yen;",     0x00A5},
256    {L"&yuml;",    0x00FF},
257    {L"&yacute;",  0x00FD},
258    {L"&Yacute;",  0x00DD},
259    {L"&Yuml;",    0x0178},
260    {L"&zwj;",     0x200D},
261    {L"&zwnj;",    0x200C},
262    {NULL,         L'\0'}};
263
264 void CHTMLUtil::ConvertHTMLToW(const CStdStringW& strHTML, CStdStringW& strStripped)
265 {
266   if (strHTML.size() == 0)
267   {
268     strStripped.Empty();
269     return ;
270   }
271   int iPos = 0;
272   strStripped = strHTML;
273   while (mappings[iPos].html)
274   {
275     strStripped.Replace(mappings[iPos].html,CStdStringW(1, mappings[iPos].w));
276     iPos++;
277   }
278
279   iPos = strStripped.Find(L"&#");
280   while (iPos > 0 && iPos < (int)strStripped.size()-4)
281   {
282     int iStart = iPos + 1;
283     iPos += 2;
284     CStdStringW num;
285     int base = 10;
286     if (strStripped[iPos+1] == L'x')
287     {
288       base = 16;
289       iPos++;
290     }
291
292     int i=iPos;
293     while ( iPos < (int)strStripped.size() && 
294            (base==16?iswxdigit(strStripped[iPos]):iswdigit(strStripped[iPos])))
295       iPos++; 
296
297     num = strStripped.Mid(i,iPos-i);
298     wchar_t val = (wchar_t)wcstol(num.c_str(),NULL,base);
299     if (base == 10)
300       num.Format(L"&#%ls;",num.c_str());
301     else
302       num.Format(L"&#x%ls;",num.c_str());
303
304     strStripped.Replace(num,CStdStringW(1,val));
305     iPos = strStripped.Find(L"&#", iStart);
306   }
307 }
308