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

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

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

Webmaster

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