getlang.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright 2001 Sun Microsystems, Inc.
  3. * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
  4. * All rights reserved.
  5. * END COPYRIGHT BLOCK **/
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include "libadmin/libadmin.h"
  12. #include "i18n.h"
  13. /*********************************************************************
  14. strReplace replaces the first instance of from in target with to.
  15. from can be "": to is inserted at start of target.
  16. to can be "": from is removed from target.
  17. if from is not found, 0 is returned; else 1 is returned.
  18. *********************************************************************/
  19. static int
  20. strReplace(char* target,char* from,char* to)
  21. {
  22. /* replace /from/to/ in target */
  23. char* pFrom;
  24. char* pOldTail;
  25. int lenTo;
  26. pFrom = strstr(target,from);
  27. if (pFrom) {
  28. pOldTail = pFrom+strlen(from);
  29. lenTo = strlen(to);
  30. memmove(pFrom+lenTo,pOldTail,strlen(pOldTail)+1);
  31. memcpy(pFrom,to,lenTo);
  32. return 1;
  33. }
  34. return 0;
  35. }
  36. /*********************************************************************
  37. statFileDir is a wrapper to stat() that strips trailing slashes
  38. because stat() on Windows seems to return -1 otherwise.
  39. *********************************************************************/
  40. int
  41. statFileDir(const char *path, struct stat *info) {
  42. int ret, pathlen;
  43. char *newpath = strdup(path);
  44. if(newpath == NULL)
  45. return -1;
  46. for (pathlen = (strlen(newpath) - 1); pathlen >= 0; pathlen--) {
  47. if (newpath[pathlen] == '/' || newpath[pathlen] == '\\') {
  48. newpath[pathlen] = '\0';
  49. } else {
  50. break;
  51. }
  52. }
  53. ret = stat(newpath, info);
  54. if (newpath)
  55. free(newpath);
  56. return ret;
  57. }
  58. /*********************************************************************
  59. GetLanguage is reserved for future use. These APIs are not belong
  60. to this file. It needs to be moved to somewhere which knows what's
  61. the current language setting.
  62. *********************************************************************/
  63. static char emptyString[] = "";
  64. static char client_language[128] = "en";
  65. static char admin_language[128] = "en";
  66. static char default_language[128] = "en";
  67. void
  68. SetLanguage(int type, char *language)
  69. {
  70. switch(type) {
  71. case CLIENT_LANGUAGE:
  72. if (language)
  73. strcpy(client_language, language);
  74. break;
  75. case ADMIN_LANGUAGE:
  76. if (language)
  77. strcpy(admin_language, language);
  78. break;
  79. case DEFAULT_LANGUAGE:
  80. if (language)
  81. strcpy(default_language, language);
  82. break;
  83. }
  84. return ;
  85. }
  86. char*
  87. GetClientLanguage(void)
  88. {
  89. if (client_language)
  90. return client_language;
  91. else
  92. return emptyString;
  93. }
  94. char*
  95. GetAdminLanguage(void)
  96. {
  97. if (admin_language)
  98. return admin_language;
  99. else
  100. return emptyString;
  101. }
  102. char*
  103. GetDefaultLanguage(void)
  104. {
  105. if (default_language)
  106. return default_language;
  107. else
  108. return "en";
  109. }
  110. /*********************************************************************
  111. GetFileForLanguage looks for a file in the appropriate language.
  112. *********************************************************************/
  113. NSAPI_PUBLIC
  114. int
  115. GetFileForLanguage(char* filePath,char* language,char* existingFilePath)
  116. {
  117. /* Input: filePath,language
  118. * filePath is of the form "/xxx/xxx/$$LANGDIR/xxx/xxx/filename"
  119. * or of the form "/xxx/xxx/xxx/xxx/filename".
  120. * filename may or may not have an extension.
  121. * language is an Accept-Language list; each language-range will be
  122. * tried as a subdirectory name and possibly as a filename modifier.
  123. * "*" is ignored - default always provided if needed.
  124. * "-" is replaced by "_".
  125. * $$LANGDIR is a special string replaced by language. It is optional.
  126. * For the default case, $$LANGDIR/ is replaced by nothing
  127. * (so // is not created).
  128. *
  129. * Returned: existingPath
  130. * existingFilePath is the path of a satisfactory, existing file.
  131. * if no file is found, an empty string "" is returned.
  132. *
  133. * int returned: -1 if no file found (existingFilePath = "")
  134. * 0 if default file is returned
  135. * 1 if language file is returned (any in list)
  136. *
  137. * Example:
  138. * filePath = "/path/$$LANGDIR/filename.ext"
  139. * language = "language"
  140. * GetDefaultLanguage() --> "default"
  141. * LANG_DELIMIT = "_"
  142. *
  143. * 1. Try: "/path/language/filename.ext"
  144. * 2. Try: "/path/filename_language.ext"
  145. * 3. Try: "/path/default/filename.ext"
  146. * 4. Try: "/path/filename_default.ext"
  147. * 5. Try: "/path/filename.ext"
  148. * else: ""
  149. *
  150. * Example:
  151. * language = "en-us;q=0.6,ja;q=0.8,en-ca"
  152. *
  153. * 1. Try: "/path/en-ca/filename.ext"
  154. * 2. Try: "/path/filename_en_ca.ext"
  155. * 3. Try: "/path/ja/filename.ext"
  156. * 4. Try: "/path/filename_ja.ext"
  157. * 5. Try: "/path/en_us/filename.ext"
  158. * 6. Try: "/path/filename_en_us.ext"
  159. * 7. Try: "/path/default/filename.ext"
  160. * 8. Try: "/path/filename_default.ext"
  161. * 9. Try: "/path/filename.ext"
  162. * else: ""
  163. *
  164. */
  165. #define LANG_DELIMIT '_'
  166. int pattern;
  167. char* pDot;
  168. char* pSlash;
  169. /* PRFileInfo info; */
  170. struct stat info;
  171. char lang_modifier[MAX_ACCEPT_LENGTH+1];
  172. ACCEPT_LANGUAGE_LIST acceptLanguageList;
  173. int numLang;
  174. int iLang;
  175. int iCase;
  176. /* escape in case XP_InitStringDatabase has not been called */
  177. if (filePath==NULL) {
  178. *existingFilePath = '\0';
  179. return -1;
  180. }
  181. pattern = (strstr(filePath,"$$LANGDIR/")!=NULL);
  182. for ( iCase=1 ; iCase>=0 ; iCase-- ) {
  183. if (iCase==1) { /* iCase=1 tries requested language */
  184. numLang = XP_AccLangList(language,acceptLanguageList);
  185. } else { /* iCase=0 tries default language */
  186. numLang = XP_AccLangList(GetDefaultLanguage(),acceptLanguageList);
  187. }
  188. for ( iLang=0 ; iLang<numLang ; iLang++ ) {
  189. /* Try: /path/language/filename.ext */
  190. if (pattern) {
  191. strcpy(existingFilePath,filePath);
  192. strReplace(existingFilePath,"$$LANGDIR",acceptLanguageList[iLang]);
  193. if (statFileDir(existingFilePath,&info)==0) {
  194. return iCase;
  195. }
  196. /*
  197. if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
  198. return iCase;
  199. }
  200. */
  201. }
  202. /* Try: /path/filename_language.ext */
  203. {
  204. strcpy(existingFilePath,filePath);
  205. strReplace(existingFilePath,"$$LANGDIR/",emptyString);
  206. pDot = strrchr(existingFilePath,'.');
  207. pSlash = strrchr(existingFilePath,'/');
  208. if (pSlash>=pDot) {
  209. pDot = strchr(existingFilePath,'\0');
  210. }
  211. sprintf(lang_modifier,"%c%s",LANG_DELIMIT,acceptLanguageList[iLang]);
  212. strReplace(pDot,emptyString,lang_modifier);
  213. if (statFileDir(existingFilePath,&info)==0) {
  214. return iCase;
  215. }
  216. /*
  217. if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
  218. return iCase;
  219. }
  220. */
  221. }
  222. }
  223. }
  224. /* Try: /path/filename.ext */
  225. {
  226. strcpy(existingFilePath,filePath);
  227. strReplace(existingFilePath,"$$LANGDIR/",emptyString);
  228. if (statFileDir(existingFilePath,&info)==0) {
  229. return 0;
  230. }
  231. /*
  232. if (PR_GetFileInfo(existingFilePath,&info)==PR_SUCCESS) {
  233. return 0;
  234. }
  235. */
  236. }
  237. /* Else: */
  238. *existingFilePath = '\0';
  239. return -1;
  240. }