#include "rar.hpp"
#include "log.cpp"
static MESSAGE_TYPE MsgStream= …;
static RAR_CHARSET RedirectCharset= …;
static bool ProhibitInput= …;
static bool StdoutRedirected= …,StderrRedirected= …,StdinRedirected= …;
#ifdef _WIN_ALL
static bool IsRedirected(DWORD nStdHandle)
{
HANDLE hStd=GetStdHandle(nStdHandle);
DWORD Mode;
return GetFileType(hStd)!=FILE_TYPE_CHAR || GetConsoleMode(hStd,&Mode)==0;
}
#endif
void InitConsole()
{ … }
void SetConsoleMsgStream(MESSAGE_TYPE MsgStream)
{ … }
void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset)
{ … }
void ProhibitConsoleInput()
{ … }
#ifndef SILENT
static void cvt_wprintf(FILE *dest,const wchar *fmt,va_list arglist)
{
std::wstring s=vwstrprintf(fmt,arglist);
ReplaceEsc(s);
#ifdef _WIN_ALL
if (dest==stdout && StdoutRedirected || dest==stderr && StderrRedirected)
{
HANDLE hOut=GetStdHandle(dest==stdout ? STD_OUTPUT_HANDLE:STD_ERROR_HANDLE);
DWORD Written;
if (RedirectCharset==RCH_UNICODE)
WriteFile(hOut,s.data(),(DWORD)s.size()*sizeof(s[0]),&Written,NULL);
else
{
std::string MsgA;
if (RedirectCharset==RCH_UTF8)
WideToUtf(s,MsgA);
else
WideToChar(s,MsgA);
if (RedirectCharset==RCH_DEFAULT || RedirectCharset==RCH_OEM)
CharToOemA(&MsgA[0],&MsgA[0]);
WriteFile(hOut,MsgA.data(),(DWORD)MsgA.size(),&Written,NULL);
}
return;
}
HANDLE hOut=GetStdHandle(dest==stderr ? STD_ERROR_HANDLE:STD_OUTPUT_HANDLE);
DWORD Written;
WriteConsole(hOut,s.data(),(DWORD)s.size(),&Written,NULL);
#else
fputws(s.c_str(),dest);
fflush(dest);
#endif
}
void mprintf(const wchar *fmt,...)
{
if (MsgStream==MSG_NULL || MsgStream==MSG_ERRONLY)
return;
fflush(stderr);
va_list arglist;
va_start(arglist,fmt);
FILE *dest=MsgStream==MSG_STDERR ? stderr:stdout;
cvt_wprintf(dest,fmt,arglist);
va_end(arglist);
}
#endif
#ifndef SILENT
void eprintf(const wchar *fmt,...)
{
if (MsgStream==MSG_NULL)
return;
fflush(stdout);
va_list arglist;
va_start(arglist,fmt);
cvt_wprintf(stderr,fmt,arglist);
va_end(arglist);
}
#endif
#ifndef SILENT
static void QuitIfInputProhibited()
{
if (ProhibitInput)
{
mprintf(St(MStdinNoInput));
ErrHandler.Exit(RARX_FATAL);
}
}
static void GetPasswordText(std::wstring &Str)
{
QuitIfInputProhibited();
if (StdinRedirected)
getwstr(Str);
else
{
#ifdef _WIN_ALL
HANDLE hConIn=GetStdHandle(STD_INPUT_HANDLE);
DWORD ConInMode;
GetConsoleMode(hConIn,&ConInMode);
SetConsoleMode(hConIn,ENABLE_LINE_INPUT);
std::vector<wchar> Buf(MAXPASSWORD);
DWORD Read=0;
ReadConsole(hConIn,Buf.data(),(DWORD)Buf.size()-1,&Read,NULL);
Buf[Read]=0;
Str=Buf.data();
cleandata(Buf.data(),Buf.size()*sizeof(Buf[0]));
SetConsoleMode(hConIn,ConInMode);
#else
std::vector<char> StrA(MAXPASSWORD*4);
#ifdef __VMS
fgets(StrA.data(),StrA.size()-1,stdin);
#elif defined(__sun)
strncpyz(StrA.data(),getpassphrase(""),StrA.size());
#else
strncpyz(StrA.data(),getpass(""),StrA.size());
#endif
CharToWide(StrA.data(),Str);
cleandata(StrA.data(),StrA.size()*sizeof(StrA[0]));
#endif
}
RemoveLF(Str);
}
#endif
#ifndef SILENT
bool GetConsolePassword(UIPASSWORD_TYPE Type,const std::wstring &FileName,SecPassword *Password)
{
if (!StdinRedirected)
uiAlarm(UIALARM_QUESTION);
while (true)
{
if (Type==UIPASSWORD_GLOBAL)
eprintf(L"\n%s: ",St(MAskPsw));
else
eprintf(St(MAskPswFor),FileName.c_str());
std::wstring PlainPsw;
GetPasswordText(PlainPsw);
if (PlainPsw.empty() && Type==UIPASSWORD_GLOBAL)
return false;
if (PlainPsw.size()>=MAXPASSWORD)
{
PlainPsw.erase(MAXPASSWORD-1);
uiMsg(UIERROR_TRUNCPSW,MAXPASSWORD-1);
}
if (!StdinRedirected && Type==UIPASSWORD_GLOBAL)
{
eprintf(St(MReAskPsw));
std::wstring CmpStr;
GetPasswordText(CmpStr);
if (CmpStr.empty() || PlainPsw!=CmpStr)
{
eprintf(St(MNotMatchPsw));
cleandata(&PlainPsw[0],PlainPsw.size()*sizeof(PlainPsw[0]));
cleandata(&CmpStr[0],CmpStr.size()*sizeof(CmpStr[0]));
continue;
}
cleandata(&CmpStr[0],CmpStr.size()*sizeof(CmpStr[0]));
}
Password->Set(PlainPsw.c_str());
cleandata(&PlainPsw[0],PlainPsw.size()*sizeof(PlainPsw[0]));
break;
}
return true;
}
#endif
#ifndef SILENT
bool getwstr(std::wstring &str)
{
fflush(stderr);
QuitIfInputProhibited();
str.clear();
const size_t MaxRead=MAXPATHSIZE;
#if defined(_WIN_ALL)
if (StdinRedirected)
{
std::vector<char> StrA(MaxRead*4);
File SrcFile;
SrcFile.SetHandleType(FILE_HANDLESTD);
SrcFile.SetLineInputMode(true);
int ReadSize=SrcFile.Read(&StrA[0],StrA.size()-1);
if (ReadSize<=0)
{
ErrHandler.Exit(RARX_USERBREAK);
}
StrA[ReadSize]=0;
CharToWide(&StrA[0],str);
cleandata(&StrA[0],StrA.size());
}
else
{
std::vector<wchar> Buf(MaxRead);
DWORD ReadSize=0;
if (ReadConsole(GetStdHandle(STD_INPUT_HANDLE),&Buf[0],(DWORD)Buf.size()-1,&ReadSize,NULL)==0)
return false;
Buf[ReadSize]=0;
str=Buf.data();
}
#else
std::vector<wchar> Buf(MaxRead);
if (fgetws(&Buf[0],Buf.size(),stdin)==NULL)
ErrHandler.Exit(RARX_USERBREAK);
str=Buf.data();
#endif
RemoveLF(str);
return true;
}
#endif
#ifndef SILENT
int Ask(const wchar *AskStr)
{
uiAlarm(UIALARM_QUESTION);
const int MaxItems=10;
wchar Item[MaxItems][40];
int ItemKeyPos[MaxItems],NumItems=0;
for (const wchar *NextItem=AskStr;NextItem!=NULL;NextItem=wcschr(NextItem+1,'_'))
{
wchar *CurItem=Item[NumItems];
wcsncpyz(CurItem,NextItem+1,ASIZE(Item[0]));
wchar *EndItem=wcschr(CurItem,'_');
if (EndItem!=NULL)
*EndItem=0;
int KeyPos=0,CurKey;
while ((CurKey=CurItem[KeyPos])!=0)
{
bool Found=false;
for (int I=0;I<NumItems && !Found;I++)
if (toupperw(Item[I][ItemKeyPos[I]])==toupperw(CurKey))
Found=true;
if (!Found && CurKey!=' ')
break;
KeyPos++;
}
ItemKeyPos[NumItems]=KeyPos;
NumItems++;
}
for (int I=0;I<NumItems;I++)
{
eprintf(I==0 ? (NumItems>3 ? L"\n":L" "):L", ");
int KeyPos=ItemKeyPos[I];
for (int J=0;J<KeyPos;J++)
eprintf(L"%c",Item[I][J]);
eprintf(L"[%c]%ls",Item[I][KeyPos],&Item[I][KeyPos+1]);
}
eprintf(L" ");
std::wstring Str;
getwstr(Str);
wchar Ch=toupperw(Str[0]);
for (int I=0;I<NumItems;I++)
if (Ch==Item[I][ItemKeyPos[I]])
return I+1;
return 0;
}
#endif
static bool IsCommentUnsafe(const std::wstring &Data)
{ … }
void OutComment(const std::wstring &Comment)
{ … }