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