From b9e45212748f18f41caa02bf1bd1598c07908f91 Mon Sep 17 00:00:00 2001 From: sirakaba Date: Sun, 20 Feb 2011 10:31:53 +0000 Subject: [PATCH] =?utf8?q?0.01β7=E4=BB=A5=E9=99=8D=E3=80=81Windows?= =?utf8?q?=E3=81=A7=E5=87=A6=E7=90=86=E3=81=8C=E4=BD=8E=E9=80=9F=E3=81=AB?= =?utf8?q?=E3=81=AA=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E3=83=90=E3=82=B0?= =?utf8?q?=E3=82=92=E4=BF=AE=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/tpi/tpi@489 9df91469-1e22-0410-86e7-ea8537beb833 --- src/plugin/cuiWrapper/cuiWrapper.cpp | 222 +++++++++++++++++------------------ 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/src/plugin/cuiWrapper/cuiWrapper.cpp b/src/plugin/cuiWrapper/cuiWrapper.cpp index 7c6da87..42aec89 100644 --- a/src/plugin/cuiWrapper/cuiWrapper.cpp +++ b/src/plugin/cuiWrapper/cuiWrapper.cpp @@ -27,8 +27,9 @@ #include "../../common/header/plugin-extra.h" #include "../../common/library/library.h" #include "../../common/library/xmldoc.h" -#include #include +#include +#include #include "cuiWrapper.h" //****************************************************************************** @@ -50,87 +51,30 @@ TPI_PROC g_prProc; // Inside Functions //****************************************************************************** -int myExecute(const wxString & szCommandLine, wxString * szOutput, const wxString & szCwd, bool fWine) +int myExecute(const wxString & szCommandLine, bool fWine) { #ifdef __LINUX__ - wxString sz = ::wxGetCwd(); - ::wxSetWorkingDirectory(szCwd); FILE * fp = popen(fWine ? (wxT("wine ") + szCommandLine).ToUTF8() : szCommandLine.ToUTF8(), "r"); - ::wxSetWorkingDirectory(sz); if (fp == NULL) { wxLogError(L"Error :\n\nCommandLine:\n%s", szCommandLine.c_str()); return TPI_ERROR_U_USE_LIBRARY; } - if (szOutput != NULL) - { - char sz[32769]; - while (! feof(fp)) - { - memset(sz, 0, sizeof(sz)); - fread(sz, sizeof(char), sizeof(sz) - 1, fp); - * szOutput += UTF82String(sz); - } -// ::wxMessageBox(* szOutput); - } - // 127を返した場合はコマンドが存在しない。 int nErrorCode = pclose(fp); return (WIFEXITED(nErrorCode) && WEXITSTATUS(nErrorCode) != 127) ? TPI_ERROR_SUCCESS : TPI_ERROR_U_USE_LIBRARY; #else - SECURITY_ATTRIBUTES sa; - memset(& sa, 0, sizeof(SECURITY_ATTRIBUTES)); - sa.bInheritHandle = TRUE; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - HANDLE hRead, hWrite; - if (! ::CreatePipe(& hRead, & hWrite, & sa, 0)) - { - return TPI_ERROR_U_USE_LIBRARY; - } STARTUPINFO si; + PROCESS_INFORMATION pi; memset(& si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); - si.dwFlags = STARTF_USESTDHANDLES; - si.hStdOutput = hWrite; - si.hStdError = hWrite; - PROCESS_INFORMATION pi; - if (! ::CreateProcess(NULL, szCommandLine.wchar_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, szCwd.IsEmpty() ? NULL : szCwd.wchar_str(), & si, & pi)) + if (! ::CreateProcess(NULL, szCommandLine.wchar_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, & si, & pi)) { return TPI_ERROR_U_USE_LIBRARY; } ::CloseHandle(pi.hThread); - - if (szOutput != NULL) - { - char sz[32768]; - while (true) - { - DWORD dwSize = 0; - if (! ::PeekNamedPipe(hRead, NULL, 0, NULL, & dwSize, NULL)) - { - continue; - } - - if (dwSize > 0) - { - memset(sz, 0, sizeof(sz)); - ::ReadFile(hRead, & sz, sizeof(sz), & dwSize, NULL); - * szOutput += wxString(sz); - // UTF-8以外の文字コードだと、UTF82Stringを使うと書庫が開けなくなる。データの切り出しにも影響。 -// * szOutput += UTF82String(sz); -// ::MessageBoxA(NULL, sz, NULL, 0); - } - else if (::WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0) - { - break; - } - } - } - ::CloseHandle(pi.hProcess); - ::CloseHandle(hRead); - ::CloseHandle(hWrite); return TPI_ERROR_SUCCESS; #endif } @@ -144,15 +88,18 @@ PosInfo MakePosInfo(const wxString & szPrefix) return pi; } -wxULongLong_t GetSize(const PosInfo & pi, wxULongLong_t nCurrent, const wxArrayString & as) +wxULongLong_t GetSize(const PosInfo & pi, const wxArrayString & as) { if (pi.nStart == 0 && pi.nCount == 0) { return 0; } - wxULongLong_t nTemp = 0, nPos = nCurrent + pi.nLine; - wxString sz = pi.nCount == 0 ? as[nPos].Mid(pi.nStart) : as[nPos].Mid(pi.nStart, pi.nCount); + wxULongLong_t nTemp = 0; + wxString sz = + pi.nCount == 0 ? + as[pi.nLine].Mid(pi.nStart) : + as[pi.nLine].Mid(pi.nStart, pi.nCount); sz.ToULongLong(& nTemp); return nTemp; } @@ -215,7 +162,7 @@ int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst) MakeFormatInfo(xmlLibrary, wxT("cuiWrapper"), _fiInfo, s_nFileId++); wxString szExeFile = xmlLibrary->GetAttribute(wxT("name"), wxEmptyString); - if (myExecute(szExeFile, NULL, wxEmptyString, szExeFile.Find(wxT('.')) != wxNOT_FOUND && szExeFile.AfterLast(wxT('.')) == wxT("exe")) != TPI_ERROR_SUCCESS) + if (myExecute(szExeFile, szExeFile.EndsWith(wxT(".exe"))) != TPI_ERROR_SUCCESS) { _fiInfo->eSupportedCommand = 0; } @@ -290,32 +237,47 @@ int __stdcall OpenArchive ( const wxString & _szArcName, void * * _hArchive, - wxULongLong_t * _nFileCount + wxULongLong_t * ) { - wxString szOutput; - if (myExecute(g_LibInfo.szExeFile + wxT(" ") + MakeCommandLineSend(g_LibInfo.node.GetAttribute(wxT("list"), wxEmptyString), _szArcName), & szOutput, wxEmptyString, g_LibInfo.szExeFile.Find(wxT('.')) != wxNOT_FOUND && g_LibInfo.szExeFile.AfterLast(wxT('.')) == wxT("exe")) != TPI_ERROR_SUCCESS) + wxString szCommandLine = g_LibInfo.szExeFile + wxT(" ") + MakeCommandLineSend(g_LibInfo.node.GetAttribute(wxT("list"), wxEmptyString), _szArcName); +#ifdef __LINUX__ + wxProcess * p = ::wxProcess::Open(g_LibInfo.szExeFile.EndsWith(wxT(".exe")) ? (wxT("wine ") + szCommandLine) : szCommandLine, wxEXEC_ASYNC); +#else + wxProcess * p = ::wxProcess::Open(szCommandLine, wxEXEC_ASYNC); +#endif + if (p == NULL) { + wxLogError(L"Error :\n\nCommandLine:\n%s", szCommandLine.c_str()); return TPI_ERROR_U_USE_LIBRARY; } - wxArrayString * as = new wxArrayString(::wxStringTokenize(szOutput, wxT("\r\n"))); - * _hArchive = (void *) as; - as->Shrink(); - if (_nFileCount != NULL) + + p->Redirect(); + wxInputStream * is = p->GetInputStream(); + wxTextInputStream tis(* is); + wxString szStartLine = g_LibInfo.node.GetAttribute(wxT("list-line-s"), wxEmptyString); + if (! szStartLine.IsEmpty()) { - * _nFileCount = as->GetCount(); + // 開始行まで読み飛ばす。 + while (! is->Eof() && tis.ReadLine() != szStartLine); + if (is->Eof()) + { + // 書庫が読み込めなかった? + ::wxSafeShowMessage(wxEmptyString, wxT("Unsupported archive!")); + p->Detach(); + return TPI_ERROR_ARC_UNSUPPORTED; + } } - return as->IsEmpty() ? TPI_ERROR_UNDEFINED : TPI_ERROR_SUCCESS; + + * _hArchive = (void *) is; + return is->Eof() ? TPI_ERROR_UNDEFINED : TPI_ERROR_SUCCESS; } int __stdcall CloseArchive ( - void * _hArchive + void * ) { - wxArrayString * as = (wxArrayString *) _hArchive; - as->Clear(); - delete as; return TPI_ERROR_SUCCESS; } @@ -332,7 +294,8 @@ int __stdcall GetFileInformation { return TPI_ERROR_UNDEFINED; } - wxArrayString asOutput = * (wxArrayString *) _hArchive; + wxInputStream * is = (wxInputStream *) _hArchive; + wxTextInputStream tis(* is); // XMLからの読み込みは初回に行う。 static wxString szEndLine, szDateFormat; @@ -340,60 +303,60 @@ int __stdcall GetFileInformation static PosInfo piFName, piPSize, piUSize, piDate; if (_bFirst) { - s_nFileId = 0; - wxString szStartLine = g_LibInfo.node.GetAttribute(wxT("list-line-s"), wxEmptyString); - if (! szStartLine.IsEmpty()) - { - // 開始行の次の行にセット。 - s_nCurrentLine = asOutput.Index(szStartLine) + 1; - if (s_nCurrentLine == wxNOT_FOUND + 1) - { - // 書庫が読み込めなかった? - return TPI_ERROR_ARC_UNSUPPORTED; - } - } - // 初期設定。 + s_nFileId = 0; nProcessPerLine = myGetAttributeInt(& g_LibInfo.node, wxT("list-line-c"), 1); - szEndLine = g_LibInfo.node.GetAttribute(wxT("list-line-e"), szStartLine); - szDateFormat = g_LibInfo.node.GetAttribute(wxT("list-date-f"), wxDefaultDateTimeFormat); + szEndLine = g_LibInfo.node.GetAttribute(wxT("list-line-e"), g_LibInfo.node.GetAttribute(wxT("list-line-s"), wxEmptyString)); + szDateFormat = g_LibInfo.node.GetAttribute(wxT("list-date-f"), wxDefaultDateTimeFormat); piFName = MakePosInfo(wxT("fname")); piPSize = MakePosInfo(wxT("psize")); piUSize = MakePosInfo(wxT("usize")); piDate = MakePosInfo(wxT("date")); } - if (s_nCurrentLine >= asOutput.GetCount()) + if (is->Eof()) { // 空行で終わるとき以外はエラーとする。 return szEndLine.IsEmpty() ? TPI_ERROR_S_ENDOFDATA : TPI_ERROR_ARC_UNSUPPORTED; } - // 最終行かどうか確認。 - if (asOutput[s_nCurrentLine] == szEndLine) + // 必要な行数だけ取得。 + wxArrayString as; + as.Add(tis.ReadLine()); + if (as[0] == szEndLine) { return TPI_ERROR_S_ENDOFDATA; } + for (int i = 1; i < nProcessPerLine; i++) + { + as.Add(tis.ReadLine()); + } // ファイル名を取得。 - _fiInfo->szStoredName = piFName.nCount == 0 ? asOutput[s_nCurrentLine + piFName.nLine].Mid(piFName.nStart) : asOutput[s_nCurrentLine + piFName.nLine].Mid(piFName.nStart, piFName.nCount); + _fiInfo->szStoredName = + piFName.nCount == 0 ? + as[piFName.nLine].Mid(piFName.nStart) : + as[piFName.nLine].Mid(piFName.nStart, piFName.nCount); _fiInfo->szStoredName.Trim(); _fiInfo->fnFileName = wxFileName(_fiInfo->szStoredName, wxPATH_DOS); // サイズ取得。 - _fiInfo->nPackedSize = GetSize(piPSize, s_nCurrentLine, asOutput); - _fiInfo->nUnpackedSize = GetSize(piUSize, s_nCurrentLine, asOutput); + _fiInfo->nPackedSize = GetSize(piPSize, as); + _fiInfo->nUnpackedSize = GetSize(piUSize, as); // 更新時刻取得。 if (piDate.nStart != 0 || piDate.nCount != 0) { - _fiInfo->tmModify.ParseFormat(piDate.nCount == 0 ? asOutput[s_nCurrentLine + piDate.nLine].Mid(piDate.nStart) : asOutput[s_nCurrentLine + piDate.nLine].Mid(piDate.nStart, piDate.nCount), szDateFormat); + _fiInfo->tmModify.ParseFormat( + piDate.nCount == 0 ? + as[piDate.nLine].Mid(piDate.nStart) : + as[piDate.nLine].Mid(piDate.nStart, piDate.nCount), + szDateFormat + ); } // 最後に次の行へ進めておく。 _fiInfo->nFileId = s_nFileId++; - s_nCurrentLine += nProcessPerLine; - return TPI_ERROR_SUCCESS; } @@ -453,20 +416,57 @@ int __stdcall Command // コマンドライン・レスポンスファイル作成。 wxString szResponceFileName = MakeResponceFile(_szFiles, myGetAttributeBool(& g_LibInfo.node, wxT("quote-resp"), true)), - szCommandLineSend = MakeCommandLineSend(szCommandLine, _szArcName, _swInfo, _szFiles, szResponceFileName); + szCommandLineSend = g_LibInfo.szExeFile + wxT(" ") + MakeCommandLineSend(szCommandLine, _szArcName, _swInfo, _szFiles, szResponceFileName), + sz = ::wxGetCwd(); // コマンドライン実行。 - wxString szOutput; - int nErrorCode = myExecute(g_LibInfo.szExeFile + wxT(" ") + szCommandLineSend, & szOutput, _swInfo->fnDestinationDirectory.GetFullPath(), g_LibInfo.szExeFile.Find(wxT('.')) != wxNOT_FOUND && g_LibInfo.szExeFile.AfterLast(wxT('.')) == wxT("exe")); + ::wxSetWorkingDirectory(_swInfo->fnDestinationDirectory.GetFullPath()); +#ifdef __LINUX__ + wxProcess * p = ::wxProcess::Open(g_LibInfo.szExeFile.EndsWith(wxT(".exe")) ? (wxT("wine ") + szCommandLineSend) : szCommandLineSend, wxEXEC_ASYNC); +#else + wxProcess * p = ::wxProcess::Open(szCommandLineSend, wxEXEC_ASYNC); +#endif + ::wxSetWorkingDirectory(sz); + if (p == NULL) + { + ::wxRemoveFile(szResponceFileName); + wxLogError(L"CommandLine:\n%s", szCommandLineSend.c_str()); + return TPI_ERROR_U_USE_LIBRARY; + } - // レスポンスファイル削除。 - ::wxRemoveFile(szResponceFileName); + TPI_PROCESSINFO piInfo; + piInfo.eMessage = TPI_MESSAGE_STATUS; + piInfo.eStatus = TPI_STATUS_INPROCESS; + piInfo.nProcessedSize = 0; - if (nErrorCode != TPI_ERROR_SUCCESS) + p->Redirect(); + wxString szOutput; + wxInputStream * is = p->GetInputStream(); + while (! is->Eof()) { - wxLogError(L"Error :\n%x\n\nCommandLine:\n%s\n\nOutput:\n%s", nErrorCode, szCommandLineSend.c_str(), szOutput.c_str()); + // コールバック関数に送信。 + if (g_prProc != NULL && g_prProc(TPI_NOTIFY_COMMON, & piInfo) == TPI_CALLBACK_CANCEL) + { + p->Kill(p->GetPid(), wxSIGKILL); + p->Detach(); + ::wxRemoveFile(szResponceFileName); + return TPI_ERROR_D_SKIPPED; + } + + if (! is->CanRead()) + { + continue; + } + + char sz[8192]; + is->Read(sz, sizeof(sz)); + szOutput += UTF82String(sz); } - return nErrorCode; +// ::wxMessageBox(szOutput); + + // レスポンスファイル削除。 + ::wxRemoveFile(szResponceFileName); + return TPI_ERROR_SUCCESS; } int __stdcall SetCallbackProc -- 2.11.0