filestr.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #include "rar.hpp"
  2. static bool IsUnicode(byte *Data,int Size);
  3. bool ReadTextFile(
  4. const char *Name,
  5. const wchar *NameW,
  6. StringList *List,
  7. bool Config,
  8. bool AbortOnError,
  9. RAR_CHARSET SrcCharset,
  10. bool Unquote,
  11. bool SkipComments,
  12. bool ExpandEnvStr)
  13. {
  14. char FileName[NM];
  15. *FileName=0;
  16. if (Name!=NULL)
  17. if (Config)
  18. GetConfigName(Name,FileName,true);
  19. else
  20. strcpy(FileName,Name);
  21. wchar FileNameW[NM];
  22. *FileNameW=0;
  23. #ifdef _WIN_ALL
  24. if (NameW!=NULL)
  25. if (Config)
  26. GetConfigName(NameW,FileNameW,true);
  27. else
  28. wcscpy(FileNameW,NameW);
  29. #endif
  30. File SrcFile;
  31. if (FileName!=NULL && *FileName!=0 || FileNameW!=NULL && *FileNameW!=0)
  32. {
  33. bool OpenCode=AbortOnError ? SrcFile.WOpen(FileName,FileNameW):SrcFile.Open(FileName,FileNameW);
  34. if (!OpenCode)
  35. {
  36. if (AbortOnError)
  37. ErrHandler.Exit(OPEN_ERROR);
  38. return(false);
  39. }
  40. }
  41. else
  42. SrcFile.SetHandleType(FILE_HANDLESTD);
  43. unsigned int DataSize=0,ReadSize;
  44. const int ReadBlock=1024;
  45. Array<char> Data(ReadBlock+5);
  46. while ((ReadSize=SrcFile.Read(&Data[DataSize],ReadBlock))!=0)
  47. {
  48. DataSize+=ReadSize;
  49. Data.Add(ReadSize);
  50. }
  51. memset(&Data[DataSize],0,5);
  52. if (SrcCharset==RCH_UNICODE ||
  53. SrcCharset==RCH_DEFAULT && IsUnicode((byte *)&Data[0],DataSize))
  54. {
  55. // Unicode in native system format, can be more than 2 bytes per character.
  56. Array<wchar> DataW(Data.Size()/2+1);
  57. for (size_t I=2;I<Data.Size()-1;I+=2)
  58. {
  59. // Need to convert Data to (byte) first to prevent the sign extension
  60. // to higher bytes.
  61. DataW[(I-2)/2]=(wchar)((byte)Data[I])+(wchar)((byte)Data[I+1])*256;
  62. }
  63. wchar *CurStr=&DataW[0];
  64. Array<char> AnsiName;
  65. while (*CurStr!=0)
  66. {
  67. wchar *NextStr=CurStr,*CmtPtr=NULL;
  68. while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
  69. {
  70. if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
  71. {
  72. *NextStr=0;
  73. CmtPtr=NextStr;
  74. }
  75. NextStr++;
  76. }
  77. *NextStr=0;
  78. for (wchar *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
  79. {
  80. if (*SpacePtr!=' ' && *SpacePtr!='\t')
  81. break;
  82. *SpacePtr=0;
  83. }
  84. if (*CurStr)
  85. {
  86. // Length and AddSize must be defined as signed, because AddSize
  87. // can be negative.
  88. int Length=(int)wcslen(CurStr);
  89. int AddSize=4*(Length-(int)AnsiName.Size()+1);
  90. if (AddSize>0)
  91. AnsiName.Add(AddSize);
  92. if (Unquote && *CurStr=='\"' && CurStr[Length-1]=='\"')
  93. {
  94. CurStr[Length-1]=0;
  95. CurStr++;
  96. }
  97. WideToChar(CurStr,&AnsiName[0],AnsiName.Size());
  98. bool Expanded=false;
  99. #if defined(_WIN_ALL) && !defined(_WIN_CE)
  100. if (ExpandEnvStr && *CurStr=='%')
  101. {
  102. // Expanding environment variables in Windows version.
  103. char ExpName[NM];
  104. wchar ExpNameW[NM];
  105. *ExpNameW=0;
  106. int ret,retw=1;
  107. ret=ExpandEnvironmentStringsA(&AnsiName[0],ExpName,ASIZE(ExpName));
  108. if (ret!=0 && WinNT())
  109. retw=ExpandEnvironmentStringsW(CurStr,ExpNameW,ASIZE(ExpNameW));
  110. Expanded=ret!=0 && ret<ASIZE(ExpName) &&
  111. retw!=0 && retw<ASIZE(ExpNameW);
  112. if (Expanded)
  113. List->AddString(ExpName,ExpNameW);
  114. }
  115. #endif
  116. if (!Expanded)
  117. List->AddString(&AnsiName[0],CurStr);
  118. }
  119. CurStr=NextStr+1;
  120. while (*CurStr=='\r' || *CurStr=='\n')
  121. CurStr++;
  122. }
  123. }
  124. else
  125. {
  126. char *CurStr=&Data[0];
  127. while (*CurStr!=0)
  128. {
  129. char *NextStr=CurStr,*CmtPtr=NULL;
  130. while (*NextStr!='\r' && *NextStr!='\n' && *NextStr!=0)
  131. {
  132. if (SkipComments && NextStr[0]=='/' && NextStr[1]=='/')
  133. {
  134. *NextStr=0;
  135. CmtPtr=NextStr;
  136. }
  137. NextStr++;
  138. }
  139. *NextStr=0;
  140. for (char *SpacePtr=(CmtPtr ? CmtPtr:NextStr)-1;SpacePtr>=CurStr;SpacePtr--)
  141. {
  142. if (*SpacePtr!=' ' && *SpacePtr!='\t')
  143. break;
  144. *SpacePtr=0;
  145. }
  146. if (*CurStr)
  147. {
  148. if (Unquote && *CurStr=='\"')
  149. {
  150. size_t Length=strlen(CurStr);
  151. if (CurStr[Length-1]=='\"')
  152. {
  153. CurStr[Length-1]=0;
  154. CurStr++;
  155. }
  156. }
  157. #if defined(_WIN_ALL)
  158. if (SrcCharset==RCH_OEM)
  159. OemToCharA(CurStr,CurStr);
  160. #endif
  161. bool Expanded=false;
  162. #if defined(_WIN_ALL) && !defined(_WIN_CE)
  163. if (ExpandEnvStr && *CurStr=='%')
  164. {
  165. // Expanding environment variables in Windows version.
  166. char ExpName[NM];
  167. int ret=ExpandEnvironmentStringsA(CurStr,ExpName,ASIZE(ExpName));
  168. Expanded=ret!=0 && ret<ASIZE(ExpName);
  169. if (Expanded)
  170. List->AddString(ExpName);
  171. }
  172. #endif
  173. if (!Expanded)
  174. List->AddString(CurStr);
  175. }
  176. CurStr=NextStr+1;
  177. while (*CurStr=='\r' || *CurStr=='\n')
  178. CurStr++;
  179. }
  180. }
  181. return(true);
  182. }
  183. bool IsUnicode(byte *Data,int Size)
  184. {
  185. if (Size<4 || Data[0]!=0xff || Data[1]!=0xfe)
  186. return(false);
  187. for (int I=2;I<Size;I++)
  188. if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n')
  189. return(true);
  190. return(false);
  191. }