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

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

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

Webmaster

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