Logo ROOT  
Reference Guide
TGHtmlUri.cxx
Go to the documentation of this file.
1// $Id$
2// Author: Valeriy Onuchin 03/05/2007
3
4/*************************************************************************
5 * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/**************************************************************************
13
14 HTML widget for xclass. Based on tkhtml 1.28
15 Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
16 Copyright (C) 2002-2003 Hector Peraza.
17
18 This library is free software; you can redistribute it and/or
19 modify it under the terms of the GNU Library General Public
20 License as published by the Free Software Foundation; either
21 version 2 of the License, or (at your option) any later version.
22
23 This library is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26 Library General Public License for more details.
27
28 You should have received a copy of the GNU Library General Public
29 License along with this library; if not, write to the Free
30 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
32**************************************************************************/
33
34// Routines for processing URLs.
35
36#include <ctype.h>
37#include <cstring>
38#include <cstdlib>
39
40#include "TGHtml.h"
41#include "TGHtmlUri.h"
42#include "strlcpy.h"
43
44static char *StrNDup(const char *z, int n);
45static void ReplaceStr(char **pzDest, const char *zSrc);
46#if 0 // not used
47static char *Trim(char *z);
48#endif
49
50
51////////////////////////////////////////////////////////////////////////////////
52/// Parse a text URI into an HtmlUri structure.
53
54TGHtmlUri::TGHtmlUri(const char *zUri)
55{
56 int n;
57
59
60 if (zUri && *zUri) {
61 while (isspace(*zUri)) ++zUri;
62 n = ComponentLength(zUri, "", ":/?# ");
63 if (n > 0 && zUri[n] == ':') {
64 fZScheme = StrNDup(zUri, n);
65 zUri += n+1;
66 }
67 n = ComponentLength(zUri, "//", "/?# ");
68 if (n > 0) {
69 fZAuthority = StrNDup(&zUri[2], n-2);
70 zUri += n;
71 }
72 n = ComponentLength(zUri, "", "?# ");
73 if (n > 0) {
74 fZPath = StrNDup(zUri, n);
75 zUri += n;
76 }
77 n = ComponentLength(zUri, "?", "# ");
78 if (n > 0) {
79 fZQuery = StrNDup(&zUri[1], n-1);
80 zUri += n;
81 }
82 n = ComponentLength(zUri, "#", " ");
83 if (n > 0) {
84 fZFragment = StrNDup(&zUri[1], n-1);
85 }
86 }
87}
88
89////////////////////////////////////////////////////////////////////////////////
90/// Html uri copy constructor.
91
93{
95
96 if (uri) {
97 if (uri->fZScheme) fZScheme = StrDup(uri->fZScheme);
98 if (uri->fZAuthority) fZAuthority = StrDup(uri->fZAuthority);
99 if (uri->fZPath) fZPath = StrDup(uri->fZPath);
100 if (uri->fZQuery) fZQuery = StrDup(uri->fZQuery);
101 if (uri->fZFragment) fZFragment = StrDup(uri->fZFragment);
102 }
103}
104
105////////////////////////////////////////////////////////////////////////////////
106/// Html uri destructor.
107
109{
110 if (fZScheme) delete[] fZScheme;
111 if (fZAuthority) delete[] fZAuthority;
112 if (fZPath) delete[] fZPath;
113 if (fZQuery) delete[] fZQuery;
114 if (fZFragment) delete[] fZFragment;
115}
116
117////////////////////////////////////////////////////////////////////////////////
118/// Compare another uri with given field mask.
119
120int TGHtmlUri::EqualsUri(const TGHtmlUri *uri, int field_mask)
121{
122 if (!uri) return 0;
123
124 if (field_mask & URI_SCHEME_MASK) {
125 if (uri->fZScheme && fZScheme) {
126 if (strcmp(uri->fZScheme, fZScheme) != 0) return 0;
127 } else if (uri->fZScheme != fZScheme) { // one of them null?
128 return 0;
129 }
130 }
131
132 if (field_mask & URI_AUTH_MASK) {
133 if (uri->fZAuthority && fZAuthority) {
134 if (strcmp(uri->fZAuthority, fZAuthority) != 0) return 0;
135 } else if (uri->fZAuthority != fZAuthority) {
136 return 0;
137 }
138 }
139
140 if (field_mask & URI_PATH_MASK) {
141 if (uri->fZPath && fZPath) {
142 if (strcmp(uri->fZPath, fZPath) != 0) return 0;
143 } else if (uri->fZPath != fZPath) {
144 return 0;
145 }
146 }
147
148 if (field_mask & URI_QUERY_MASK) {
149 if (uri->fZQuery && fZQuery) {
150 if (strcmp(uri->fZQuery, fZQuery) != 0) return 0;
151 } else if (uri->fZQuery != fZQuery) {
152 return 0;
153 }
154 }
155
156 if (field_mask & URI_FRAGMENT_MASK) {
157 if (uri->fZFragment && fZFragment) {
158 if (strcmp(uri->fZFragment, fZFragment) != 0) return 0;
159 } else if (uri->fZFragment != fZFragment) {
160 return 0;
161 }
162 }
163
164 return 1;
165}
166
167////////////////////////////////////////////////////////////////////////////////
168/// Return the length of the next component of the URL in z[] given
169/// that the component starts at z[0]. The initial sequence of the
170/// component must be zInit[]. The component is terminated by any
171/// character in zTerm[]. The length returned is 0 if the component
172/// doesn't exist. The length includes the zInit[] string, but not
173/// the termination character.
174///
175/// Component zInit zTerm
176/// ---------- ------- -------
177/// scheme "" ":/?#"
178/// authority "//" "/?#"
179/// path "/" "?#"
180/// query "?" "#"
181/// fragment "#" ""
182
183int TGHtmlUri::ComponentLength(const char *z, const char *zInit, const char *zTerm)
184{
185 int i, n;
186
187 for (n = 0; zInit[n]; ++n) {
188 if (zInit[n] != z[n]) return 0;
189 }
190 while (z[n]) {
191 for (i = 0; zTerm[i]; ++i) {
192 if (z[n] == zTerm[i]) return n;
193 }
194 ++n;
195 }
196
197 return n;
198}
199
200////////////////////////////////////////////////////////////////////////////////
201/// Create a string to hold the given URI. Memory to hold the string is
202/// allocated with new[] and must be freed by the calling function.
203
205{
206 TString uri;
207
208 if (fZScheme)
209 uri.Append(TString::Format("%s:", fZScheme));
210
211 if (fZAuthority)
212 uri.Append(TString::Format("//%s", fZAuthority));
213
214 if (fZAuthority && fZAuthority[strlen(fZAuthority)-1] != '/' &&
215 !(fZPath && fZPath[0] == '/'))
216 uri.Append("/");
217
218 if (fZPath)
219 uri.Append(fZPath);
220
221 if (fZQuery)
222 uri.Append(TString::Format("?%s", fZQuery));
223
224 if (fZFragment)
225 uri.Append(TString::Format("#%s", fZFragment));
226
227 return StrDup(uri.Data());
228}
229
230
231////////////////////////////////////////////////////////////////////////////////
232/// Duplicate a string of length n.
233
234static char *StrNDup(const char *z, int n)
235{
236 char *zResult;
237
238 if (n <= 0) n = strlen(z);
239 zResult = new char[n + 1];
240 if (zResult) {
241 memcpy(zResult, z, n);
242 zResult[n] = 0;
243 }
244 return zResult;
245}
246
247////////////////////////////////////////////////////////////////////////////////
248/// Replace the string in *pzDest with the string in zSrc
249
250static void ReplaceStr(char **pzDest, const char *zSrc)
251{
252 if (*pzDest != 0) delete[] *pzDest;
253 if (zSrc == 0) {
254 *pzDest = 0;
255 } else {
256 *pzDest = StrNDup(zSrc, -1);
257 }
258}
259
260#if 0 // not used
261static char *Trim(char *z)
262{
263 // Remove leading and trailing spaces from the given string. Return
264 // a new string allocated with new[].
265 int i;
266 char *zNew;
267
268 while (isspace(*z)) z++;
269 i = strlen(z);
270 zNew = new char[i + 1];
271 if (zNew == 0) return 0;
272 strcpy(zNew, z);
273 while (i > 0 && isspace(zNew[i-1])) zNew[--i] = 0;
274
275 return zNew;
276}
277#endif
278
279////////////////////////////////////////////////////////////////////////////////
280/// This function resolves the specified URI and returns the result in
281/// a newly allocated string. The resolver algorithm specified in section
282/// 5.2 of RFC 2396 is used.
283
284char *TGHtml::ResolveUri(const char *zUri)
285{
286 char *result = 0;
287 TGHtmlUri *base, *term;
288
289 if (zUri == 0 || *zUri == 0) return 0;
290
291 if (fZBaseHref && *fZBaseHref) {
292 base = new TGHtmlUri(fZBaseHref);
293 } else {
294 base = new TGHtmlUri(fZBase);
295 }
296
297 term = new TGHtmlUri(zUri);
298
299 if (term->fZScheme == 0 &&
300 term->fZAuthority == 0 &&
301 term->fZPath == 0 &&
302 term->fZQuery == 0 &&
303 term->fZFragment) {
304 ReplaceStr(&base->fZFragment, term->fZFragment);
305 } else if (term->fZScheme) {
306 TGHtmlUri *temp;
307 temp = term;
308 term = base;
309 base = temp;
310 } else if (term->fZAuthority) {
311 ReplaceStr(&base->fZAuthority, term->fZAuthority);
312 ReplaceStr(&base->fZPath, term->fZPath);
313 ReplaceStr(&base->fZQuery, term->fZQuery);
314 ReplaceStr(&base->fZFragment, term->fZFragment);
315 } else if (term->fZPath && (term->fZPath[0] == '/' || base->fZPath == 0)) {
316 ReplaceStr(&base->fZPath, term->fZPath);
317 ReplaceStr(&base->fZQuery, term->fZQuery);
318 ReplaceStr(&base->fZFragment, term->fZFragment);
319 } else if (term->fZPath && base->fZPath) {
320 int i, j, zBufSz = strlen(base->fZPath) + strlen(term->fZPath) + 2;
321 char *zBuf = new char[zBufSz];
322 if (zBuf) {
323 strlcpy(zBuf, base->fZPath, zBufSz);
324 for (i = strlen(zBuf) - 1; i >= 0 && zBuf[i] != '/'; --i) {
325 zBuf[i] = 0;
326 }
327 strlcat(zBuf, term->fZPath, zBufSz);
328 for (i = 0; zBuf[i]; i++) {
329 if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == '/') {
330 // coverity[secure_coding]
331 strcpy(&zBuf[i+1], &zBuf[i+3]); // NOLINT
332 --i;
333 continue;
334 }
335 if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == 0) {
336 zBuf[i+1] = 0;
337 continue;
338 }
339 if (i > 0 && zBuf[i] == '/' && zBuf[i+1] == '.' &&
340 zBuf[i+2] == '.' && (zBuf[i+3] == '/' || zBuf[i+3] == 0)) {
341 for (j = i - 1; j >= 0 && zBuf[j] != '/'; --j) {}
342 if (zBuf[i+3]) {
343 // coverity[secure_coding]
344 strcpy(&zBuf[j+1], &zBuf[i+4]); // NOLINT
345 } else {
346 zBuf[j+1] = 0;
347 }
348 i = j - 1;
349 if (i < -1) i = -1;
350 continue;
351 }
352 }
353 delete[] base->fZPath;
354 base->fZPath = zBuf;
355 }
356 ReplaceStr(&base->fZQuery, term->fZQuery);
357 ReplaceStr(&base->fZFragment, term->fZFragment);
358 }
359 delete term;
360
361 result = base->BuildUri();
362 delete base;
363
364 return result;
365}
static char * StrNDup(const char *z, int n)
Duplicate a string of length n.
Definition: TGHtmlUri.cxx:234
static void ReplaceStr(char **pzDest, const char *zSrc)
Replace the string in *pzDest with the string in zSrc.
Definition: TGHtmlUri.cxx:250
#define URI_FRAGMENT_MASK
Definition: TGHtmlUri.h:43
#define URI_AUTH_MASK
Definition: TGHtmlUri.h:40
#define URI_SCHEME_MASK
Definition: TGHtmlUri.h:39
#define URI_PATH_MASK
Definition: TGHtmlUri.h:41
#define URI_QUERY_MASK
Definition: TGHtmlUri.h:42
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2515
char * fZAuthority
Definition: TGHtmlUri.h:72
int EqualsUri(const TGHtmlUri *uri, int field_mask=URI_FULL_MASK)
Compare another uri with given field mask.
Definition: TGHtmlUri.cxx:120
int ComponentLength(const char *z, const char *zInit, const char *zTerm)
Return the length of the next component of the URL in z[] given that the component starts at z[0].
Definition: TGHtmlUri.cxx:183
char * fZQuery
Definition: TGHtmlUri.h:74
virtual ~TGHtmlUri()
Html uri destructor.
Definition: TGHtmlUri.cxx:108
char * BuildUri()
Create a string to hold the given URI.
Definition: TGHtmlUri.cxx:204
char * fZFragment
Definition: TGHtmlUri.h:75
char * fZPath
Definition: TGHtmlUri.h:73
TGHtmlUri(const TGHtmlUri &)=delete
char * fZScheme
Definition: TGHtmlUri.h:71
const char * fZBase
Definition: TGHtml.h:1268
virtual char * ResolveUri(const char *uri)
This function resolves the specified URI and returns the result in a newly allocated string.
Definition: TGHtmlUri.cxx:284
char * fZBaseHref
Definition: TGHtml.h:1269
Basic string class.
Definition: TString.h:136
const char * Data() const
Definition: TString.h:369
TString & Append(const char *cs)
Definition: TString.h:564
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2336
const Int_t n
Definition: legend1.C:16