contentlanguage.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:5k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc.
- ** See COPYING for distribution information.
- */
- /* $Id: contentlanguage.c,v 1.11 2000/06/03 14:50:18 mrsam Exp $ */
- #if HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include "http11.h"
- #include "../rfc2045/rfc2045charset.h"
- #if HAVE_DIRENT_H
- #include <dirent.h>
- #define NAMLEN(dirent) strlen(dirent->d_name)
- #else
- #define dirent direct
- #define NAMLEN(dirent) ((dirent)->d_namlen)
- #if HAVE_SYS_NDIR_H
- #include <sys/ndir.h>
- #endif
- #if HAVE_SYS_DIR_H
- #include <sys/dir.h>
- #endif
- #if HAVE_NDIR_H
- #include <ndir.h>
- #endif
- #endif
- extern void error(const char *);
- static void enomem()
- {
- error("Out of memory.");
- }
- static const char defaultlang[] = HTTP11_DEFAULTLANG;
- /*
- ** Based upon Accept-Language: header, figure out which directory in
- ** HTMLLIBDIR matches it.
- */
- FILE *http11_open_langfile(const char *libdir, const char *subdir,
- const char *file)
- {
- char *p=malloc(strlen(libdir)+strlen(subdir)+strlen(file)+3);
- FILE *fp;
- if (!p) return (0);
- strcat(strcat(strcat(strcat(strcpy(p, libdir), "/"), subdir), "/"),
- file);
- fp=fopen(p, "r");
- free(p);
- return (fp);
- }
- /**************************************************************************/
- /* Parse Accept-Language: header */
- static size_t parse_accept_language(const char *acc_lang, char **languages,
- double *weights)
- {
- char *p=strdup(acc_lang ? acc_lang:"");
- size_t cnt=0;
- char *q, *r;
- int has_weights=0;
- double *save_weights=weights;
- if (!p) enomem();
- for (q=p; (q=strtok(q, ", ")) != 0; q=0)
- {
- if (languages)
- {
- q=strdup(q);
- if (!q) enomem();
- *languages++=q;
- }
- if (weights) *weights=1; /* Until further notice */
- for (r=q; *r; r++)
- *r=tolower(*r);
- if ((r=strchr(q, ':')) != 0)
- {
- *r++=0;
- if (*r == 'q' && r[1] == '=')
- {
- double weight=atof(r+2);
- if (weights) *weights=weight;
- has_weights=1;
- }
- }
- if (weights) ++weights;
- ++cnt;
- }
- free(p);
- if (!has_weights && weights)
- {
- size_t i;
- double weight=1;
- /*
- ** Broken HTTP/1.1 clients do not specify quality factors, and expect
- ** the server to pick the first one on the list
- */
- for (i=cnt; i; )
- {
- --i;
- save_weights[i]=weight;
- weight = weight + 1;
- }
- }
-
- return (cnt);
- }
- char *http11_best_content_language(const char *libdir, const char *acc_lang)
- {
- size_t naccept=parse_accept_language(acc_lang, 0, 0);
- char **languages=malloc(naccept ? sizeof(char *)*naccept:1);
- double *weights=malloc(naccept ? sizeof(double)*naccept:1);
- DIR *p;
- struct dirent *de;
- size_t i;
- double missweight=1;
- char *bestlang=0;
- double bestweight=0;
- int found_nondefault_match=0;
- if (!languages || !weights)
- {
- if (languages) free(languages);
- if (weights) free(weights);
- enomem();
- }
- (void)parse_accept_language(acc_lang, languages, weights);
- for (i=0; i<naccept; i++)
- if (strcmp(languages[i], "*") == 0) missweight=weights[i];
- /* Default weight */
- p=opendir(libdir);
- while (p && (de=readdir(p)) != 0)
- {
- FILE *fp;
- if (*de->d_name == '.') continue;
- if ((fp=http11_open_langfile(libdir, de->d_name, "LOCALE"))
- != 0)
- {
- #if 0
- double myweight=missweight;
- #else
- double myweight=0;
- #endif
- fclose(fp);
- for (i=0; i<naccept; i++)
- if (strcmp(languages[i], de->d_name) == 0)
- {
- myweight=weights[i];
- break;
- }
- if (!bestlang || myweight > bestweight)
- {
- if (bestlang) free(bestlang);
- bestlang=strdup(de->d_name);
- if (!bestlang) enomem();
- bestweight=myweight;
- if (i < naccept)
- found_nondefault_match=1;
- }
- }
- }
- if (p) closedir(p);
- if (!bestlang || !found_nondefault_match)
- {
- if (bestlang) free(bestlang);
- if ((bestlang=malloc(sizeof(defaultlang))) == 0) enomem();
- strcpy(bestlang, defaultlang);
- }
- for (i=0; i<naccept; i++)
- free(languages[i]);
- free(languages);
- free(weights);
- return (bestlang);
- }
- static const char *get_http11(const char *libdir, const char *subdir,
- char *buf,
- const char *file, const char *def)
- {
- FILE *fp=http11_open_langfile(libdir, subdir, file);
- if (fp != 0)
- {
- size_t n=fread(buf, 1, 79, fp);
- if (n <= 0) n=0;
- buf[n]=0;
- fclose(fp);
- return (strtok(buf, "rn"));
- }
- return (def);
- }
- const char *http11_content_language(const char *libdir, const char *acc_lang)
- {
- static char buf[80];
- return (get_http11(libdir, acc_lang, buf, "LANGUAGE", defaultlang));
- }
- const char *http11_content_locale(const char *libdir, const char *acc_lang)
- {
- static char buf[80];
- const char *p=get_http11(libdir, acc_lang, buf, "LOCALE", "C");
- return (p);
- }
- const char *http11_content_ispelldict(const char *libdir, const char *acc_lang)
- {
- static char buf[80];
- return (get_http11(libdir, acc_lang, buf, "ISPELLDICT", defaultlang));
- }
- const char *http11_content_charset(const char *libdir, const char *acc_lang)
- {
- static char buf[80];
- return (get_http11(libdir, acc_lang, buf, "CHARSET", RFC2045CHARSET));
- }