[BACK] Return to HTMulti.c CVS log [TXT] [DIR] Up to [Public] / libwww / Library / src

Annotation of libwww/Library/src/HTMulti.c, revision 2.26

2.11 frystyk 1: /*                                  HTMulti.c
 2: **   MULTIFORMAT HANDLING
 3: **
2.15 frystyk 4: **   (c) COPYRIGHT MIT 1995.
2.11 frystyk 5: **   Please first read the full copyright statement in the file COPYRIGH.
2.1 luotonen 6: **
 7: ** History:
 8: **   March 94 AL  Separated from HTFile.c because
 9: **           multiformat handling would be a mess in VMS.
 10: */
 11: 
2.13 frystyk 12: /* Library include files */
2.26 ! frystyk 13: #include "sysdep.h"
2.13 frystyk 14: #include "HTUtils.h"
 15: #include "HTString.h"
2.2 duns 16: #include "HTMulti.h"
2.20 frystyk 17: #include "HTFile.h"
2.14 frystyk 18: #include "HTBind.h"
2.1 luotonen 19: #include "HTList.h"
2.19 frystyk 20: #include "HTReqMan.h"
2.1 luotonen 21: 
2.3 luotonen 22: PRIVATE HTList * welcome_names = NULL; /* Welcome.html, index.html etc. */
 23: 
 24: 
2.14 frystyk 25: /* PUBLIC                       HTSplitFilename()
 26: **
 27: **   Split the filename to an array of suffixes.
 28: **   Return the number of parts placed to the array.
 29: **   Array should have MAX_SUFF+1 items.
 30: */
2.23 frystyk 31: PRIVATE int HTSplitFilename (char * s_str, char ** s_arr)
2.14 frystyk 32: {
2.26 ! frystyk 33:   const char *delimiters = HTBind_delimiters();
2.14 frystyk 34:   char * start = s_str;
 35:   char * end;
 36:   char save;
 37:   int i;
 38: 
 39:   if (!s_str || !s_arr) return 0;
 40: 
 41:   for (i=0; i < MAX_SUFF && *start; i++) {
 42:    for(end=start+1; *end && !strchr(delimiters, *end); end++);
 43:    save = *end;
 44:    *end = 0;
 45:    StrAllocCopy(s_arr[i], start); /* Frees the previous value */
 46:    *end = save;
 47:    start = end;
 48:   }
2.24 frystyk 49:   HT_FREE(s_arr[i]);    /* Terminating NULL */
2.14 frystyk 50:   return i;
 51: }
 52: 
 53: 
2.3 luotonen 54: /*
 55: **   Set default file name for welcome page on each directory.
 56: */
2.23 frystyk 57: PUBLIC void HTAddWelcome (char * name)
2.3 luotonen 58: {
 59:   if (name) {
 60:    char * mycopy = NULL;
 61:    StrAllocCopy(mycopy,name);
 62: 
 63:    if (!welcome_names)
 64:      welcome_names = HTList_new();
 65:    HTList_addObject(welcome_names, (void*)mycopy);
 66:   }
 67: }
 68: 
 69: 
2.26 ! frystyk 70: #ifdef HAVE_READDIR
2.1 luotonen 71: 
 72: /* PRIVATE                       multi_match()
 73: **
 74: **   Check if actual filename (split in parts) fulfills
 75: **   the requirements.
 76: */
2.23 frystyk 77: PRIVATE BOOL multi_match (char ** required, int m, char ** actual, int n)
2.1 luotonen 78: {
 79:   int c;
 80:   int i,j;
 81: 
2.2 duns 82: #ifdef VMS
 83:   for(c=0; c<m && c<n && !strcasecomp(required[c], actual[c]); c++);
 84: #else /* not VMS */
2.1 luotonen 85:   for(c=0; c<m && c<n && !strcmp(required[c], actual[c]); c++);
2.2 duns 86: #endif /* not VMS */
2.1 luotonen 87: 
 88:   if (!c) return NO;     /* Names differ rigth from start */
 89: 
 90:   for(i=c; i<m; i++) {
 91:    BOOL found = NO;
 92:    for(j=c; j<n; j++) {
2.2 duns 93: #ifdef VMS
 94:      if (!strcasecomp(required[i], actual[j])) {
 95: #else /* not VMS */
2.1 luotonen 96:      if (!strcmp(required[i], actual[j])) {
2.2 duns 97: #endif /* not VMS */
2.1 luotonen 98:        found = YES;
 99:        break;
 100:      }
 101:    }
 102:    if (!found) return NO;
 103:   }
 104:   return YES;
 105: }
 106: 
 107: 
 108: /*
 109: **   Get multi-match possibilities for a given file
 110: **   ----------------------------------------------
 111: ** On entry:
 112: **   path  absolute path to one file in a directory,
 113: **       may end in .multi.
 114: ** On exit:
 115: **   returns a list of ContentDesription structures
 116: **       describing the mathing files.
 117: **
 118: */
2.23 frystyk 119: PRIVATE HTList * dir_matches (char * path)
2.1 luotonen 120: {
 121:   static char * required[MAX_SUFF+1];
 122:   static char * actual[MAX_SUFF+1];
 123:   int m,n;
 124:   char * dirname = NULL;
 125:   char * basename = NULL;
 126:   int baselen;
 127:   char * multi = NULL;
 128:   DIR * dp;
2.26 ! frystyk 129:   struct dirent * dirbuf;
2.1 luotonen 130:   HTList * matches = NULL;
2.16 frystyk 131: #ifdef HT_REENTRANT
2.26 ! frystyk 132:   DIR result;                  /* For readdir_r */
2.16 frystyk 133: #endif
2.1 luotonen 134: 
 135:   if (!path) return NULL;
 136: 
 137:   StrAllocCopy(dirname, path);
 138:   basename = (strrchr(dirname, '/'));
 139:   if (!basename)
 140:    goto dir_match_failed;
 141:   *basename++ = 0;
 142: 
 143:   multi = strrchr(basename, MULTI_SUFFIX[0]);
2.2 duns 144:   if (multi && !strcasecomp(multi, MULTI_SUFFIX))
2.1 luotonen 145:    *multi = 0;
 146:   baselen = strlen(basename);
 147: 
 148:   m = HTSplitFilename(basename, required);
 149: 
 150:   dp = opendir(dirname);
 151:   if (!dp) {
2.13 frystyk 152:    if (PROT_TRACE)
2.25 eric 153:      HTTrace("Warning..... Can't open directory %s\n", dirname);
2.1 luotonen 154:    goto dir_match_failed;
 155:   }
 156: 
 157:   matches = HTList_new();
2.16 frystyk 158: #ifdef HT_REENTRANT
2.26 ! frystyk 159:    while ((dirbuf = (DIR *) readdir_r(dp, &result))) {
2.16 frystyk 160: #else
 161:    while ((dirbuf = readdir(dp))) {
 162: #endif /* HT_REENTRANT */
2.1 luotonen 163:    if (!dirbuf->d_ino) continue;  /* Not in use */
2.3 luotonen 164:    if (!strcmp(dirbuf->d_name,".") ||
 165:      !strcmp(dirbuf->d_name,"..") ||
2.20 frystyk 166:      !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
2.3 luotonen 167:      continue;
2.7 frystyk 168: 
2.13 frystyk 169:    /* Use of direct->namlen is only valid in BSD'ish system */
 170:    /* Thanks to chip@chinacat.unicom.com (Chip Rosenthal) */
 171:    /* if ((int)(dirbuf->d_namlen) >= baselen) { */
 172:    if ((int) strlen(dirbuf->d_name) >= baselen) {
2.1 luotonen 173:      n = HTSplitFilename(dirbuf->d_name, actual);
 174:      if (multi_match(required, m, actual, n)) {
 175:        HTContentDescription * cd;
2.14 frystyk 176:        cd = HTBind_getDescription(dirbuf->d_name);
2.1 luotonen 177:        if (cd) {
 178:          if (cd->content_type) {
2.24 frystyk 179:            if ((cd->filename = (char *) HT_MALLOC(strlen(dirname) + 2 + strlen(dirbuf->d_name))) == NULL)
 180:              HT_OUTOFMEM("dir_matches");
2.1 luotonen 181:            sprintf(cd->filename, "%s/%s",
 182:                dirname, dirbuf->d_name);
 183:            HTList_addObject(matches, (void*)cd);
 184:          }
2.24 frystyk 185:          else HT_FREE(cd);
2.1 luotonen 186:        }
 187:      }
 188:    }
 189:   }
 190:   closedir(dp);
 191: 
 192:  dir_match_failed:
2.24 frystyk 193:   HT_FREE(dirname);
2.1 luotonen 194:   return matches;
 195: }
 196: 
 197: 
 198: /*
 199: **   Get the best match for a given file
 200: **   -----------------------------------
 201: ** On entry:
 202: **   req->conversions accepted content-types
 203: **   req->encodings  accepted content-transfer-encodings
 204: **   req->languages  accepted content-languages
 205: **   path       absolute pathname of the filename for
 206: **            which the match is desired.
 207: ** On exit:
 208: **   returns a newly allocated absolute filepath.
 209: */
2.23 frystyk 210: PRIVATE char * HTGetBest (HTRequest * req, char * path)
2.1 luotonen 211: {
 212:   HTList * matches;
 213:   HTList * cur;
 214:   HTContentDescription * cd;
 215:   HTContentDescription * best = NULL;
 216:   char * best_path = NULL;
 217: 
2.13 frystyk 218:   if (!path || !*path) return NULL;
2.1 luotonen 219: 
 220:   matches = dir_matches(path);
 221:   if (!matches) {
2.13 frystyk 222:    if (PROT_TRACE)
2.25 eric 223:      HTTrace("No matches.. for \"%s\"\n", path);
2.13 frystyk 224:    return NULL;
2.1 luotonen 225:   }
 226: 
 227:   /* BEGIN DEBUG */
 228:   cur = matches;
2.13 frystyk 229:   if (PROT_TRACE)
2.25 eric 230:    HTTrace("Multi....... Possibilities for \"%s\"\n", path);
2.13 frystyk 231:   if (PROT_TRACE)
2.25 eric 232:    HTTrace("\nCONTENT-TYPE LANGUAGE ENCODING QUALITY FILE\n");
2.1 luotonen 233:   while ((cd = (HTContentDescription*)HTList_nextObject(cur))) {
2.13 frystyk 234:    if (PROT_TRACE)
2.25 eric 235:      HTTrace("%s\t%s\t%s\t %.5f %s\n",
2.13 frystyk 236:          cd->content_type  ?HTAtom_name(cd->content_type) :"-\t",
 237:          cd->content_language?HTAtom_name(cd->content_language):"-",
 238:          cd->content_encoding?HTAtom_name(cd->content_encoding):"-",
 239:          cd->quality,
 240:          cd->filename    ?cd->filename           :"-");
2.1 luotonen 241:   }
2.25 eric 242:   if (PROT_TRACE) HTTrace("\n");
2.1 luotonen 243:   /* END DEBUG */
 244: 
 245:   /*
 246:   ** Finally get best that is readable
 247:   */
 248:   if (HTRank(matches, req->conversions, req->languages, req->encodings)) {
 249:    cur = matches;
 250:    while ((best = (HTContentDescription*)HTList_nextObject(cur))) {
 251:      if (best && best->filename) {
 252:        if (access(best->filename, R_OK) != -1) {
 253:          StrAllocCopy(best_path, best->filename);
 254:          break;
2.13 frystyk 255:        } else if (PROT_TRACE)
2.25 eric 256:          HTTrace("Bad News.... \"%s\" is not readable\n",
2.1 luotonen 257:              best->filename);
 258:      }
 259:    }
 260:   } /* Select best */
 261: 
 262:   cur = matches;
 263:   while ((cd = (HTContentDescription*)HTList_nextObject(cur))) {
2.24 frystyk 264:    if (cd->filename) HT_FREE(cd->filename);
 265:    HT_FREE(cd);
2.1 luotonen 266:   }
 267:   HTList_delete(matches);
 268: 
 269:   return best_path;
 270: }
 271: 
2.3 luotonen 272: 
 273: 
2.23 frystyk 274: PRIVATE int welcome_value (char * name)
2.3 luotonen 275: {
 276:   HTList * cur = welcome_names;
 277:   char * welcome;
 278:   int v = 0;
 279: 
 280:   while ((welcome = (char*)HTList_nextObject(cur))) {
 281:    v++;
 282:    if (!strcmp(welcome,name)) return v;
 283:   }
 284:   return 0;
 285: }
 286: 
 287: 
 288: 
2.23 frystyk 289: PRIVATE char * get_best_welcome (char * path)
2.3 luotonen 290: {
 291:   char * best_welcome = NULL;
 292:   int best_value = 0;
 293:   DIR * dp;
2.26 ! frystyk 294:   struct dirent * dirbuf;
2.3 luotonen 295:   char * last = strrchr(path, '/');
 296: 
 297:   if (!welcome_names) {
 298:    HTAddWelcome("Welcome.html");
 299:    HTAddWelcome("welcome.html");
2.5 luotonen 300: #if 0
2.3 luotonen 301:    HTAddWelcome("Index.html");
2.5 luotonen 302: #endif
2.3 luotonen 303:    HTAddWelcome("index.html");
 304:   }
 305: 
2.5 luotonen 306:   if (last && last!=path) *last = 0;
2.3 luotonen 307:   dp = opendir(path);
2.5 luotonen 308:   if (last && last!=path) *last='/';
2.3 luotonen 309:   if (!dp) {
2.13 frystyk 310:    if (PROT_TRACE)
2.25 eric 311:      HTTrace("Warning..... Can't open directory %s\n",path);
2.3 luotonen 312:    return NULL;
 313:   }
 314:   while ((dirbuf = readdir(dp))) {
2.13 frystyk 315:    if (!dirbuf->d_ino ||
2.3 luotonen 316:      !strcmp(dirbuf->d_name,".") ||
 317:      !strcmp(dirbuf->d_name,"..") ||
2.20 frystyk 318:      !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
2.3 luotonen 319:      continue;
 320:    else {
 321:      int v = welcome_value(dirbuf->d_name);
 322:      if (v > best_value) {
 323:        best_value = v;
 324:        StrAllocCopy(best_welcome, dirbuf->d_name);
 325:      }
 326:    }
 327:   }
 328:   closedir(dp);
 329: 
 330:   if (best_welcome) {
2.24 frystyk 331:    char * welcome;
 332:    if ((welcome = (char *) HT_MALLOC(strlen(path) + strlen(best_welcome)+2)) == NULL)
 333:      HT_OUTOFMEM("get_best_welcome");
2.4 luotonen 334:    sprintf(welcome, "%s%s%s", path, last ? "" : "/", best_welcome);
2.24 frystyk 335:    HT_FREE(best_welcome);
2.13 frystyk 336:    if (PROT_TRACE)
2.25 eric 337:      HTTrace("Welcome..... \"%s\"\n",welcome);
2.3 luotonen 338:    return welcome;
 339:   }
 340:   return NULL;
 341: }
 342: 
2.26 ! frystyk 343: #endif /* HAVE_READDIR */
2.1 luotonen 344: 
 345: 
 346: /*
 347: **   Do multiformat handling
 348: **   -----------------------
 349: ** On entry:
 350: **   req->conversions accepted content-types
 351: **   req->encodings  accepted content-transfer-encodings
 352: **   req->languages  accepted content-languages
 353: **   path       absolute pathname of the filename for
 354: **            which the match is desired.
 355: **   stat_info     pointer to result space.
 356: **
 357: ** On exit:
 358: **   returns a newly allocated absolute filepath of the best
 359: **       match, or NULL if no match.
 360: **   stat_info     will contain inode information as
 361: **            returned by stat().
 362: */
2.23 frystyk 363: PUBLIC char * HTMulti (HTRequest *   req,
 364:            char *      path,
 365:            struct stat *  stat_info)
2.1 luotonen 366: {
 367:   char * new_path = NULL;
 368:   int stat_status = -1;
 369: 
2.3 luotonen 370:   if (!req || !path || !*path || !stat_info)
2.1 luotonen 371:    return NULL;
 372: 
2.26 ! frystyk 373: #ifdef HAVE_READDIR
2.19 frystyk 374:   if (*(path+strlen(path)-1) == '/') {    /* Find welcome page */
2.3 luotonen 375:    new_path = get_best_welcome(path);
 376:    if (new_path) path = new_path;
2.1 luotonen 377:   }
2.3 luotonen 378:   else{
 379:    char * multi = strrchr(path, MULTI_SUFFIX[0]);
 380:    if (multi && !strcasecomp(multi, MULTI_SUFFIX)) {
2.13 frystyk 381:      if (PROT_TRACE)
2.25 eric 382:        HTTrace("Multi....... by %s suffix\n", MULTI_SUFFIX);
2.1 luotonen 383:      if (!(new_path = HTGetBest(req, path))) {
2.13 frystyk 384:        if (PROT_TRACE)
2.25 eric 385:          HTTrace("Multi....... failed -- giving up\n");
2.1 luotonen 386:        return NULL;
 387:      }
 388:      path = new_path;
2.3 luotonen 389:    }
 390:    else {
2.18 frystyk 391:      stat_status = HT_STAT(path, stat_info);
2.3 luotonen 392:      if (stat_status == -1) {
2.13 frystyk 393:        if (PROT_TRACE)
2.25 eric 394:          HTTrace(
2.13 frystyk 395:              "AutoMulti... can't stat \"%s\"(errno %d)\n",
 396:              path, errno);
2.3 luotonen 397:        if (!(new_path = HTGetBest(req, path))) {
2.13 frystyk 398:          if (PROT_TRACE)
2.25 eric 399:            HTTrace("AutoMulti... failed -- giving up\n");
2.3 luotonen 400:          return NULL;
 401:        }
 402:        path = new_path;
 403:      }
2.1 luotonen 404:    }
 405:   }
2.26 ! frystyk 406: #endif /* HAVE_READDIR */
2.1 luotonen 407: 
 408:   if (stat_status == -1)
2.18 frystyk 409:    stat_status = HT_STAT(path, stat_info);
2.1 luotonen 410:   if (stat_status == -1) {
2.13 frystyk 411:    if (PROT_TRACE)
2.25 eric 412:      HTTrace("Stat fails.. on \"%s\" -- giving up (errno %d)\n",
2.13 frystyk 413:          path, errno);
2.1 luotonen 414:    return NULL;
 415:   }
 416:   else {
 417:    if (!new_path) {
 418:      StrAllocCopy(new_path, path);
 419:      return new_path;
 420:    }
 421:    else return path;
 422:   }
 423: }
 424: 
 425: 

Webmaster

AltStyle によって変換されたページ (->オリジナル) /