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

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

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

Webmaster

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