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

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

2.29 frystyk 1: /*
 2: **   CONTENT NEGOTIATION
2.11 frystyk 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.37 ! kahan 6: **   @(#) $Id: HTMulti.c,v 2.36 2000年01月06日 10:48:50 kahan Exp $
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.32 frystyk 14: #include "wwwsys.h"
2.28 frystyk 15: #include "WWWUtil.h"
 16: #include "WWWCore.h"
2.2 duns 17: #include "HTMulti.h"
2.34 frystyk 18: #include "HTBind.h"
2.20 frystyk 19: #include "HTFile.h"
2.1 luotonen 20: 
2.29 frystyk 21: #define MULTI_SUFFIX  ".multi"/* Extension for scanning formats */
 22: #define MAX_SUFF    15   /* Maximum number of suffixes for a file */
 23: #define VARIANTS    4    /* We start with this array size */
 24: 
 25: typedef struct _HTContentDescription {
 26:   char *   filename;
 27:   HTFormat  content_type;
 28:   HTLanguage content_language;
 29:   HTEncoding content_encoding;
 30:   HTEncoding content_transfer;
 31:   int        content_length;
 32:   double   quality;
 33: } HTContentDescription;
 34: 
2.3 luotonen 35: PRIVATE HTList * welcome_names = NULL; /* Welcome.html, index.html etc. */
 36: 
2.29 frystyk 37: /* ------------------------------------------------------------------------- */
 38: 
 39: /*
 40: ** Sort the q values in descending order
 41: */
 42: PRIVATE int VariantSort (const void * a, const void * b)
 43: {
 44:   HTContentDescription * aa = *(HTContentDescription **) a;
 45:   HTContentDescription * bb = *(HTContentDescription **) b;
2.33 frystyk 46:   if (aa && bb) return (aa->quality > bb->quality) ? -1 : 1;
 47:   return bb - aa;
2.29 frystyk 48: }
 49: 
 50: /*
 51: * Added by takada@seraph.ntt.jp (94/04/08)
 52: */
 53: PRIVATE BOOL lang_match (HTAtom * tmplate, HTAtom * actual)
 54: {
 55:   const char *t, *a;
 56:   char *st, *sa;
 57:   BOOL match = NO;
 58: 
 59:   if (tmplate && actual &&
 60:    (t = HTAtom_name(tmplate)) && (a = HTAtom_name(actual))) {
 61:    st = strchr(t, '_');
 62:    sa = strchr(a, '_');
 63:    if ((st != NULL) && (sa != NULL)) {
 64:      if (!strcasecomp(t, a))
 65:       match = YES;
 66:      else
 67:       match = NO;
 68:    }
 69:    else {
 70:      if (st != NULL) *st = 0;
 71:      if (sa != NULL) *sa = 0;
 72:      if (!strcasecomp(t, a))
 73:       match = YES;
 74:      else
 75:       match = NO;
 76:      if (st != NULL) *st = '_';
 77:      if (sa != NULL) *sa = '_';
 78:    }
 79:   }
 80:   return match;
 81: }
 82: 
 83: PRIVATE double type_value (HTAtom * content_type, HTList * accepted)
 84: {
 85:   if (!content_type) return (1.0);
 86:   if (accepted) {
 87:    HTList * cur = accepted;
 88:    HTPresentation * pres;
 89:    HTPresentation * wild = NULL;
 90:    while ((pres = (HTPresentation *) HTList_nextObject(cur))) {
 91:      if (pres->rep == content_type)
 92:        return pres->quality;
2.30 frystyk 93:      else if (HTMIMEMatch(pres->rep, content_type))
2.29 frystyk 94:        wild = pres;
 95:    }
 96:    if (wild) return wild->quality;
 97:    else return (0.0);                /* Nothing matched */
 98:   }
 99:   return (1.0);                  /* We accept all types */
 100: }
 101: 
 102: PRIVATE double lang_value (HTAtom * language, HTList * accepted)
 103: {
 104:   if (!language) return (1.0);
 105:   if (accepted) {
 106:    HTList * cur = accepted;
 107:    HTAcceptNode * node;
 108:    HTAcceptNode * wild = NULL;
 109:    while ((node = (HTAcceptNode *) HTList_nextObject(cur))) {
 110:      if (node->atom == language)
 111:        return node->quality;
 112:      /*
 113:       * patch by takada@seraph.ntt.jp (94/04/08)
 114:       * the original line was
2.30 frystyk 115:       * else if (HTMIMEMatch(node->atom, language)) {
2.29 frystyk 116:       * and the new line is
 117:       */
 118:      else if (lang_match(node->atom, language))
 119:        wild = node;
 120:    }
 121:    if (wild) return wild->quality;
 122:    else return (0.0);                /* Nothing matched */
 123:   }
 124:   return (1.0);                /* We accept all languages */
 125: }
 126: 
 127: PRIVATE double encoding_value (HTAtom * encoding, HTList * accepted)
 128: {
 129:   if (!encoding) return (1.0);
 130:   if (accepted) {
 131:    HTList * cur = accepted;
 132:    HTAcceptNode * node;
 133:    HTAcceptNode * wild = NULL;
 134:    const char * e = HTAtom_name(encoding);
 135:    if (!strcmp(e, "7bit") || !strcmp(e, "8bit") || !strcmp(e, "binary"))
 136:      return (1.0);
 137:    while ((node = (HTAcceptNode*)HTList_nextObject(cur))) {
 138:      if (node->atom == encoding)
 139:        return node->quality;
2.30 frystyk 140:      else if (HTMIMEMatch(node->atom, encoding))
2.29 frystyk 141:        wild = node;
 142:    }
 143:    if (wild) return wild->quality;
 144:    else return (0.0);                /* Nothing matched */
 145:   }
 146:   return (1.0);                /* We accept all encodings */
 147: }
 148: 
 149: PRIVATE BOOL HTRank (HTRequest * request, HTArray * variants)
 150: {
 151:   HTContentDescription * cd;
 152:   void ** data;
 153:   if (!variants) {
2.35 frystyk 154:    HTTRACE(PROT_TRACE, "Ranking..... No variants\n");
2.29 frystyk 155:    return NO;
 156:   }
 157:   /* 
 158:   ** Walk through the list of local and global preferences and find the
 159:   ** overall q factor for each variant
 160:   */
 161:   cd = (HTContentDescription *) HTArray_firstObject(variants, data);
 162:   while (cd) {
 163:    double ctq_local = type_value(cd->content_type, HTRequest_conversion(request));
 164:    double ctq_global = type_value(cd->content_type, HTFormat_conversion());
 165:    double clq_local = lang_value(cd->content_language, HTRequest_language(request));
 166:    double clq_global = lang_value(cd->content_language, HTFormat_language());
 167:    double ceq_local = encoding_value(cd->content_encoding, HTRequest_encoding(request));
 168:    double ceq_global = encoding_value(cd->content_encoding, HTFormat_contentCoding());
2.35 frystyk 169:    HTTRACE(PROT_TRACE, "Qualities... Content type: %.3f, Content language: %.3f, Content encoding: %.3f\n" _ 
 170:          HTMAX(ctq_local, ctq_global) _ 
 171:          HTMAX(clq_local, clq_global) _ 
2.29 frystyk 172:          HTMAX(ceq_local, ceq_global));
 173:    cd->quality *= (HTMAX(ctq_local, ctq_global) *
 174:            HTMAX(clq_local, clq_global) *
 175:            HTMAX(ceq_local, ceq_global));
 176:    cd = (HTContentDescription *) HTArray_nextObject(variants, data);
 177:   }
 178: 
 179:   /* Sort the array of all our accepted preferences */
 180:   HTArray_sort(variants, VariantSort);
 181: 
 182:   /* Write out the result */
2.35 frystyk 183: #ifdef HTDEBUG 
2.29 frystyk 184:   if (PROT_TRACE) {
 185:    int cnt = 1;
 186:    cd = (HTContentDescription *) HTArray_firstObject(variants, data);
2.35 frystyk 187:    HTTRACE(PROT_TRACE, "Ranking.....\n");
 188:    HTTRACE(PROT_TRACE, "RANK QUALITY CONTENT-TYPE     LANGUAGE ENCODING FILE\n");
2.29 frystyk 189:    while (cd) {
2.35 frystyk 190:      HTTRACE(PROT_TRACE, "%d.  %.4f %-20.20s %-8.8s %-10.10s %s\n" _
 191:          cnt++ _
 192:          cd->quality _
 193:          cd->content_type ? HTAtom_name(cd->content_type) : "-" _
 194:          cd->content_language?HTAtom_name(cd->content_language):"-" _
 195:          cd->content_encoding?HTAtom_name(cd->content_encoding):"-" _
2.29 frystyk 196:          cd->filename ? cd->filename :"-");
 197:      cd = (HTContentDescription *) HTArray_nextObject(variants, data);
 198:    }
 199:   }
2.35 frystyk 200: #endif /* HTDEBUG */
2.29 frystyk 201:   return YES;
 202: }
2.3 luotonen 203: 
2.14 frystyk 204: /* PUBLIC                       HTSplitFilename()
 205: **
 206: **   Split the filename to an array of suffixes.
 207: **   Return the number of parts placed to the array.
 208: **   Array should have MAX_SUFF+1 items.
 209: */
2.23 frystyk 210: PRIVATE int HTSplitFilename (char * s_str, char ** s_arr)
2.14 frystyk 211: {
2.26 frystyk 212:   const char *delimiters = HTBind_delimiters();
2.14 frystyk 213:   char * start = s_str;
 214:   char * end;
 215:   char save;
 216:   int i;
 217: 
 218:   if (!s_str || !s_arr) return 0;
 219: 
 220:   for (i=0; i < MAX_SUFF && *start; i++) {
 221:    for(end=start+1; *end && !strchr(delimiters, *end); end++);
 222:    save = *end;
 223:    *end = 0;
 224:    StrAllocCopy(s_arr[i], start); /* Frees the previous value */
 225:    *end = save;
 226:    start = end;
 227:   }
2.24 frystyk 228:   HT_FREE(s_arr[i]);    /* Terminating NULL */
2.14 frystyk 229:   return i;
 230: }
 231: 
 232: 
2.3 luotonen 233: /*
 234: **   Set default file name for welcome page on each directory.
 235: */
2.23 frystyk 236: PUBLIC void HTAddWelcome (char * name)
2.3 luotonen 237: {
 238:   if (name) {
 239:    char * mycopy = NULL;
 240:    StrAllocCopy(mycopy,name);
 241: 
 242:    if (!welcome_names)
 243:      welcome_names = HTList_new();
 244:    HTList_addObject(welcome_names, (void*)mycopy);
 245:   }
 246: }
 247: 
 248: 
2.26 frystyk 249: #ifdef HAVE_READDIR
2.1 luotonen 250: 
 251: /* PRIVATE                       multi_match()
 252: **
 253: **   Check if actual filename (split in parts) fulfills
 254: **   the requirements.
 255: */
2.23 frystyk 256: PRIVATE BOOL multi_match (char ** required, int m, char ** actual, int n)
2.1 luotonen 257: {
 258:   int c;
 259:   int i,j;
 260: 
2.2 duns 261: #ifdef VMS
 262:   for(c=0; c<m && c<n && !strcasecomp(required[c], actual[c]); c++);
 263: #else /* not VMS */
2.1 luotonen 264:   for(c=0; c<m && c<n && !strcmp(required[c], actual[c]); c++);
2.2 duns 265: #endif /* not VMS */
2.1 luotonen 266: 
 267:   if (!c) return NO;     /* Names differ rigth from start */
 268: 
 269:   for(i=c; i<m; i++) {
 270:    BOOL found = NO;
 271:    for(j=c; j<n; j++) {
2.2 duns 272: #ifdef VMS
 273:      if (!strcasecomp(required[i], actual[j])) {
 274: #else /* not VMS */
2.1 luotonen 275:      if (!strcmp(required[i], actual[j])) {
2.2 duns 276: #endif /* not VMS */
2.1 luotonen 277:        found = YES;
 278:        break;
 279:      }
 280:    }
 281:    if (!found) return NO;
 282:   }
 283:   return YES;
 284: }
 285: 
 286: 
 287: /*
 288: **   Get multi-match possibilities for a given file
 289: **   ----------------------------------------------
 290: ** On entry:
 291: **   path  absolute path to one file in a directory,
 292: **       may end in .multi.
 293: ** On exit:
 294: **   returns a list of ContentDesription structures
 295: **       describing the mathing files.
 296: **
 297: */
2.29 frystyk 298: PRIVATE HTArray * dir_matches (char * path)
2.1 luotonen 299: {
 300:   static char * required[MAX_SUFF+1];
 301:   static char * actual[MAX_SUFF+1];
 302:   int m,n;
 303:   char * dirname = NULL;
 304:   char * basename = NULL;
 305:   int baselen;
 306:   char * multi = NULL;
 307:   DIR * dp;
2.26 frystyk 308:   struct dirent * dirbuf;
2.29 frystyk 309:   HTArray * matches = NULL;
2.16 frystyk 310: #ifdef HT_REENTRANT
2.31 frystyk 311:   struct dirent result;                    /* For readdir_r */
2.16 frystyk 312: #endif
2.1 luotonen 313: 
 314:   if (!path) return NULL;
 315: 
 316:   StrAllocCopy(dirname, path);
 317:   basename = (strrchr(dirname, '/'));
 318:   if (!basename)
 319:    goto dir_match_failed;
 320:   *basename++ = 0;
 321: 
 322:   multi = strrchr(basename, MULTI_SUFFIX[0]);
2.2 duns 323:   if (multi && !strcasecomp(multi, MULTI_SUFFIX))
2.1 luotonen 324:    *multi = 0;
 325:   baselen = strlen(basename);
 326: 
 327:   m = HTSplitFilename(basename, required);
 328: 
 329:   dp = opendir(dirname);
 330:   if (!dp) {
2.35 frystyk 331:    HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ dirname);
2.1 luotonen 332:    goto dir_match_failed;
 333:   }
 334: 
2.29 frystyk 335:   matches = HTArray_new(VARIANTS);
2.36 kahan 336: #ifdef HAVE_READDIR_R_2
2.31 frystyk 337:    while ((dirbuf = (struct dirent *) readdir_r(dp, &result))) {
2.36 kahan 338: #elif defined(HAVE_READDIR_R_3)
 339:     while (readdir_r(dp, &result, &dirbuf) == 0) {
2.16 frystyk 340: #else
 341:    while ((dirbuf = readdir(dp))) {
2.36 kahan 342: #endif /* HAVE_READDIR_R_2 */
2.1 luotonen 343:    if (!dirbuf->d_ino) continue;  /* Not in use */
2.3 luotonen 344:    if (!strcmp(dirbuf->d_name,".") ||
 345:      !strcmp(dirbuf->d_name,"..") ||
2.20 frystyk 346:      !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
2.3 luotonen 347:      continue;
2.7 frystyk 348: 
2.13 frystyk 349:    /* Use of direct->namlen is only valid in BSD'ish system */
 350:    /* Thanks to chip@chinacat.unicom.com (Chip Rosenthal) */
 351:    /* if ((int)(dirbuf->d_namlen) >= baselen) { */
 352:    if ((int) strlen(dirbuf->d_name) >= baselen) {
2.1 luotonen 353:      n = HTSplitFilename(dirbuf->d_name, actual);
 354:      if (multi_match(required, m, actual, n)) {
 355:        HTContentDescription * cd;
2.29 frystyk 356:        if ((cd = (HTContentDescription *)
 357:           HT_CALLOC(1, sizeof(HTContentDescription))) == NULL)
 358:          HT_OUTOFMEM("dir_matches");
 359:        if (HTBind_getFormat(dirbuf->d_name,
 360:                   &cd->content_type,
 361:                   &cd->content_encoding,
 362:                   &cd->content_transfer,
 363:                   &cd->content_language,
 364:                   &cd->quality)) {
2.1 luotonen 365:          if (cd->content_type) {
2.24 frystyk 366:            if ((cd->filename = (char *) HT_MALLOC(strlen(dirname) + 2 + strlen(dirbuf->d_name))) == NULL)
 367:              HT_OUTOFMEM("dir_matches");
2.29 frystyk 368:            sprintf(cd->filename, "%s/%s", dirname, dirbuf->d_name);
 369:            HTArray_addObject(matches, (void *) cd);
 370:          } else {
 371:            HT_FREE(cd);
2.1 luotonen 372:          }
2.29 frystyk 373:        } else {
 374:          HT_FREE(cd);
2.1 luotonen 375:        }
 376:      }
 377:    }
 378:   }
 379:   closedir(dp);
 380: 
 381:  dir_match_failed:
2.24 frystyk 382:   HT_FREE(dirname);
2.1 luotonen 383:   return matches;
 384: }
 385: 
 386: 
 387: /*
 388: **   Get the best match for a given file
 389: **   -----------------------------------
 390: ** On entry:
 391: **   req->conversions accepted content-types
 392: **   req->encodings  accepted content-transfer-encodings
 393: **   req->languages  accepted content-languages
 394: **   path       absolute pathname of the filename for
 395: **            which the match is desired.
 396: ** On exit:
 397: **   returns a newly allocated absolute filepath.
 398: */
2.23 frystyk 399: PRIVATE char * HTGetBest (HTRequest * req, char * path)
2.1 luotonen 400: {
2.29 frystyk 401:   HTArray * variants = NULL;
 402:   char * representation = NULL;
2.1 luotonen 403: 
2.13 frystyk 404:   if (!path || !*path) return NULL;
2.1 luotonen 405: 
2.29 frystyk 406:   if ((variants = dir_matches(path)) == NULL) {
2.35 frystyk 407:    HTTRACE(PROT_TRACE, "No matches.. for \"%s\"\n" _ path);
2.13 frystyk 408:    return NULL;
2.1 luotonen 409:   }
 410: 
2.35 frystyk 411: #ifdef HTDEBUG
2.29 frystyk 412:   if (PROT_TRACE) {
 413:    void ** data;
 414:    HTContentDescription * cd = HTArray_firstObject(variants, data);
2.35 frystyk 415:    HTTRACE(PROT_TRACE, "Multi....... Possibilities for \"%s\"\n" _ path);
 416:    HTTRACE(PROT_TRACE, "   QUALITY CONTENT-TYPE     LANGUAGE ENCODING FILE\n");
2.29 frystyk 417:    while (cd) {
2.35 frystyk 418:      HTTRACE(PROT_TRACE, "   %.4f %-20.20s %-8.8s %-10.10s %s\n" _
 419:          cd->quality _
 420:          cd->content_type  ?HTAtom_name(cd->content_type) :"-\t" _
 421:          cd->content_language?HTAtom_name(cd->content_language):"-" _
 422:          cd->content_encoding?HTAtom_name(cd->content_encoding):"-" _
2.29 frystyk 423:          cd->filename    ?cd->filename          :"-");
 424:      cd = (HTContentDescription *) HTArray_nextObject(variants, data);
 425:    }
2.1 luotonen 426:   }
2.35 frystyk 427: #endif /* HTDEBUG */
2.1 luotonen 428: 
 429:   /*
2.29 frystyk 430:   ** Finally get the best variant which is readable
2.1 luotonen 431:   */
2.29 frystyk 432:   if (HTRank(req, variants)) {
2.37 ! kahan 433:    void ** data = NULL;
2.29 frystyk 434:    HTContentDescription * cd = HTArray_firstObject(variants, data);
 435:    while (cd) {
 436:      if (cd->filename) {
 437:        if (access(cd->filename, R_OK) != -1)
 438:          StrAllocCopy(representation, cd->filename);
2.35 frystyk 439:        else HTTRACE(PROT_TRACE, "Multi....... `%s\' is not readable\n" _ 
2.29 frystyk 440:              cd->filename);
2.1 luotonen 441:      }
2.29 frystyk 442:      HT_FREE(cd->filename);
 443:      HT_FREE(cd);
 444:      cd = (HTContentDescription *) HTArray_nextObject(variants, data);
2.1 luotonen 445:    }
 446:   }
2.29 frystyk 447:   HTArray_delete(variants);
 448:   return representation;
2.1 luotonen 449: }
 450: 
2.3 luotonen 451: 
 452: 
2.23 frystyk 453: PRIVATE int welcome_value (char * name)
2.3 luotonen 454: {
 455:   HTList * cur = welcome_names;
 456:   char * welcome;
 457:   int v = 0;
 458: 
 459:   while ((welcome = (char*)HTList_nextObject(cur))) {
 460:    v++;
 461:    if (!strcmp(welcome,name)) return v;
 462:   }
 463:   return 0;
 464: }
 465: 
 466: 
 467: 
2.23 frystyk 468: PRIVATE char * get_best_welcome (char * path)
2.3 luotonen 469: {
 470:   char * best_welcome = NULL;
 471:   int best_value = 0;
 472:   DIR * dp;
2.26 frystyk 473:   struct dirent * dirbuf;
2.3 luotonen 474:   char * last = strrchr(path, '/');
 475: 
 476:   if (!welcome_names) {
 477:    HTAddWelcome("Welcome.html");
 478:    HTAddWelcome("welcome.html");
2.5 luotonen 479: #if 0
2.3 luotonen 480:    HTAddWelcome("Index.html");
2.5 luotonen 481: #endif
2.3 luotonen 482:    HTAddWelcome("index.html");
 483:   }
 484: 
2.5 luotonen 485:   if (last && last!=path) *last = 0;
2.3 luotonen 486:   dp = opendir(path);
2.5 luotonen 487:   if (last && last!=path) *last='/';
2.3 luotonen 488:   if (!dp) {
2.35 frystyk 489:    HTTRACE(PROT_TRACE, "Warning..... Can't open directory %s\n" _ path);
2.3 luotonen 490:    return NULL;
 491:   }
 492:   while ((dirbuf = readdir(dp))) {
2.13 frystyk 493:    if (!dirbuf->d_ino ||
2.3 luotonen 494:      !strcmp(dirbuf->d_name,".") ||
 495:      !strcmp(dirbuf->d_name,"..") ||
2.20 frystyk 496:      !strcmp(dirbuf->d_name, DEFAULT_DIR_FILE))
2.3 luotonen 497:      continue;
 498:    else {
 499:      int v = welcome_value(dirbuf->d_name);
 500:      if (v > best_value) {
 501:        best_value = v;
 502:        StrAllocCopy(best_welcome, dirbuf->d_name);
 503:      }
 504:    }
 505:   }
 506:   closedir(dp);
 507: 
 508:   if (best_welcome) {
2.24 frystyk 509:    char * welcome;
 510:    if ((welcome = (char *) HT_MALLOC(strlen(path) + strlen(best_welcome)+2)) == NULL)
 511:      HT_OUTOFMEM("get_best_welcome");
2.4 luotonen 512:    sprintf(welcome, "%s%s%s", path, last ? "" : "/", best_welcome);
2.24 frystyk 513:    HT_FREE(best_welcome);
2.35 frystyk 514:    HTTRACE(PROT_TRACE, "Welcome..... \"%s\"\n" _ welcome);
2.3 luotonen 515:    return welcome;
 516:   }
 517:   return NULL;
 518: }
 519: 
2.26 frystyk 520: #endif /* HAVE_READDIR */
2.1 luotonen 521: 
 522: 
 523: /*
 524: **   Do multiformat handling
 525: **   -----------------------
 526: ** On entry:
 527: **   req->conversions accepted content-types
 528: **   req->encodings  accepted content-transfer-encodings
 529: **   req->languages  accepted content-languages
 530: **   path       absolute pathname of the filename for
 531: **            which the match is desired.
 532: **   stat_info     pointer to result space.
 533: **
 534: ** On exit:
 535: **   returns a newly allocated absolute filepath of the best
 536: **       match, or NULL if no match.
 537: **   stat_info     will contain inode information as
 538: **            returned by stat().
 539: */
2.23 frystyk 540: PUBLIC char * HTMulti (HTRequest *   req,
 541:            char *      path,
 542:            struct stat *  stat_info)
2.1 luotonen 543: {
 544:   char * new_path = NULL;
 545:   int stat_status = -1;
 546: 
2.3 luotonen 547:   if (!req || !path || !*path || !stat_info)
2.1 luotonen 548:    return NULL;
 549: 
2.26 frystyk 550: #ifdef HAVE_READDIR
2.19 frystyk 551:   if (*(path+strlen(path)-1) == '/') {    /* Find welcome page */
2.3 luotonen 552:    new_path = get_best_welcome(path);
 553:    if (new_path) path = new_path;
2.29 frystyk 554:   } else{
2.3 luotonen 555:    char * multi = strrchr(path, MULTI_SUFFIX[0]);
 556:    if (multi && !strcasecomp(multi, MULTI_SUFFIX)) {
2.35 frystyk 557:      HTTRACE(PROT_TRACE, "Multi....... by %s suffix\n" _ MULTI_SUFFIX);
2.1 luotonen 558:      if (!(new_path = HTGetBest(req, path))) {
2.35 frystyk 559:        HTTRACE(PROT_TRACE, "Multi....... failed -- giving up\n");
2.1 luotonen 560:        return NULL;
 561:      }
 562:      path = new_path;
2.29 frystyk 563:    } else {
2.18 frystyk 564:      stat_status = HT_STAT(path, stat_info);
2.3 luotonen 565:      if (stat_status == -1) {
2.35 frystyk 566:        HTTRACE(PROT_TRACE, "AutoMulti... can't stat \"%s\"(errno %d)\n" _ 
 567:              path _ errno);
2.3 luotonen 568:        if (!(new_path = HTGetBest(req, path))) {
2.35 frystyk 569:          HTTRACE(PROT_TRACE, "AutoMulti... failed -- giving up\n");
2.3 luotonen 570:          return NULL;
 571:        }
 572:        path = new_path;
 573:      }
2.1 luotonen 574:    }
 575:   }
2.26 frystyk 576: #endif /* HAVE_READDIR */
2.1 luotonen 577: 
 578:   if (stat_status == -1)
2.18 frystyk 579:    stat_status = HT_STAT(path, stat_info);
2.1 luotonen 580:   if (stat_status == -1) {
2.35 frystyk 581:    HTTRACE(PROT_TRACE, "Stat fails.. on \"%s\" -- giving up (errno %d)\n" _ 
 582:          path _ errno);
2.1 luotonen 583:    return NULL;
2.29 frystyk 584:   } else {
2.1 luotonen 585:    if (!new_path) {
 586:      StrAllocCopy(new_path, path);
 587:      return new_path;
 588:    }
 589:    else return path;
 590:   }
 591: }
 592: 
 593: 

Webmaster

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