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

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

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: 
 ! 12: #include "HTFile.h"
 ! 13: #include "HTList.h"
 ! 14: 
 ! 15: #ifdef USE_DIRENT       /* Set this for Sys V systems */
 ! 16: #define STRUCT_DIRENT struct dirent
 ! 17: #else
 ! 18: #define STRUCT_DIRENT struct direct
 ! 19: #endif
 ! 20: 
 ! 21: 
 ! 22: #ifdef GOT_READ_DIR
 ! 23: 
 ! 24: /* PRIVATE                       multi_match()
 ! 25: **
 ! 26: **   Check if actual filename (split in parts) fulfills
 ! 27: **   the requirements.
 ! 28: */
 ! 29: PRIVATE BOOL multi_match ARGS4(char **, required,
 ! 30:                int,   m,
 ! 31:                char **, actual,
 ! 32:                int,   n)
 ! 33: {
 ! 34:   int c;
 ! 35:   int i,j;
 ! 36: 
 ! 37:   for(c=0; c<m && c<n && !strcmp(required[c], actual[c]); c++);
 ! 38: 
 ! 39:   if (!c) return NO;     /* Names differ rigth from start */
 ! 40: 
 ! 41:   for(i=c; i<m; i++) {
 ! 42:    BOOL found = NO;
 ! 43:    for(j=c; j<n; j++) {
 ! 44:      if (!strcmp(required[i], actual[j])) {
 ! 45:        found = YES;
 ! 46:        break;
 ! 47:      }
 ! 48:    }
 ! 49:    if (!found) return NO;
 ! 50:   }
 ! 51:   return YES;
 ! 52: }
 ! 53: 
 ! 54: 
 ! 55: /*
 ! 56: **   Get multi-match possibilities for a given file
 ! 57: **   ----------------------------------------------
 ! 58: ** On entry:
 ! 59: **   path  absolute path to one file in a directory,
 ! 60: **       may end in .multi.
 ! 61: ** On exit:
 ! 62: **   returns a list of ContentDesription structures
 ! 63: **       describing the mathing files.
 ! 64: **
 ! 65: */
 ! 66: PRIVATE HTList * dir_matches ARGS1(char *, path)
 ! 67: {
 ! 68:   static char * required[MAX_SUFF+1];
 ! 69:   static char * actual[MAX_SUFF+1];
 ! 70:   int m,n;
 ! 71:   char * dirname = NULL;
 ! 72:   char * basename = NULL;
 ! 73:   int baselen;
 ! 74:   char * multi = NULL;
 ! 75:   DIR * dp;
 ! 76:   STRUCT_DIRENT * dirbuf;
 ! 77:   HTList * matches = NULL;
 ! 78: 
 ! 79:   if (!path) return NULL;
 ! 80: 
 ! 81:   StrAllocCopy(dirname, path);
 ! 82:   basename = (strrchr(dirname, '/'));
 ! 83:   if (!basename)
 ! 84:    goto dir_match_failed;
 ! 85:   *basename++ = 0;
 ! 86: 
 ! 87:   multi = strrchr(basename, MULTI_SUFFIX[0]);
 ! 88:   if (multi && !strcmp(multi, MULTI_SUFFIX))
 ! 89:    *multi = 0;
 ! 90:   baselen = strlen(basename);
 ! 91: 
 ! 92:   m = HTSplitFilename(basename, required);
 ! 93: 
 ! 94:   dp = opendir(dirname);
 ! 95:   if (!dp) {
 ! 96:    CTRACE(stderr,"Warning..... Can't open directory %s\n",
 ! 97:        dirname);
 ! 98:    goto dir_match_failed;
 ! 99:   }
 ! 100: 
 ! 101:   matches = HTList_new();
 ! 102:   while ((dirbuf = readdir(dp))) {
 ! 103:    if (!dirbuf->d_ino) continue;  /* Not in use */
 ! 104:    if ((int)(dirbuf->d_namlen) >= baselen) {
 ! 105:      n = HTSplitFilename(dirbuf->d_name, actual);
 ! 106:      if (multi_match(required, m, actual, n)) {
 ! 107:        HTContentDescription * cd;
 ! 108:        cd = HTGetContentDescription(actual, n);
 ! 109:        if (cd) {
 ! 110:          if (cd->content_type) {
 ! 111:            cd->filename = (char*)malloc(strlen(dirname) + 2 +
 ! 112:                           strlen(dirbuf->d_name));
 ! 113:            if (!cd->filename) outofmem(__FILE__, "dir_matches");
 ! 114:            sprintf(cd->filename, "%s/%s",
 ! 115:                dirname, dirbuf->d_name);
 ! 116:            HTList_addObject(matches, (void*)cd);
 ! 117:          }
 ! 118:          else free(cd);
 ! 119:        }
 ! 120:      }
 ! 121:    }
 ! 122:   }
 ! 123:   closedir(dp);
 ! 124: 
 ! 125:  dir_match_failed:
 ! 126:   free(dirname);
 ! 127:   return matches;
 ! 128: }
 ! 129: 
 ! 130: 
 ! 131: /*
 ! 132: **   Get the best match for a given file
 ! 133: **   -----------------------------------
 ! 134: ** On entry:
 ! 135: **   req->conversions accepted content-types
 ! 136: **   req->encodings  accepted content-transfer-encodings
 ! 137: **   req->languages  accepted content-languages
 ! 138: **   path       absolute pathname of the filename for
 ! 139: **            which the match is desired.
 ! 140: ** On exit:
 ! 141: **   returns a newly allocated absolute filepath.
 ! 142: */
 ! 143: PRIVATE char * HTGetBest ARGS2(HTRequest *,  req,
 ! 144:                char *,     path)
 ! 145: {
 ! 146:   HTList * matches;
 ! 147:   HTList * cur;
 ! 148:   HTContentDescription * cd;
 ! 149:   HTContentDescription * best = NULL;
 ! 150:   char * best_path = NULL;
 ! 151: 
 ! 152:   
 ! 153:   if (!path || !*path) return NO;
 ! 154: 
 ! 155:   matches = dir_matches(path);
 ! 156:   if (!matches) {
 ! 157:    CTRACE(stderr, "No matches.. for \"%s\"\n", path);
 ! 158:    return NO;
 ! 159:   }
 ! 160: 
 ! 161:   /* BEGIN DEBUG */
 ! 162:   cur = matches;
 ! 163:   CTRACE(stderr, "Multi....... Possibilities for \"%s\"\n", path);
 ! 164:   CTRACE(stderr, "\nCONTENT-TYPE LANGUAGE ENCODING QUALITY FILE\n");
 ! 165:   while ((cd = (HTContentDescription*)HTList_nextObject(cur))) {
 ! 166:    CTRACE(stderr, "%s\t%s\t%s\t %.5f %s\n",
 ! 167:        cd->content_type  ?HTAtom_name(cd->content_type) :"-\t",
 ! 168:        cd->content_language?HTAtom_name(cd->content_language):"-",
 ! 169:        cd->content_encoding?HTAtom_name(cd->content_encoding):"-",
 ! 170:        cd->quality,
 ! 171:        cd->filename    ?cd->filename           :"-");
 ! 172:   }
 ! 173:   CTRACE(stderr, "\n");
 ! 174:   /* END DEBUG */
 ! 175: 
 ! 176:   /*
 ! 177:   ** Finally get best that is readable
 ! 178:   */
 ! 179:   if (HTRank(matches, req->conversions, req->languages, req->encodings)) {
 ! 180:    cur = matches;
 ! 181:    while ((best = (HTContentDescription*)HTList_nextObject(cur))) {
 ! 182:      if (best && best->filename) {
 ! 183:        if (access(best->filename, R_OK) != -1) {
 ! 184:          StrAllocCopy(best_path, best->filename);
 ! 185:          break;
 ! 186:        }
 ! 187:        else CTRACE(stderr, "Bad News.... \"%s\" is not readable\n",
 ! 188:              best->filename);
 ! 189:      }
 ! 190:    }
 ! 191:   } /* Select best */
 ! 192: 
 ! 193:   cur = matches;
 ! 194:   while ((cd = (HTContentDescription*)HTList_nextObject(cur))) {
 ! 195:    if (cd->filename) free(cd->filename);
 ! 196:    free(cd);
 ! 197:   }
 ! 198:   HTList_delete(matches);
 ! 199: 
 ! 200:   return best_path;
 ! 201: }
 ! 202: 
 ! 203: 
 ! 204: 
 ! 205: /*
 ! 206: **   Do multiformat handling
 ! 207: **   -----------------------
 ! 208: ** On entry:
 ! 209: **   req->conversions accepted content-types
 ! 210: **   req->encodings  accepted content-transfer-encodings
 ! 211: **   req->languages  accepted content-languages
 ! 212: **   path       absolute pathname of the filename for
 ! 213: **            which the match is desired.
 ! 214: **   stat_info     pointer to result space.
 ! 215: **
 ! 216: ** On exit:
 ! 217: **   returns a newly allocated absolute filepath of the best
 ! 218: **       match, or NULL if no match.
 ! 219: **   stat_info     will contain inode information as
 ! 220: **            returned by stat().
 ! 221: */
 ! 222: PUBLIC char * HTMulti ARGS3(HTRequest *,    req,
 ! 223:              char *,       path,
 ! 224:              struct stat *,   stat_info)
 ! 225: {
 ! 226:   char * multi;
 ! 227:   char * new_path = NULL;
 ! 228:   int stat_status = -1;
 ! 229: 
 ! 230:   if (!req || !path || !stat_info)
 ! 231:    return NULL;
 ! 232: 
 ! 233:   multi = strrchr(path, MULTI_SUFFIX[0]);
 ! 234:   if (multi && !strcmp(multi, MULTI_SUFFIX)) {
 ! 235:    CTRACE(stderr, "Multi....... by %s suffix\n", MULTI_SUFFIX);
 ! 236:    if (!(new_path = HTGetBest(req, path))) {
 ! 237:      CTRACE(stderr, "Multi....... failed -- giving up\n");
 ! 238:      return NULL;
 ! 239:    }
 ! 240:    path = new_path;
 ! 241:   }
 ! 242:   else {
 ! 243:    stat_status = stat(path, stat_info);
 ! 244:    if (stat_status == -1) {
 ! 245:      CTRACE(stderr,
 ! 246:          "AutoMulti... because couldn't stat \"%s\" (errno %d)\n",
 ! 247:          path, errno);
 ! 248:      if (!(new_path = HTGetBest(req, path))) {
 ! 249:        CTRACE(stderr, "AutoMulti... failed -- giving up\n");
 ! 250:        return NULL;
 ! 251:      }
 ! 252:      path = new_path;
 ! 253:    }
 ! 254:   }
 ! 255: 
 ! 256:   if (stat_status == -1)
 ! 257:    stat_status = stat(path, stat_info);
 ! 258:   if (stat_status == -1) {
 ! 259:    CTRACE(stderr, "Stat fails.. on \"%s\" -- giving up (errno %d)\n",
 ! 260:        path, errno);
 ! 261:    return NULL;
 ! 262:   }
 ! 263:   else {
 ! 264:    if (!new_path) {
 ! 265:      StrAllocCopy(new_path, path);
 ! 266:      return new_path;
 ! 267:    }
 ! 268:    else return path;
 ! 269:   }
 ! 270: }
 ! 271: 
 ! 272: #endif /* GOT_READ_DIR */
 ! 273: 

Webmaster

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