TGHtmlUri.cxx

Go to the documentation of this file.
00001 // $Id$
00002 // Author:  Valeriy Onuchin   03/05/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2001, Rene Brun, Fons Rademakers and Reiner Rohlfs *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /**************************************************************************
00013 
00014     HTML widget for xclass. Based on tkhtml 1.28
00015     Copyright (C) 1997-2000 D. Richard Hipp <drh@acm.org>
00016     Copyright (C) 2002-2003 Hector Peraza.
00017 
00018     This library is free software; you can redistribute it and/or
00019     modify it under the terms of the GNU Library General Public
00020     License as published by the Free Software Foundation; either
00021     version 2 of the License, or (at your option) any later version.
00022 
00023     This library is distributed in the hope that it will be useful,
00024     but WITHOUT ANY WARRANTY; without even the implied warranty of
00025     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026     Library General Public License for more details.
00027 
00028     You should have received a copy of the GNU Library General Public
00029     License along with this library; if not, write to the Free
00030     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00031 
00032 **************************************************************************/
00033 
00034 // Routines for processing URLs.
00035 
00036 #include <ctype.h>
00037 #include <string.h>
00038 #include <stdlib.h>
00039 
00040 #include "TGHtml.h"
00041 #include "TGHtmlUri.h"
00042 
00043 
00044 static char *StrNDup(const char *z, int n);
00045 static void ReplaceStr(char **pzDest, const char *zSrc);
00046 #if 0  // not used
00047 static char *Trim(char *z);
00048 #endif
00049 
00050 
00051 //______________________________________________________________________________
00052 TGHtmlUri::TGHtmlUri(const char *zUri) 
00053 {
00054    // Parse a text URI into an HtmlUri structure.
00055    
00056    int n;
00057 
00058    fZScheme = fZAuthority = fZPath = fZQuery = fZFragment = (char *) 0;
00059 
00060    if (zUri && *zUri) {
00061       while (isspace(*zUri)) ++zUri;
00062       n = ComponentLength(zUri, "", ":/?# ");
00063       if (n > 0 && zUri[n] == ':') {
00064          fZScheme = StrNDup(zUri, n);
00065          zUri += n+1;
00066       }
00067       n = ComponentLength(zUri, "//", "/?# ");
00068       if (n > 0) {
00069          fZAuthority = StrNDup(&zUri[2], n-2);
00070          zUri += n;
00071       }
00072       n = ComponentLength(zUri, "", "?# ");
00073       if (n > 0) {
00074          fZPath = StrNDup(zUri, n);
00075          zUri += n;
00076       }
00077       n = ComponentLength(zUri, "?", "# ");
00078       if (n > 0) {
00079          fZQuery = StrNDup(&zUri[1], n-1);
00080          zUri += n;
00081       }
00082       n = ComponentLength(zUri, "#", " ");
00083       if (n > 0) {
00084          fZFragment = StrNDup(&zUri[1], n-1);
00085       }
00086    }
00087 }
00088 
00089 //______________________________________________________________________________
00090 TGHtmlUri::TGHtmlUri(const TGHtmlUri *uri)
00091 {
00092    // Html uri copy constructor.
00093 
00094    fZScheme = fZAuthority = fZPath = fZQuery = fZFragment = (char *) 0;
00095 
00096    if (uri) {
00097       if (uri->fZScheme)    fZScheme    = StrDup(uri->fZScheme);
00098       if (uri->fZAuthority) fZAuthority = StrDup(uri->fZAuthority);
00099       if (uri->fZPath)      fZPath      = StrDup(uri->fZPath);
00100       if (uri->fZQuery)     fZQuery     = StrDup(uri->fZQuery);
00101       if (uri->fZFragment)  fZFragment  = StrDup(uri->fZFragment);
00102    }
00103 }
00104 
00105 //______________________________________________________________________________
00106 TGHtmlUri::~TGHtmlUri()
00107 {
00108    // Html uri destructor.
00109 
00110    if (fZScheme) delete[] fZScheme;
00111    if (fZAuthority) delete[] fZAuthority;
00112    if (fZPath) delete[] fZPath;
00113    if (fZQuery) delete[] fZQuery;
00114    if (fZFragment) delete[] fZFragment;
00115 }
00116 
00117 //______________________________________________________________________________
00118 int TGHtmlUri::EqualsUri(const TGHtmlUri *uri, int field_mask)
00119 {
00120    // Compare another uri with given field mask.
00121 
00122    if (!uri) return 0;
00123 
00124    if (field_mask & URI_SCHEME_MASK) {
00125       if (uri->fZScheme && fZScheme) {
00126          if (strcmp(uri->fZScheme, fZScheme) != 0) return 0;
00127       } else if (uri->fZScheme != fZScheme) {  // one of them null?
00128          return 0;
00129       }
00130    }
00131 
00132    if (field_mask & URI_AUTH_MASK) {
00133       if (uri->fZAuthority && fZAuthority) {
00134          if (strcmp(uri->fZAuthority, fZAuthority) != 0) return 0;
00135       } else if (uri->fZAuthority != fZAuthority) {
00136          return 0;
00137       }
00138    }
00139 
00140    if (field_mask & URI_PATH_MASK) {
00141       if (uri->fZPath && fZPath) {
00142          if (strcmp(uri->fZPath, fZPath) != 0) return 0;
00143       } else if (uri->fZPath != fZPath) {
00144          return 0;
00145       }
00146    }
00147 
00148    if (field_mask & URI_QUERY_MASK) {
00149       if (uri->fZQuery && fZQuery) {
00150          if (strcmp(uri->fZQuery, fZQuery) != 0) return 0;
00151       } else if (uri->fZQuery != fZQuery) {
00152          return 0;
00153       }
00154    }
00155 
00156    if (field_mask & URI_FRAGMENT_MASK) {
00157       if (uri->fZFragment && fZFragment) {
00158          if (strcmp(uri->fZFragment, fZFragment) != 0) return 0;
00159       } else if (uri->fZFragment != fZFragment) {
00160          return 0;
00161       }
00162    }
00163 
00164    return 1;
00165 }
00166 
00167 //______________________________________________________________________________
00168 int TGHtmlUri::ComponentLength(const char *z, const char *zInit, const char *zTerm)
00169 {
00170    // Return the length of the next component of the URL in z[] given
00171    // that the component starts at z[0].  The initial sequence of the
00172    // component must be zInit[].  The component is terminated by any
00173    // character in zTerm[].  The length returned is 0 if the component
00174    // doesn't exist.  The length includes the zInit[] string, but not
00175    // the termination character.
00176    //
00177    //        Component        zInit      zTerm
00178    //        ----------       -------    -------
00179    //        scheme           ""         ":/?#"
00180    //        authority        "//"       "/?#"
00181    //        path             "/"        "?#"
00182    //        query            "?"        "#"
00183    //        fragment         "#"        ""
00184    int i, n;
00185 
00186    for (n = 0; zInit[n]; ++n) {
00187       if (zInit[n] != z[n]) return 0;
00188    }
00189    while (z[n]) {
00190       for (i = 0; zTerm[i]; ++i) {
00191          if (z[n] == zTerm[i]) return n;
00192       }
00193       ++n;
00194    }
00195 
00196    return n;
00197 }
00198 
00199 //______________________________________________________________________________
00200 char *TGHtmlUri::BuildUri()
00201 {
00202    // Create a string to hold the given URI. Memory to hold the string is
00203    // allocated with new[] and must be freed by the calling function.
00204   
00205    int n = 1;
00206    char *z;
00207 
00208    if (fZScheme)    n += strlen(fZScheme) + 1;
00209    if (fZAuthority) n += strlen(fZAuthority) + 3;
00210    if (fZPath)      n += strlen(fZPath) + 1;
00211    if (fZQuery)     n += strlen(fZQuery) + 1;
00212    if (fZFragment)  n += strlen(fZFragment) + 1;
00213    z = new char[n];
00214    if (z == 0) return 0;
00215    n = 0;
00216    if (fZScheme) {
00217       sprintf(z, "%s:", fZScheme);
00218       n = strlen(z);
00219    }
00220    if (fZAuthority) {
00221       sprintf(&z[n], "//%s", fZAuthority);
00222       n += strlen(&z[n]);
00223    }
00224    if (fZAuthority && fZAuthority[strlen(fZAuthority)-1] != '/' &&
00225       !(fZPath && fZPath[0] == '/')) {
00226       strcat(z, "/");
00227       ++n;
00228    }
00229    if (fZPath) {
00230       sprintf(&z[n], "%s", fZPath);
00231       n += strlen(&z[n]);
00232    }
00233    if (fZQuery) {
00234       sprintf(&z[n], "?%s", fZQuery);
00235       n += strlen(&z[n]);
00236    }
00237    if (fZFragment) {
00238       sprintf(&z[n], "#%s", fZFragment);
00239    } else {
00240       z[n] = 0;
00241    }
00242 
00243    return z;
00244 }
00245 
00246 
00247 //______________________________________________________________________________
00248 static char *StrNDup(const char *z, int n) 
00249 {
00250    // Duplicate a string of length n.
00251 
00252    char *zResult;
00253 
00254    if (n <= 0) n = strlen(z);
00255    zResult = new char[n + 1];
00256    if (zResult) {
00257       memcpy(zResult, z, n);
00258       zResult[n] = 0;
00259    }
00260    return zResult;
00261 }
00262 
00263 //______________________________________________________________________________
00264 static void ReplaceStr(char **pzDest, const char *zSrc)
00265 {
00266    // Replace the string in *pzDest with the string in zSrc
00267    
00268    if (*pzDest != 0) delete[] *pzDest;
00269    if (zSrc == 0) {
00270       *pzDest = 0;
00271    } else {
00272       *pzDest = StrNDup(zSrc, -1);
00273    }
00274 }
00275 
00276 #if 0  // not used
00277 static char *Trim(char *z) 
00278 {
00279    // Remove leading and trailing spaces from the given string. Return
00280    // a new string allocated with new[].
00281    int i;
00282    char *zNew;
00283 
00284    while (isspace(*z)) z++;
00285    i = strlen(z);
00286    zNew = new char[i + 1];
00287    if (zNew == 0) return 0;
00288    strcpy(zNew, z);
00289    while (i > 0 && isspace(zNew[i-1])) zNew[--i] = 0;
00290 
00291    return zNew;
00292 }
00293 #endif
00294 
00295 //______________________________________________________________________________
00296 char *TGHtml::ResolveUri(const char *zUri)
00297 {
00298    // This function resolves the specified URI and returns the result in
00299    // a newly allocated string. The resolver algorithm specified in section
00300    // 5.2 of RFC 2396 is used.
00301 
00302    char *result = 0;
00303    TGHtmlUri *base, *term;
00304 
00305    if (zUri == 0 || *zUri == 0) return 0;
00306 
00307    if (fZBaseHref && *fZBaseHref) {
00308       base = new TGHtmlUri(fZBaseHref);
00309    } else {
00310       base = new TGHtmlUri(fZBase);
00311    }
00312 
00313    term = new TGHtmlUri(zUri);
00314 
00315    if (term->fZScheme == 0 &&
00316        term->fZAuthority == 0 &&
00317        term->fZPath == 0 &&
00318        term->fZQuery == 0 &&
00319        term->fZFragment) {
00320       ReplaceStr(&base->fZFragment, term->fZFragment);
00321    } else if (term->fZScheme) {
00322       TGHtmlUri *temp;
00323       temp = term;
00324       term = base;
00325       base = temp;
00326    } else if (term->fZAuthority) {
00327       ReplaceStr(&base->fZAuthority, term->fZAuthority);
00328       ReplaceStr(&base->fZPath, term->fZPath);
00329       ReplaceStr(&base->fZQuery, term->fZQuery);
00330       ReplaceStr(&base->fZFragment, term->fZFragment);
00331    } else if (term->fZPath && (term->fZPath[0] == '/' || base->fZPath == 0)) {
00332       ReplaceStr(&base->fZPath, term->fZPath);
00333       ReplaceStr(&base->fZQuery, term->fZQuery);
00334       ReplaceStr(&base->fZFragment, term->fZFragment);
00335    } else if (term->fZPath && base->fZPath) {
00336       char *zBuf;
00337       int i, j;
00338       zBuf = new char[strlen(base->fZPath) + strlen(term->fZPath) + 2];
00339       if (zBuf) {
00340          sprintf(zBuf, "%s", base->fZPath);
00341          for (i = strlen(zBuf) - 1; i >= 0 && zBuf[i] != '/'; --i) {
00342             zBuf[i] = 0;
00343          }
00344          strcat(zBuf, term->fZPath);
00345          for (i = 0; zBuf[i]; i++) {
00346             if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == '/') {
00347                strcpy(&zBuf[i+1], &zBuf[i+3]);
00348                --i;
00349                continue;
00350             }
00351             if (zBuf[i] == '/' && zBuf[i+1] == '.' && zBuf[i+2] == 0) {
00352                zBuf[i+1] = 0;
00353                continue;
00354             }
00355             if (i > 0 && zBuf[i] == '/' && zBuf[i+1] == '.' && 
00356                 zBuf[i+2] == '.' && (zBuf[i+3] == '/' || zBuf[i+3] == 0)) {
00357                for (j = i - 1; j >= 0 && zBuf[j] != '/'; --j) {}
00358                if (zBuf[i+3]) {
00359                   strcpy(&zBuf[j+1], &zBuf[i+4]);
00360                } else {
00361                   zBuf[j+1] = 0;
00362                }
00363                i = j - 1;
00364                if (i < -1) i = -1;
00365                continue;
00366             }
00367          }
00368          delete[] base->fZPath;
00369          base->fZPath = zBuf;
00370       }
00371       ReplaceStr(&base->fZQuery, term->fZQuery);
00372       ReplaceStr(&base->fZFragment, term->fZFragment);
00373    }
00374    delete term;
00375   
00376    result = base->BuildUri();
00377    delete base;
00378 
00379    return result;
00380 }

Generated on Tue Jul 5 14:22:19 2011 for ROOT_528-00b_version by  doxygen 1.5.1