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