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

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

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

Webmaster

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