📄 htmulti.c
字号:
/*** CONTENT NEGOTIATION**** (c) COPYRIGHT MIT 1995.** Please first read the full copyright statement in the file COPYRIGH.** @(#) $Id: HTMulti.c,v 2.35 1999/02/22 22:10:11 frystyk Exp $**** History:** March 94 AL Separated from HTFile.c because** multiformat handling would be a mess in VMS.*//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "HTMulti.h"#include "HTBind.h"#include "HTFile.h"#define MULTI_SUFFIX ".multi"/* Extension for scanning formats */#define MAX_SUFF 15 /* Maximum number of suffixes for a file */#define VARIANTS 4 /* We start with this array size */typedef struct _HTContentDescription { char * filename; HTFormat content_type; HTLanguage content_language; HTEncoding content_encoding; HTEncoding content_transfer; int content_length; double quality;} HTContentDescription;PRIVATE HTList * welcome_names = NULL; /* Welcome.html, index.html etc. *//* ------------------------------------------------------------------------- *//*** Sort the q values in descending order*/PRIVATE int VariantSort (const void * a, const void * b){ HTContentDescription * aa = *(HTContentDescription **) a; HTContentDescription * bb = *(HTContentDescription **) b; if (aa && bb) return (aa->quality > bb->quality) ? -1 : 1; return bb - aa;}/* * Added by takada@seraph.ntt.jp (94/04/08) */PRIVATE BOOL lang_match (HTAtom * tmplate, HTAtom * actual){ const char *t, *a; char *st, *sa; BOOL match = NO; if (tmplate && actual && (t = HTAtom_name(tmplate)) && (a = HTAtom_name(actual))) { st = strchr(t, '_'); sa = strchr(a, '_'); if ((st != NULL) && (sa != NULL)) { if (!strcasecomp(t, a)) match = YES; else match = NO; } else { if (st != NULL) *st = 0; if (sa != NULL) *sa = 0; if (!strcasecomp(t, a)) match = YES; else match = NO; if (st != NULL) *st = '_'; if (sa != NULL) *sa = '_'; } } return match;}PRIVATE double type_value (HTAtom * content_type, HTList * accepted){ if (!content_type) return (1.0); if (accepted) { HTList * cur = accepted; HTPresentation * pres; HTPresentation * wild = NULL; while ((pres = (HTPresentation *) HTList_nextObject(cur))) { if (pres->rep == content_type) return pres->quality; else if (HTMIMEMatch(pres->rep, content_type)) wild = pres; } if (wild) return wild->quality; else return (0.0); /* Nothing matched */ } return (1.0); /* We accept all types */}PRIVATE double lang_value (HTAtom * language, HTList * accepted){ if (!language) return (1.0); if (accepted) { HTList * cur = accepted; HTAcceptNode * node; HTAcceptNode * wild = NULL; while ((node = (HTAcceptNode *) HTList_nextObject(cur))) { if (node->atom == language) return node->quality; /* * patch by takada@seraph.ntt.jp (94/04/08) * the original line was * else if (HTMIMEMatch(node->atom, language)) { * and the new line is */ else if (lang_match(node->atom, language)) wild = node; } if (wild) return wild->quality; else return (0.0); /* Nothing matched */ } return (1.0); /* We accept all languages */}PRIVATE double encoding_value (HTAtom * encoding, HTList * accepted){ if (!encoding) return (1.0); if (accepted) { HTList * cur = accepted; HTAcceptNode * node; HTAcceptNode * wild = NULL; const char * e = HTAtom_name(encoding); if (!strcmp(e, "7bit") || !strcmp(e, "8bit") || !strcmp(e, "binary")) return (1.0); while ((node = (HTAcceptNode*)HTList_nextObject(cur))) { if (node->atom == encoding) return node->quality; else if (HTMIMEMatch(node->atom, encoding)) wild = node; } if (wild) return wild->quality; else return (0.0); /* Nothing matched */ } return (1.0); /* We accept all encodings */}PRIVATE BOOL HTRank (HTRequest * request, HTArray * variants){ HTContentDescription * cd; void ** data; if (!variants) { HTTRACE(PROT_TRACE, "Ranking..... No variants\n"); return NO; } /* ** Walk through the list of local and global preferences and find the ** overall q factor for each variant */ cd = (HTContentDescription *) HTArray_firstObject(variants, data); while (cd) { double ctq_local = type_value(cd->content_type, HTRequest_conversion(request)); double ctq_global = type_value(cd->content_type, HTFormat_conversion()); double clq_local = lang_value(cd->content_language, HTRequest_language(request)); double clq_global = lang_value(cd->content_language, HTFormat_language()); double ceq_local = encoding_value(cd->content_encoding, HTRequest_encoding(request)); double ceq_global = encoding_value(cd->content_encoding, HTFormat_contentCoding()); HTTRACE(PROT_TRACE, "Qualities... Content type: %.3f, Content language: %.3f, Content encoding: %.3f\n" _ HTMAX(ctq_local, ctq_global) _ HTMAX(clq_local, clq_global) _ HTMAX(ceq_local, ceq_global)); cd->quality *= (HTMAX(ctq_local, ctq_global) * HTMAX(clq_local, clq_global) * HTMAX(ceq_local, ceq_global)); cd = (HTContentDescription *) HTArray_nextObject(variants, data); } /* Sort the array of all our accepted preferences */ HTArray_sort(variants, VariantSort); /* Write out the result */#ifdef HTDEBUG if (PROT_TRACE) { int cnt = 1; cd = (HTContentDescription *) HTArray_firstObject(variants, data); HTTRACE(PROT_TRACE, "Ranking.....\n"); HTTRACE(PROT_TRACE, "RANK QUALITY CONTENT-TYPE LANGUAGE ENCODING FILE\n"); while (cd) { HTTRACE(PROT_TRACE, "%d. %.4f %-20.20s %-8.8s %-10.10s %s\n" _ cnt++ _ cd->quality _ cd->content_type ? HTAtom_name(cd->content_type) : "-" _ cd->content_language?HTAtom_name(cd->content_language):"-" _ cd->content_encoding?HTAtom_name(cd->content_encoding):"-" _ cd->filename ? cd->filename :"-"); cd = (HTContentDescription *) HTArray_nextObject(variants, data); } }#endif /* HTDEBUG */ return YES;}/* PUBLIC HTSplitFilename()**** Split the filename to an array of suffixes.** Return the number of parts placed to the array.** Array should have MAX_SUFF+1 items.*/PRIVATE int HTSplitFilename (char * s_str, char ** s_arr){ const char *delimiters = HTBind_delimiters(); char * start = s_str; char * end; char save; int i; if (!s_str || !s_arr) return 0; for (i=0; i < MAX_SUFF && *start; i++) { for(end=start+1; *end && !strchr(delimiters, *end); end++); save = *end; *end = 0; StrAllocCopy(s_arr[i], start); /* Frees the previous value */ *end = save; start = end; } HT_FREE(s_arr[i]); /* Terminating NULL */ return i;}/*** Set default file name for welcome page on each directory.*/PUBLIC void HTAddWelcome (char * name){ if (name) { char * mycopy = NULL; StrAllocCopy(mycopy,name); if (!welcome_names) welcome_names = HTList_new(); HTList_addObject(welcome_names, (void*)mycopy); }}#ifdef HAVE_READDIR/* PRIVATE multi_match()**** Check if actual filename (split in parts) fulfills** the requirements.*/PRIVATE BOOL multi_match (char ** required, int m, char ** actual, int n){ int c; int i,j;#ifdef VMS for(c=0; c<m && c<n && !strcasecomp(required[c], actual[c]); c++);#else /* not VMS */ for(c=0; c<m && c<n && !strcmp(required[c], actual[c]); c++);#endif /* not VMS */ if (!c) return NO; /* Names differ rigth from start */ for(i=c; i<m; i++) { BOOL found = NO; for(j=c; j<n; j++) {#ifdef VMS if (!strcasecomp(required[i], actual[j])) {#else /* not VMS */ if (!strcmp(required[i], actual[j])) {#endif /* not VMS */ found = YES; break; } } if (!found) return NO; } return YES;}/*** Get multi-match possibilities for a given file** ----------------------------------------------** On entry:** path absolute path to one file in a directory,** may end in .multi.** On exit:** returns a list of ContentDesription structures** describing the mathing files.**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -