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

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

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

Webmaster

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