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

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

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

Webmaster

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