contentlanguage.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:5k
源码类别:

WEB邮件程序

开发平台:

C/C++

  1. /*
  2. ** Copyright 1998 - 1999 Double Precision, Inc.
  3. ** See COPYING for distribution information.
  4. */
  5. /* $Id: contentlanguage.c,v 1.11 2000/06/03 14:50:18 mrsam Exp $ */
  6. #if HAVE_CONFIG_H
  7. #include "config.h"
  8. #endif
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <stdlib.h>
  12. #include <ctype.h>
  13. #include "http11.h"
  14. #include "../rfc2045/rfc2045charset.h"
  15. #if HAVE_DIRENT_H
  16. #include <dirent.h>
  17. #define NAMLEN(dirent) strlen(dirent->d_name)
  18. #else
  19. #define dirent direct
  20. #define NAMLEN(dirent) ((dirent)->d_namlen)
  21. #if HAVE_SYS_NDIR_H
  22. #include <sys/ndir.h>
  23. #endif
  24. #if HAVE_SYS_DIR_H
  25. #include <sys/dir.h>
  26. #endif
  27. #if HAVE_NDIR_H
  28. #include <ndir.h>
  29. #endif
  30. #endif
  31. extern void error(const char *);
  32. static void enomem()
  33. {
  34. error("Out of memory.");
  35. }
  36. static const char defaultlang[] = HTTP11_DEFAULTLANG;
  37. /*
  38. ** Based upon Accept-Language: header, figure out which directory in
  39. ** HTMLLIBDIR matches it.
  40. */
  41. FILE *http11_open_langfile(const char *libdir, const char *subdir,
  42. const char *file)
  43. {
  44. char *p=malloc(strlen(libdir)+strlen(subdir)+strlen(file)+3);
  45. FILE *fp;
  46. if (!p) return (0);
  47. strcat(strcat(strcat(strcat(strcpy(p, libdir), "/"), subdir), "/"),
  48. file);
  49. fp=fopen(p, "r");
  50. free(p);
  51. return (fp);
  52. }
  53. /**************************************************************************/
  54. /* Parse Accept-Language: header */
  55. static size_t parse_accept_language(const char *acc_lang, char **languages,
  56. double *weights)
  57. {
  58. char *p=strdup(acc_lang ? acc_lang:"");
  59. size_t cnt=0;
  60. char *q, *r;
  61. int has_weights=0;
  62. double *save_weights=weights;
  63. if (!p) enomem();
  64. for (q=p; (q=strtok(q, ", ")) != 0; q=0)
  65. {
  66. if (languages)
  67. {
  68. q=strdup(q);
  69. if (!q) enomem();
  70. *languages++=q;
  71. }
  72. if (weights) *weights=1; /* Until further notice */
  73. for (r=q; *r; r++)
  74. *r=tolower(*r);
  75. if ((r=strchr(q, ':')) != 0)
  76. {
  77. *r++=0;
  78. if (*r == 'q' && r[1] == '=')
  79. {
  80. double weight=atof(r+2);
  81. if (weights) *weights=weight;
  82. has_weights=1;
  83. }
  84. }
  85. if (weights) ++weights;
  86. ++cnt;
  87. }
  88. free(p);
  89. if (!has_weights && weights)
  90. {
  91. size_t i;
  92. double weight=1;
  93. /*
  94. ** Broken HTTP/1.1 clients do not specify quality factors, and expect
  95. ** the server to pick the first one on the list
  96. */
  97. for (i=cnt; i; )
  98. {
  99. --i;
  100. save_weights[i]=weight;
  101. weight = weight + 1;
  102. }
  103. }
  104. return (cnt);
  105. }
  106. char *http11_best_content_language(const char *libdir, const char *acc_lang)
  107. {
  108. size_t naccept=parse_accept_language(acc_lang, 0, 0);
  109. char **languages=malloc(naccept ? sizeof(char *)*naccept:1);
  110. double *weights=malloc(naccept ? sizeof(double)*naccept:1);
  111. DIR *p;
  112. struct dirent *de;
  113. size_t i;
  114. double missweight=1;
  115. char *bestlang=0;
  116. double bestweight=0;
  117. int found_nondefault_match=0;
  118. if (!languages || !weights)
  119. {
  120. if (languages) free(languages);
  121. if (weights) free(weights);
  122. enomem();
  123. }
  124. (void)parse_accept_language(acc_lang, languages, weights);
  125. for (i=0; i<naccept; i++)
  126. if (strcmp(languages[i], "*") == 0) missweight=weights[i];
  127. /* Default weight */
  128. p=opendir(libdir);
  129. while (p && (de=readdir(p)) != 0)
  130. {
  131. FILE *fp;
  132. if (*de->d_name == '.') continue;
  133. if ((fp=http11_open_langfile(libdir, de->d_name, "LOCALE"))
  134. != 0)
  135. {
  136. #if 0
  137. double myweight=missweight;
  138. #else
  139. double  myweight=0;
  140. #endif
  141. fclose(fp);
  142. for (i=0; i<naccept; i++)
  143. if (strcmp(languages[i], de->d_name) == 0)
  144. {
  145. myweight=weights[i];
  146. break;
  147. }
  148. if (!bestlang || myweight > bestweight)
  149. {
  150. if (bestlang) free(bestlang);
  151. bestlang=strdup(de->d_name);
  152. if (!bestlang) enomem();
  153. bestweight=myweight;
  154. if (i < naccept)
  155. found_nondefault_match=1;
  156. }
  157. }
  158. }
  159. if (p) closedir(p);
  160. if (!bestlang || !found_nondefault_match)
  161. {
  162. if (bestlang) free(bestlang);
  163. if ((bestlang=malloc(sizeof(defaultlang))) == 0) enomem();
  164. strcpy(bestlang, defaultlang);
  165. }
  166. for (i=0; i<naccept; i++)
  167. free(languages[i]);
  168. free(languages);
  169. free(weights);
  170. return (bestlang);
  171. }
  172. static const char *get_http11(const char *libdir, const char *subdir,
  173. char *buf,
  174. const char *file, const char *def)
  175. {
  176. FILE *fp=http11_open_langfile(libdir, subdir, file);
  177. if (fp != 0)
  178. {
  179. size_t n=fread(buf, 1, 79, fp);
  180. if (n <= 0) n=0;
  181. buf[n]=0;
  182. fclose(fp);
  183. return (strtok(buf, "rn"));
  184. }
  185. return (def);
  186. }
  187. const char *http11_content_language(const char *libdir, const char *acc_lang)
  188. {
  189. static char buf[80];
  190. return (get_http11(libdir, acc_lang, buf, "LANGUAGE", defaultlang));
  191. }
  192. const char *http11_content_locale(const char *libdir, const char *acc_lang)
  193. {
  194. static char buf[80];
  195. const char *p=get_http11(libdir, acc_lang, buf, "LOCALE", "C");
  196. return (p);
  197. }
  198. const char *http11_content_ispelldict(const char *libdir, const char *acc_lang)
  199. {
  200. static char buf[80];
  201. return (get_http11(libdir, acc_lang, buf, "ISPELLDICT", defaultlang));
  202. }
  203. const char *http11_content_charset(const char *libdir, const char *acc_lang)
  204. {
  205. static char buf[80];
  206. return (get_http11(libdir, acc_lang, buf, "CHARSET", RFC2045CHARSET));
  207. }