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

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

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

Webmaster

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