acclanglist.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include <stdlib.h>
  45. #include "i18n.h"
  46. /*
  47. * Accept-Language = "Accept-Language" ":"
  48. * 1#( language-range [ ";" "q" "=" qvalue ] )
  49. * language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" )
  50. *
  51. * NLS_AccLangList() assumes that "Accept-Language:" has already
  52. * been stripped off. It takes as input
  53. *
  54. * 1#( ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) [ ";" "q" "=" qvalue ] )
  55. *
  56. * and returns a list of languages, ordered by qvalues, in
  57. * the array NLS_ACCEPT_LANGUAGE_LIST.
  58. *
  59. * If there are to many languages (>NLS_MAX_ACCEPT_LANGUAGE) the excess
  60. * is ignored. If the language-range is too long (>NLS_MAX_ACCEPT_LENGTH),
  61. * the language-range is ignored. In these cases, NLS_AccLangList()
  62. * will quietly return, perhaps with numLang = 0. numLang is
  63. * returned by the function.
  64. */
  65. static size_t
  66. AcceptLangList(const char* AcceptLanguage,
  67. ACCEPT_LANGUAGE_LIST AcceptLanguageList)
  68. {
  69. char* input;
  70. char* cPtr;
  71. char* cPtr1;
  72. char* cPtr2;
  73. int i;
  74. int j;
  75. int countLang = 0;
  76. input = strdup(AcceptLanguage);
  77. if (input == (char*)NULL){
  78. return 0;
  79. }
  80. cPtr1 = input-1;
  81. cPtr2 = input;
  82. /* put in standard form */
  83. while (*(++cPtr1)) {
  84. if (isalpha(*cPtr1)) *cPtr2++ = tolower(*cPtr1); /* force lower case */
  85. else if (isspace(*cPtr1)); /* ignore any space */
  86. else if (*cPtr1=='-') *cPtr2++ = '_'; /* "-" -> "_" */
  87. else if (*cPtr1=='*'); /* ignore "*" */
  88. else *cPtr2++ = *cPtr1; /* else unchanged */
  89. }
  90. *cPtr2 = '\0';
  91. countLang = 0;
  92. if (strchr(input,';')) {
  93. /* deal with the quality values */
  94. float qvalue[MAX_ACCEPT_LANGUAGE];
  95. float qSwap;
  96. float bias = 0.0f;
  97. char* ptrLanguage[MAX_ACCEPT_LANGUAGE];
  98. char* ptrSwap;
  99. cPtr = strtok(input,",");
  100. while (cPtr) {
  101. qvalue[countLang] = 1.0f;
  102. if ((cPtr1 = strchr(cPtr,';'))) {
  103. sscanf(cPtr1,";q=%f",&qvalue[countLang]);
  104. *cPtr1 = '\0';
  105. }
  106. if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */
  107. qvalue[countLang] -= (bias += 0.0001f); /* to insure original order */
  108. ptrLanguage[countLang++] = cPtr;
  109. if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
  110. }
  111. cPtr = strtok(NULL,",");
  112. }
  113. /* sort according to decending qvalue */
  114. /* not a very good algorithm, but count is not likely large */
  115. for ( i=0 ; i<countLang-1 ; i++ ) {
  116. for ( j=i+1 ; j<countLang ; j++ ) {
  117. if (qvalue[i]<qvalue[j]) {
  118. qSwap = qvalue[i];
  119. qvalue[i] = qvalue[j];
  120. qvalue[j] = qSwap;
  121. ptrSwap = ptrLanguage[i];
  122. ptrLanguage[i] = ptrLanguage[j];
  123. ptrLanguage[j] = ptrSwap;
  124. }
  125. }
  126. }
  127. for ( i=0 ; i<countLang ; i++ ) {
  128. strcpy(AcceptLanguageList[i],ptrLanguage[i]);
  129. }
  130. } else {
  131. /* simple case: no quality values */
  132. cPtr = strtok(input,",");
  133. while (cPtr) {
  134. if (strlen(cPtr)<MAX_ACCEPT_LENGTH) { /* ignore if too long */
  135. strcpy(AcceptLanguageList[countLang++],cPtr);
  136. if (countLang>=MAX_ACCEPT_LANGUAGE) break; /* quit if too many */
  137. }
  138. cPtr = strtok(NULL,",");
  139. }
  140. }
  141. free(input);
  142. return countLang;
  143. }
  144. /*
  145. * Get prioritized locale list from NLS_AcceptLangList
  146. *
  147. * Add additonal language to the list for fallback if locale
  148. * name is language_region
  149. *
  150. */
  151. int
  152. XP_AccLangList(char* AcceptLanguage,
  153. ACCEPT_LANGUAGE_LIST AcceptLanguageList)
  154. {
  155. int i;
  156. int n;
  157. char *defaultLanguage = "en";
  158. ACCEPT_LANGUAGE_LIST curLanguageList;
  159. int index = 0;
  160. char lang[3];
  161. int k;
  162. n = AcceptLangList(AcceptLanguage, curLanguageList);
  163. if (n == 0)
  164. return 0;
  165. memset(lang, 0, 3);
  166. for (i = 0; i < n; i++) {
  167. if (*lang && (strncmp(lang, curLanguageList[i], 2) != 0)) {
  168. /* add lang if current language is the last occurence in the list */
  169. for (k = i+1; (k < n) && strncmp(curLanguageList[k],lang,2); k++);
  170. if (k == n) {
  171. strcpy(AcceptLanguageList[index++], lang);
  172. *lang = '\0';
  173. }
  174. }
  175. strcpy(AcceptLanguageList[index++], curLanguageList[i]);
  176. /* Add current language for future appending.,make sure it's not on list */
  177. if ((strlen(curLanguageList[i]) > 2) && (curLanguageList[i][2] == '_')) {
  178. strncpy(lang, curLanguageList[i], 2);
  179. lang[sizeof(lang)-1] = 0;
  180. for (k = 0; (k < index) && strcmp(AcceptLanguageList[k], lang); k++);
  181. if (k != index) lang[0] = '\0';
  182. }
  183. }
  184. if (lang[0] != '\0')
  185. strcpy(AcceptLanguageList[index++], lang); /* add new lang */
  186. /* Append defaultLanguage if it's not in the list */
  187. for (i = 0; (i < index) && strcmp(AcceptLanguageList[i], defaultLanguage); i++);
  188. if (i == index)
  189. strcpy(AcceptLanguageList[index++], defaultLanguage);
  190. return index;
  191. }