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 
44 static char *StrNDup(const char *z, int n);
45 static void ReplaceStr(char **pzDest, const char *zSrc);
46 #if 0 // not used
47 static char *Trim(char *z);
48 #endif
49 
50 
51 ////////////////////////////////////////////////////////////////////////////////
52 /// Parse a text URI into an HtmlUri structure.
53 
54 TGHtmlUri::TGHtmlUri(const char *zUri)
55 {
56  int n;
57 
58  fZScheme = fZAuthority = fZPath = fZQuery = fZFragment = nullptr;
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 {
94  fZScheme = fZAuthority = fZPath = fZQuery = fZFragment = nullptr;
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 
120 int 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 
183 int 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 
234 static 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 
250 static 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
261 static 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 
284 char *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 }
n
const Int_t n
Definition: legend1.C:16
URI_QUERY_MASK
#define URI_QUERY_MASK
Definition: TGHtmlUri.h:42
TGHtmlUri::fZFragment
char * fZFragment
Definition: TGHtmlUri.h:75
TGHtmlUri::fZQuery
char * fZQuery
Definition: TGHtmlUri.h:74
StrNDup
static char * StrNDup(const char *z, int n)
Duplicate a string of length n.
Definition: TGHtmlUri.cxx:234
TString::Data
const char * Data() const
Definition: TString.h:369
TGHtmlUri::~TGHtmlUri
virtual ~TGHtmlUri()
Html uri destructor.
Definition: TGHtmlUri.cxx:108
URI_SCHEME_MASK
#define URI_SCHEME_MASK
Definition: TGHtmlUri.h:39
URI_AUTH_MASK
#define URI_AUTH_MASK
Definition: TGHtmlUri.h:40
TString::Format
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:2333
TString
Basic string class.
Definition: TString.h:136
URI_FRAGMENT_MASK
#define URI_FRAGMENT_MASK
Definition: TGHtmlUri.h:43
URI_PATH_MASK
#define URI_PATH_MASK
Definition: TGHtmlUri.h:41
TGHtmlUri::fZAuthority
char * fZAuthority
Definition: TGHtmlUri.h:72
TGHtml::fZBaseHref
char * fZBaseHref
Definition: TGHtml.h:1269
TString::Append
TString & Append(const char *cs)
Definition: TString.h:564
TGHtml.h
TGHtmlUri
Definition: TGHtmlUri.h:55
TGHtmlUri::TGHtmlUri
TGHtmlUri(const TGHtmlUri &)=delete
StrDup
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2512
TGHtml::fZBase
const char * fZBase
Definition: TGHtml.h:1268
TGHtmlUri::EqualsUri
int EqualsUri(const TGHtmlUri *uri, int field_mask=URI_FULL_MASK)
Compare another uri with given field mask.
Definition: TGHtmlUri.cxx:120
TGHtmlUri::fZScheme
char * fZScheme
Definition: TGHtmlUri.h:71
TGHtmlUri::fZPath
char * fZPath
Definition: TGHtmlUri.h:73
TGHtmlUri.h
TGHtml::ResolveUri
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
TGHtmlUri::BuildUri
char * BuildUri()
Create a string to hold the given URI.
Definition: TGHtmlUri.cxx:204
TGHtmlUri::ComponentLength
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
ReplaceStr
static void ReplaceStr(char **pzDest, const char *zSrc)
Replace the string in *pzDest with the string in zSrc.
Definition: TGHtmlUri.cxx:250