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

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

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

Webmaster

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