Logo ROOT   master
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 <string.h>
38 #include <stdlib.h>
39 
40 #include "TGHtml.h"
41 #include "TGHtmlUri.h"
42 
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 = (char *) 0;
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 = (char *) 0;
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  int n = 1;
207  char *z;
208 
209  if (fZScheme) n += strlen(fZScheme) + 1;
210  if (fZAuthority) n += strlen(fZAuthority) + 3;
211  if (fZPath) n += strlen(fZPath) + 1;
212  if (fZQuery) n += strlen(fZQuery) + 1;
213  if (fZFragment) n += strlen(fZFragment) + 1;
214  z = new char[n];
215  if (z == 0) return 0;
216  n = 0;
217  if (fZScheme) {
218  // coverity[secure_coding]
219  sprintf(z, "%s:", fZScheme);
220  n = strlen(z);
221  }
222  if (fZAuthority) {
223  // coverity[secure_coding]
224  sprintf(&z[n], "//%s", fZAuthority);
225  n += strlen(&z[n]);
226  }
227  if (fZAuthority && fZAuthority[strlen(fZAuthority)-1] != '/' &&
228  !(fZPath && fZPath[0] == '/')) {
229  // coverity[secure_coding]
230  strcat(z, "/");
231  ++n;
232  }
233  if (fZPath) {
234  // coverity[secure_coding]
235  sprintf(&z[n], "%s", fZPath);
236  n += strlen(&z[n]);
237  }
238  if (fZQuery) {
239  // coverity[secure_coding]
240  sprintf(&z[n], "?%s", fZQuery);
241  n += strlen(&z[n]);
242  }
243  if (fZFragment) {
244  // coverity[secure_coding]
245  sprintf(&z[n], "#%s", fZFragment);
246  } else {
247  z[n] = 0;
248  }
249 
250  return z;
251 }
252 
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 /// Duplicate a string of length n.
256 
257 static char *StrNDup(const char *z, int n)
258 {
259  char *zResult;
260 
261  if (n <= 0) n = strlen(z);
262  zResult = new char[n + 1];
263  if (zResult) {
264  memcpy(zResult, z, n);
265  zResult[n] = 0;
266  }
267  return zResult;
268 }
269 
270 ////////////////////////////////////////////////////////////////////////////////
271 /// Replace the string in *pzDest with the string in zSrc
272 
273 static void ReplaceStr(char **pzDest, const char *zSrc)
274 {
275  if (*pzDest != 0) delete[] *pzDest;
276  if (zSrc == 0) {
277  *pzDest = 0;
278  } else {
279  *pzDest = StrNDup(zSrc, -1);
280  }
281 }
282 
283 #if 0 // not used
284 static char *Trim(char *z)
285 {
286  // Remove leading and trailing spaces from the given string. Return
287  // a new string allocated with new[].
288  int i;
289  char *zNew;
290 
291  while (isspace(*z)) z++;
292  i = strlen(z);
293  zNew = new char[i + 1];
294  if (zNew == 0) return 0;
295  strcpy(zNew, z);
296  while (i > 0 && isspace(zNew[i-1])) zNew[--i] = 0;
297 
298  return zNew;
299 }
300 #endif
301 
302 ////////////////////////////////////////////////////////////////////////////////
303 /// This function resolves the specified URI and returns the result in
304 /// a newly allocated string. The resolver algorithm specified in section
305 /// 5.2 of RFC 2396 is used.
306 
307 char *TGHtml::ResolveUri(const char *zUri)
308 {
309  char *result = 0;
310  TGHtmlUri *base, *term;
311 
312  if (zUri == 0 || *zUri == 0) return 0;
313 
314  if (fZBaseHref && *fZBaseHref) {
315  base = new TGHtmlUri(fZBaseHref);
316  } else {
317  base = new TGHtmlUri(fZBase);
318  }
319 
320  term = new TGHtmlUri(zUri);
321 
322  if (term->fZScheme == 0 &&
323  term->fZAuthority == 0 &&
324  term->fZPath == 0 &&
325  term->fZQuery == 0 &&
326  term->fZFragment) {
327  ReplaceStr(&base->fZFragment, term->fZFragment);
328  } else if (term->fZScheme) {
329  TGHtmlUri *temp;
330  temp = term;
331  term = base;
332  base = temp;
333  } else if (term->fZAuthority) {
334  ReplaceStr(&base->fZAuthority, term->fZAuthority);
335  ReplaceStr(&base->fZPath, term->fZPath);
336  ReplaceStr(&base->fZQuery, term->fZQuery);
337  ReplaceStr(&base->fZFragment, term->fZFragment);
338  } else if (term->fZPath && (term->fZPath[0] == '/' || base->fZPath == 0)) {
339  ReplaceStr(&base->fZPath, term->fZPath);
340  ReplaceStr(&base->fZQuery, term->fZQuery);
341  ReplaceStr(&base->fZFragment, term->fZFragment);
342  } else if (term->fZPath && base->fZPath) {
343  char *zBuf;
344  int i, j;
345  zBuf = new char[strlen(base->fZPath) + strlen(term->fZPath) + 2];
346  if (zBuf) {
347  // coverity[secure_coding]
348  sprintf(zBuf, "%s", base->fZPath);
349  for (i = strlen(zBuf) - 1; i >= 0 && zBuf[i] != '/'; --i) {
350  zBuf[i] = 0;
351  }
352  // coverity[secure_coding]
353  strcat(zBuf, term->fZPath);
354  for (i = 0; zBuf[i]; i++) {
355  if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == '/') {
356  // coverity[secure_coding]
357  strcpy(&zBuf[i+1], &zBuf[i+3]);
358  --i;
359  continue;
360  }
361  if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == 0) {
362  zBuf[i+1] = 0;
363  continue;
364  }
365  if (i > 0 && zBuf[i] == '/' && zBuf[i+1] == '.' &&
366  zBuf[i+2] == '.' && (zBuf[i+3] == '/' || zBuf[i+3] == 0)) {
367  for (j = i - 1; j >= 0 && zBuf[j] != '/'; --j) {}
368  if (zBuf[i+3]) {
369  // coverity[secure_coding]
370  strcpy(&zBuf[j+1], &zBuf[i+4]);
371  } else {
372  zBuf[j+1] = 0;
373  }
374  i = j - 1;
375  if (i < -1) i = -1;
376  continue;
377  }
378  }
379  delete[] base->fZPath;
380  base->fZPath = zBuf;
381  }
382  ReplaceStr(&base->fZQuery, term->fZQuery);
383  ReplaceStr(&base->fZFragment, term->fZFragment);
384  }
385  delete term;
386 
387  result = base->BuildUri();
388  delete base;
389 
390  return result;
391 }
const char * fZBase
Definition: TGHtml.h:1259
static void ReplaceStr(char **pzDest, const char *zSrc)
Replace the string in *pzDest with the string in zSrc.
Definition: TGHtmlUri.cxx:273
int EqualsUri(const TGHtmlUri *uri, int field_mask=URI_FULL_MASK)
Compare another uri with given field mask.
Definition: TGHtmlUri.cxx:120
char * fZPath
Definition: TGHtmlUri.h:73
static char * StrNDup(const char *z, int n)
Duplicate a string of length n.
Definition: TGHtmlUri.cxx:257
char * fZQuery
Definition: TGHtmlUri.h:74
#define URI_QUERY_MASK
Definition: TGHtmlUri.h:42
char * fZFragment
Definition: TGHtmlUri.h:75
char * fZScheme
Definition: TGHtmlUri.h:71
virtual char * ResolveUri(const char *uri)
This function resolves the specified URI and returns the result in a newly allocated string...
Definition: TGHtmlUri.cxx:307
char * fZBaseHref
Definition: TGHtml.h:1260
#define URI_SCHEME_MASK
Definition: TGHtmlUri.h:39
#define URI_PATH_MASK
Definition: TGHtmlUri.h:41
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2490
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 * fZAuthority
Definition: TGHtmlUri.h:72
you should not use this method at all Int_t Int_t z
Definition: TRolke.cxx:630
#define URI_FRAGMENT_MASK
Definition: TGHtmlUri.h:43
char * BuildUri()
Create a string to hold the given URI.
Definition: TGHtmlUri.cxx:204
#define URI_AUTH_MASK
Definition: TGHtmlUri.h:40
virtual ~TGHtmlUri()
Html uri destructor.
Definition: TGHtmlUri.cxx:108
const Int_t n
Definition: legend1.C:16
TGHtmlUri(const TGHtmlUri &)