00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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
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) {
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
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
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
00203
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
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
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
00280
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
00299
00300
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 }