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

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

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

Webmaster

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