~ubuntu-branches/ubuntu/trusty/unrar-nonfree/trusty-security

« back to all changes in this revision

Viewing changes to consio.cpp

  • Committer: Package Import Robot
  • Author(s): Martin Meredith
  • Date: 2013-08-15 17:15:19 UTC
  • mfrom: (1.1.17) (5.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20130815171519-dk2t2lrzh952r1xi
Tags: 1:5.0.10-1
* New upstream release
* Added hardening support (Closes: #694611)
* Bumped Standards version
* Updated to debhelper 9
* Moved homepage in control file to Source Section

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#include "rar.hpp"
2
 
 
3
 
#ifndef GUI
4
2
#include "log.cpp"
5
 
#endif
6
 
 
7
 
static int KbdAnsi(char *Addr,int Size);
8
 
 
9
 
#if !defined(GUI) && !defined(SILENT)
10
 
static void RawPrint(char *Msg,MESSAGE_TYPE MessageType);
11
 
static byte GetKey();
12
 
#endif
13
3
 
14
4
static MESSAGE_TYPE MsgStream=MSG_STDOUT;
15
5
static bool Sound=false;
16
6
const int MaxMsgSize=2*NM+2048;
17
7
 
 
8
#ifdef _WIN_ALL
 
9
static bool StdoutRedirected=false,StderrRedirected=false,StdinRedirected=false;
 
10
#endif
 
11
 
 
12
 
 
13
#ifdef _WIN_ALL
 
14
static bool IsRedirected(DWORD nStdHandle)
 
15
{
 
16
  HANDLE hStd=GetStdHandle(nStdHandle);
 
17
  DWORD Mode;
 
18
  return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
 
19
}
 
20
#endif
 
21
 
 
22
 
 
23
void InitConsole()
 
24
{
 
25
#ifdef _WIN_ALL
 
26
  // We want messages like file names or progress percent to be printed
 
27
  // immediately. Use only in Windows, in Unix they can cause wprintf %ls
 
28
  // to fail with non-English strings.
 
29
  setbuf(stdout,NULL);
 
30
  setbuf(stderr,NULL);
 
31
 
 
32
  // Detect if output is redirected and set output mode properly.
 
33
  // We do not want to send Unicode output to files and especially to pipes
 
34
  // like '|more', which cannot handle them correctly in Windows.
 
35
  // In Unix console output is UTF-8 and it is handled correctly
 
36
  // when redirecting, so no need to perform any adjustments.
 
37
  StdoutRedirected=IsRedirected(STD_OUTPUT_HANDLE);
 
38
  StderrRedirected=IsRedirected(STD_ERROR_HANDLE);
 
39
  StdinRedirected=IsRedirected(STD_INPUT_HANDLE);
 
40
#ifdef _MSC_VER
 
41
  if (!StdoutRedirected)
 
42
    _setmode(_fileno(stdout), _O_U16TEXT);
 
43
  if (!StderrRedirected)
 
44
    _setmode(_fileno(stderr), _O_U16TEXT);
 
45
#endif
 
46
#endif
 
47
}
 
48
 
 
49
 
18
50
void InitConsoleOptions(MESSAGE_TYPE MsgStream,bool Sound)
19
51
{
20
52
  ::MsgStream=MsgStream;
21
53
  ::Sound=Sound;
22
54
}
23
55
 
24
 
#if !defined(GUI) && !defined(SILENT)
25
 
void mprintf(const char *fmt,...)
 
56
 
 
57
#ifndef SILENT
 
58
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
 
59
{
 
60
  // This buffer is for format string only, not for entire output,
 
61
  // so it can be short enough.
 
62
  wchar fmtw[1024];
 
63
  PrintfPrepareFmt(fmt,fmtw,ASIZE(fmtw));
 
64
#ifdef _WIN_ALL
 
65
  safebuf wchar Msg[MaxMsgSize];
 
66
  if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
 
67
  {
 
68
    // Avoid Unicode for redirect in Windows, it does not work with pipes.
 
69
    vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
 
70
    safebuf char MsgA[MaxMsgSize];
 
71
    WideToChar(Msg,MsgA,ASIZE(MsgA));
 
72
    CharToOemA(MsgA,MsgA); // Console tools like 'more' expect OEM encoding.
 
73
 
 
74
    // We already converted \n to \r\n above, so we use WriteFile instead
 
75
    // of C library to avoid unnecessary additional conversion.
 
76
    HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
 
77
    DWORD Written;
 
78
    WriteFile(hOut,MsgA,(DWORD)strlen(MsgA),&Written,NULL);
 
79
    return;
 
80
  }
 
81
  // MSVC2008 vfwprintf writes every character to console separately
 
82
  // and it is too slow. We use direct WriteConsole call instead.
 
83
  vswprintf(Msg,ASIZE(Msg),fmtw,arglist);
 
84
  HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
 
85
  DWORD Written;
 
86
  WriteConsole(hOut,Msg,(DWORD)wcslen(Msg),&Written,NULL);
 
87
#else
 
88
  vfwprintf(dest,fmtw,arglist);
 
89
  // We do not use setbuf(NULL) in Unix (see comments in InitConsole).
 
90
  fflush(dest);
 
91
#endif
 
92
}
 
93
 
 
94
 
 
95
void mprintf(const wchar *fmt,...)
26
96
{
27
97
  if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
28
98
    return;
29
 
  char Msg[MaxMsgSize];
30
 
  va_list argptr;
31
 
  va_start(argptr,fmt);
32
 
  vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
33
 
 
34
 
  // Different vsnprintf implementation can return either -1 or >=MaxMsgSize
35
 
  // if string is truncated. So we do not check exit code and always zero
36
 
  // terminate the string for safety. It is faster than check for error.
37
 
  Msg[ASIZE(Msg)-1] = 0;
38
 
 
39
 
  RawPrint(Msg,MsgStream);
40
 
  va_end(argptr);
 
99
 
 
100
  fflush(stderr); // Ensure proper message order.
 
101
 
 
102
  va_list arglist;
 
103
  va_start(arglist,fmt);
 
104
  FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
 
105
  cvt_wprintf(dest,fmt,arglist);
 
106
  va_end(arglist);
41
107
}
42
108
#endif
43
109
 
44
110
 
45
 
#if !defined(GUI) && !defined(SILENT)
46
 
void eprintf(const char *fmt,...)
 
111
#ifndef SILENT
 
112
void eprintf(const wchar *fmt,...)
47
113
{
48
114
  if (MsgStream==MSG_NULL)
49
115
    return;
50
 
  safebuf char Msg[MaxMsgSize];
51
 
  va_list argptr;
52
 
  va_start(argptr,fmt);
53
 
  vsnprintf(Msg,ASIZE(Msg),fmt,argptr);
54
 
 
55
 
  // Different vsnprintf implementation can return either -1 or >=MaxMsgSize
56
 
  // if string is truncated. So we do not check exit code and always zero
57
 
  // terminate the string for safety. It is faster than check for error.
58
 
  Msg[ASIZE(Msg)-1] = 0;
59
 
 
60
 
  RawPrint(Msg,MSG_STDERR);
61
 
  va_end(argptr);
62
 
}
63
 
#endif
64
 
 
65
 
 
66
 
#if !defined(GUI) && !defined(SILENT)
67
 
void RawPrint(char *Msg,MESSAGE_TYPE MessageType)
68
 
{
69
 
  File OutFile;
70
 
  switch(MessageType)
71
 
  {
72
 
    case MSG_STDOUT:
73
 
      OutFile.SetHandleType(FILE_HANDLESTD);
74
 
      break;
75
 
    case MSG_STDERR:
76
 
    case MSG_ERRONLY:
77
 
      OutFile.SetHandleType(FILE_HANDLEERR);
78
 
      break;
79
 
    default:
80
 
      return;
81
 
  }
82
 
#ifdef _WIN_ALL
83
 
  CharToOemA(Msg,Msg);
84
 
 
85
 
  char OutMsg[MaxMsgSize];
86
 
  size_t OutPos=0;
87
 
  for (size_t I=0;Msg[I]!=0;I++)
88
 
  {
89
 
    if (Msg[I]=='\n' && (I==0 || Msg[I-1]!='\r') && OutPos<ASIZE(OutMsg)-1)
90
 
      OutMsg[OutPos++]='\r';
91
 
    if (OutPos<ASIZE(OutMsg)-1)
92
 
      OutMsg[OutPos++]=Msg[I];
93
 
  }
94
 
  OutMsg[OutPos]=0;
95
 
  strcpy(Msg,OutMsg);
96
 
#endif
97
 
#if defined(_UNIX) || defined(_EMX)
98
 
  char OutMsg[MaxMsgSize],*OutPos=OutMsg;
99
 
  for (size_t I=0;Msg[I]!=0;I++)
100
 
    if (Msg[I]!='\r')
101
 
      *(OutPos++)=Msg[I];
102
 
  *OutPos=0;
103
 
  strcpy(Msg,OutMsg);
104
 
#endif
105
 
 
106
 
  OutFile.Write(Msg,strlen(Msg));
 
116
 
 
117
  fflush(stdout); // Ensure proper message order.
 
118
 
 
119
  va_list arglist;
 
120
  va_start(arglist,fmt);
 
121
  cvt_wprintf(stderr,fmt,arglist);
 
122
  va_end(arglist);
107
123
}
108
124
#endif
109
125
 
111
127
#ifndef SILENT
112
128
void Alarm()
113
129
{
114
 
#ifndef SFX_MODULE
115
130
  if (Sound)
116
 
    putchar('\007');
 
131
  {
 
132
    static clock_t LastTime=clock();
 
133
    if ((clock()-LastTime)/CLOCKS_PER_SEC>5)
 
134
    {
 
135
#ifdef _WIN_ALL
 
136
      MessageBeep(-1);
 
137
#else
 
138
      putwchar('\007');
117
139
#endif
 
140
    }
 
141
  }
118
142
}
119
143
#endif
120
144
 
121
145
 
122
146
#ifndef SILENT
123
 
#ifndef GUI
124
 
void GetPasswordText(wchar *Str,uint MaxLength)
 
147
static void GetPasswordText(wchar *Str,uint MaxLength)
125
148
{
126
149
  if (MaxLength==0)
127
150
    return;
135
158
  SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
136
159
  SetConsoleMode(hConOut,ENABLE_PROCESSED_OUTPUT|ENABLE_WRAP_AT_EOL_OUTPUT);
137
160
 
138
 
  ReadConsoleW(hConIn,Str,MaxLength-1,&Read,NULL);
 
161
  ReadConsole(hConIn,Str,MaxLength-1,&Read,NULL);
139
162
  Str[Read]=0;
140
163
  SetConsoleMode(hConIn,ConInMode);
141
164
  SetConsoleMode(hConOut,ConOutMode);
142
165
#else
143
166
  char StrA[MAXPASSWORD];
144
 
#if defined(_EMX) || defined(_BEOS) || defined(__sparc) || defined(sparc) || defined (__VMS)
 
167
#if defined(_EMX) || defined (__VMS)
145
168
  fgets(StrA,ASIZE(StrA)-1,stdin);
 
169
#elif defined(__sun)
 
170
  strncpyz(StrA,getpassphrase(""),ASIZE(StrA));
146
171
#else
147
172
  strncpyz(StrA,getpass(""),ASIZE(StrA));
148
173
#endif
153
178
  RemoveLF(Str);
154
179
}
155
180
#endif
156
 
#endif
157
181
 
158
182
 
159
183
#ifndef SILENT
160
 
bool GetPassword(PASSWORD_TYPE Type,const char *FileName,const wchar *FileNameW,
161
 
                 SecPassword *Password)
 
184
bool GetConsolePassword(PASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
162
185
{
163
186
  Alarm();
 
187
  
164
188
  while (true)
165
189
  {
166
 
    char PromptStr[NM+256];
167
 
#if defined(_EMX) || defined(_BEOS)
168
 
    strcpy(PromptStr,St(MAskPswEcho));
169
 
#else
170
 
    strcpy(PromptStr,St(MAskPsw));
171
 
#endif
172
 
    if (Type!=PASSWORD_GLOBAL)
173
 
    {
174
 
      strcat(PromptStr,St(MFor));
175
 
      char *NameOnly=PointToName(FileName);
176
 
      if (strlen(PromptStr)+strlen(NameOnly)<ASIZE(PromptStr))
177
 
        strcat(PromptStr,NameOnly);
178
 
    }
179
 
    eprintf("\n%s: ",PromptStr);
 
190
    if (Type==PASSWORD_GLOBAL)
 
191
      eprintf(L"\n%s: ",St(MAskPsw));
 
192
    else
 
193
      eprintf(St(MAskPswFor),FileName);
180
194
 
181
195
    wchar PlainPsw[MAXPASSWORD];
182
196
    GetPasswordText(PlainPsw,ASIZE(PlainPsw));
183
197
    if (*PlainPsw==0 && Type==PASSWORD_GLOBAL)
184
 
      return(false);
 
198
      return false;
185
199
    if (Type==PASSWORD_GLOBAL)
186
200
    {
187
201
      eprintf(St(MReAskPsw));
200
214
    cleandata(PlainPsw,sizeof(PlainPsw));
201
215
    break;
202
216
  }
203
 
  return(true);
 
217
  return true;
204
218
}
205
219
#endif
206
220
 
207
221
 
208
 
#if !defined(GUI) && !defined(SILENT)
209
 
byte GetKey()
 
222
#ifndef SILENT
 
223
bool getwstr(wchar *str,size_t n)
210
224
{
211
 
  char Str[80];
212
 
  bool EndOfFile;
213
 
#if defined(__GNUC__) || defined(sun)
214
 
  EndOfFile=(fgets(Str,sizeof(Str),stdin)==NULL);
 
225
  // Print buffered prompt title function before waiting for input.
 
226
  fflush(stderr);
 
227
 
 
228
  *str=0;
 
229
#if defined(_WIN_ALL)
 
230
  // fgetws does not work well with non-English text in Windows,
 
231
  // so we do not use it.
 
232
  if (StdinRedirected) // ReadConsole does not work if redirected.
 
233
  {
 
234
    // fgets does not work well with pipes in Windows in our test.
 
235
    // Let's use files.
 
236
    Array<char> StrA(n*4); // Up to 4 UTF-8 characters per wchar_t.
 
237
    File SrcFile;
 
238
    SrcFile.SetHandleType(FILE_HANDLESTD);
 
239
    int ReadSize=SrcFile.Read(&StrA[0],StrA.Size()-1);
 
240
    if (ReadSize<=0)
 
241
    {
 
242
      // Looks like stdin is a null device. We can enter to infinite loop
 
243
      // calling Ask(), so let's better exit.
 
244
      ErrHandler.Exit(RARX_USERBREAK);
 
245
    }
 
246
    StrA[ReadSize-1]=0;
 
247
    CharToWide(&StrA[0],str,n);
 
248
  }
 
249
  else
 
250
  {
 
251
    DWORD ReadSize=0;
 
252
    if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),str,DWORD(n-1),&ReadSize,NULL)==0)
 
253
      return false;
 
254
    str[ReadSize]=0;
 
255
  }
215
256
#else
216
 
  File SrcFile;
217
 
  SrcFile.SetHandleType(FILE_HANDLESTD);
218
 
  EndOfFile=(SrcFile.Read(Str,sizeof(Str))==0);
 
257
  if (fgetws(str,n,stdin)==NULL)
 
258
    ErrHandler.Exit(RARX_USERBREAK); // Avoid infinite Ask() loop.
219
259
#endif
220
 
  if (EndOfFile)
221
 
  {
222
 
    // Looks like stdin is a null device. We can enter to infinite loop
223
 
    // calling Ask(), so let's better exit.
224
 
    ErrHandler.Exit(RARX_USERBREAK);
225
 
  }
226
 
  return (byte)Str[0];
 
260
  RemoveLF(str);
 
261
  return true;
227
262
}
228
263
#endif
229
264
 
230
265
 
231
 
#if !defined(GUI) && !defined(SILENT)
232
 
int Ask(const char *AskStr)
 
266
#ifndef SILENT
 
267
int Ask(const wchar *AskStr)
233
268
{
 
269
  Alarm();
 
270
 
234
271
  const int MaxItems=10;
235
 
  char Item[MaxItems][40];
 
272
  wchar Item[MaxItems][40];
236
273
  int ItemKeyPos[MaxItems],NumItems=0;
237
274
 
238
 
  for (const char *NextItem=AskStr;NextItem!=NULL;NextItem=strchr(NextItem+1,'_'))
 
275
  for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
239
276
  {
240
 
    char *CurItem=Item[NumItems];
241
 
    strncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
242
 
    char *EndItem=strchr(CurItem,'_');
 
277
    wchar *CurItem=Item[NumItems];
 
278
    wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
 
279
    wchar *EndItem=wcschr(CurItem,'_');
243
280
    if (EndItem!=NULL)
244
281
      *EndItem=0;
245
282
    int KeyPos=0,CurKey;
247
284
    {
248
285
      bool Found=false;
249
286
      for (int I=0;I<NumItems && !Found;I++)
250
 
        if (loctoupper(Item[I][ItemKeyPos[I]])==loctoupper(CurKey))
 
287
        if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
251
288
          Found=true;
252
289
      if (!Found && CurKey!=' ')
253
290
        break;
259
296
 
260
297
  for (int I=0;I<NumItems;I++)
261
298
  {
262
 
    eprintf(I==0 ? (NumItems>4 ? "\n":" "):", ");
 
299
    eprintf(I==0 ? (NumItems>4 ? L"\n":L" "):L", ");
263
300
    int KeyPos=ItemKeyPos[I];
264
301
    for (int J=0;J<KeyPos;J++)
265
 
      eprintf("%c",Item[I][J]);
266
 
    eprintf("[%c]%s",Item[I][KeyPos],&Item[I][KeyPos+1]);
 
302
      eprintf(L"%c",Item[I][J]);
 
303
    eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
267
304
  }
268
 
  eprintf(" ");
269
 
  byte Ch=GetKey();
270
 
#if defined(_WIN_ALL)
271
 
  OemToCharBuffA((LPCSTR)&Ch,(LPSTR)&Ch,1);
272
 
#endif
273
 
  Ch=loctoupper(Ch);
 
305
  eprintf(L" ");
 
306
  wchar Str[50];
 
307
  getwstr(Str,ASIZE(Str));
 
308
  wchar Ch=toupperw(Str[0]);
274
309
  for (int I=0;I<NumItems;I++)
275
 
    if (Ch==(byte)Item[I][ItemKeyPos[I]])
276
 
      return(I+1);
277
 
  return(0);
 
310
    if (Ch==Item[I][ItemKeyPos[I]])
 
311
      return I+1;
 
312
  return 0;
278
313
}
279
314
#endif
280
315
 
281
316
 
282
 
int KbdAnsi(char *Addr,size_t Size)
 
317
static bool IsCommentUnsafe(const wchar *Data,size_t Size)
283
318
{
284
 
  int RetCode=0;
285
 
#ifndef GUI
286
319
  for (size_t I=0;I<Size;I++)
287
 
    if (Addr[I]==27 && Addr[I+1]=='[')
288
 
    {
 
320
    if (Data[I]==27 && Data[I+1]=='[')
289
321
      for (size_t J=I+2;J<Size;J++)
290
322
      {
291
 
        if (Addr[J]=='\"')
292
 
          return(2);
293
 
        if (!IsDigit(Addr[J]) && Addr[J]!=';')
 
323
        // Return true for <ESC>[{key};"{string}"p used to redefine
 
324
        // a keyboard key on some terminals.
 
325
        if (Data[J]=='\"')
 
326
          return true;
 
327
        if (!IsDigit(Data[J]) && Data[J]!=';')
294
328
          break;
295
329
      }
296
 
      RetCode=1;
297
 
    }
298
 
#endif
299
 
  return(RetCode);
 
330
  return false;
300
331
}
301
332
 
302
333
 
303
 
void OutComment(char *Comment,size_t Size)
 
334
void OutComment(const wchar *Comment,size_t Size)
304
335
{
305
 
#ifndef GUI
306
 
  if (KbdAnsi(Comment,Size)==2)
 
336
  if (IsCommentUnsafe(Comment,Size))
307
337
    return;
308
338
  const size_t MaxOutSize=0x400;
309
339
  for (size_t I=0;I<Size;I+=MaxOutSize)
310
340
  {
311
 
    char Msg[MaxOutSize+1];
 
341
    wchar Msg[MaxOutSize+1];
312
342
    size_t CopySize=Min(MaxOutSize,Size-I);
313
 
    strncpy(Msg,Comment+I,CopySize);
 
343
    wcsncpy(Msg,Comment+I,CopySize);
314
344
    Msg[CopySize]=0;
315
 
    mprintf("%s",Msg);
 
345
    mprintf(L"%s",Msg);
316
346
  }
317
 
  mprintf("\n");
318
 
#endif
 
347
  mprintf(L"\n");
319
348
}