OSDN Git Service

3a8f5e48bfb6a5e15f4f40d366241501b80433b2
[tpi/lychee.git] / src / plugin / rarArc / rarArc.cpp
1 /*******************************************************************************\r
2   TPI - flexible but useless plug-in framework.\r
3   Copyright (C) 2002-2009 Silky\r
4 \r
5   This library is free software; you can redistribute it and/or modify it under\r
6   the terms of the GNU Lesser General Public License as published by the Free\r
7   Software Foundation; either version 2.1 of the License, or (at your option)\r
8   any later version.\r
9 \r
10   This library is distributed in the hope that it will be useful, but WITHOUT\r
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or \r
12   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License\r
13   for more details.\r
14 \r
15   You should have received a copy of the GNU Lesser General Public License along\r
16   with this library; if not, write to the Free Software Foundation, Inc.,\r
17   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
18 \r
19   $Id$\r
20 *******************************************************************************/\r
21 \r
22 //******************************************************************************\r
23 //    Includes\r
24 //******************************************************************************\r
25 \r
26 #define wxUSE_DYNLIB_CLASS 1\r
27 #include "../../common/header/plugin.h"\r
28 #include "../../common/header/plugin-extra.h"\r
29 #include "../../common/library/library.h"\r
30 #include <wx/dynlib.h>\r
31 #include "rarArc.h"\r
32 \r
33 //******************************************************************************\r
34 //    Global varients\r
35 //******************************************************************************\r
36 \r
37 wxDynamicLibrary g_hLib;\r
38 TPI_PROC g_prProc;\r
39 char g_szComment[64001];\r
40 RAROpenArchiveDataEx g_oaInfo;\r
41 RARHeaderDataEx * g_hdInfo;\r
42 \r
43 //******************************************************************************\r
44 //    Callback Wrapper\r
45 //******************************************************************************\r
46 \r
47 int __stdcall CallbackProc(unsigned int msg, long, long P1, long P2)\r
48 {\r
49         // 構造体を初期化。\r
50         static TPI_PROCESSINFO piInfo;\r
51 \r
52         switch (msg)\r
53         {\r
54         case UCM_CHANGEVOLUME:\r
55                 switch (P2)\r
56                 {\r
57                 case RAR_VOL_ASK:\r
58                         // 分割書庫の次の部分を要求。\r
59                         piInfo.eMessage = TPI_MESSAGE_ASK;\r
60                         piInfo.eStatus  = TPI_PARAM_NEXTVOLUME;\r
61                         piInfo.szParam.Empty();\r
62                         break;\r
63                 case RAR_VOL_NOTIFY:\r
64                         // 分割部分の読み込みを開始。\r
65                         piInfo.eMessage = TPI_MESSAGE_STATUS;\r
66                         piInfo.eStatus  = TPI_STATUS_OPENARCHIVE;\r
67                         piInfo.fiInfo.fnFileName = wxFileName(UTF82String((char *) P1));\r
68                         break;\r
69                 default:\r
70                         return 1;\r
71                 }\r
72                 break;\r
73         case UCM_PROCESSDATA:\r
74                 piInfo.eMessage = TPI_MESSAGE_STATUS;\r
75                 piInfo.eStatus  = TPI_STATUS_INPROCESS;\r
76                 piInfo.nProcessedSize += P2;\r
77                 break;\r
78         case UCM_NEEDPASSWORD:\r
79                 piInfo.eMessage = TPI_MESSAGE_ASK;\r
80                 piInfo.eStatus  = TPI_PARAM_PASSWORD;\r
81                 piInfo.szParam.Empty();\r
82                 break;\r
83         default:\r
84                 return 1;\r
85         }\r
86 \r
87         // コールバック関数に送信。\r
88         if (g_prProc == NULL || g_prProc(TPI_NOTIFY_COMMON, & piInfo) == TPI_CALLBACK_CONTINUE)\r
89         {\r
90                 if (msg != UCM_PROCESSDATA && P2 != RAR_VOL_NOTIFY)\r
91                 {\r
92                         strncpy((char *) P1, piInfo.szParam.char_str(), (msg == UCM_CHANGEVOLUME ? 1024 : P2) - 1);\r
93                 }\r
94                 return 1;\r
95         }\r
96         else\r
97         {\r
98                 return -1;\r
99         }\r
100 }\r
101 \r
102 //******************************************************************************\r
103 //    Inside Functions\r
104 //******************************************************************************\r
105 \r
106 int ErrorCodeConvert(int nErrorCode)\r
107 {\r
108         switch (nErrorCode)\r
109         {\r
110         case 0:                     return TPI_ERROR_SUCCESS;\r
111         case 1:                     return TPI_ERROR_SUCCESS;\r
112         case ERAR_END_ARCHIVE:      return TPI_ERROR_S_ENDOFDATA;\r
113         case ERAR_NO_MEMORY:        return TPI_ERROR_D_OUTOFMEMORY;\r
114         case ERAR_BAD_DATA:         return TPI_ERROR_ARC_BROKEN_MISC;\r
115         case ERAR_BAD_ARCHIVE:      return TPI_ERROR_ARC_UNSUPPORTED;\r
116         case ERAR_UNKNOWN_FORMAT:   return TPI_ERROR_ARC_ENCRYPTED;\r
117         case ERAR_EOPEN:            return TPI_ERROR_IO_ARC_OPEN;\r
118         case ERAR_ECREATE:          return TPI_ERROR_IO_FILE_OPEN;\r
119         case ERAR_ECLOSE:           return TPI_ERROR_IO_CLOSE;\r
120         case ERAR_EREAD:            return TPI_ERROR_IO_ARC_READ;\r
121         case ERAR_EWRITE:           return TPI_ERROR_IO_FILE_WRITE;\r
122         case ERAR_SMALL_BUF:        return TPI_ERROR_UNDEFINED;\r
123         case ERAR_UNKNOWN:          return TPI_ERROR_UNDEFINED;\r
124         case ERAR_MISSING_PASSWORD: return TPI_ERROR_ARC_ENCRYPTED;\r
125         default:                    return TPI_ERROR_UNDEFINED;\r
126         }\r
127 }\r
128 \r
129 //******************************************************************************\r
130 //    Functions\r
131 //******************************************************************************\r
132 \r
133 #ifdef __cplusplus\r
134 extern "C"\r
135 {\r
136 #endif\r
137 \r
138 int __stdcall GetPluginInformation\r
139 (\r
140         unsigned int _uInfoId,\r
141         wxULongLong_t,\r
142         void * _pPtr\r
143 )\r
144 {\r
145         if (_pPtr == NULL)\r
146         {\r
147                 return TPI_ERROR_D_PARAMETER;\r
148         }\r
149         switch (_uInfoId)\r
150         {\r
151         case TPI_INFO_VERSION_MAJOR:\r
152         case TPI_INFO_VERSION_MINOR:\r
153                 * (int *) _pPtr = 0;\r
154                 break;\r
155         case TPI_INFO_VERSION_API:\r
156                 * (int *) _pPtr = 2;\r
157                 break;\r
158         default:\r
159                 return TPI_ERROR_D_UNSUPPORTED;\r
160         }\r
161         return TPI_ERROR_SUCCESS;\r
162 }\r
163 \r
164 int __stdcall GetFormatInformation(TPI_FORMATINFO * _fiInfo, bool _bFirst)\r
165 {\r
166         if (! _bFirst)\r
167         {\r
168                 return TPI_ERROR_S_ENDOFDATA;\r
169         }\r
170 \r
171         _fiInfo->szTypeName   = wxT("RAR");\r
172         _fiInfo->szSuffix     = wxT("rar");\r
173         _fiInfo->szEngineName = g_hLib.CanonicalizeName(wxT("unrar"));\r
174         _fiInfo->szTPIName    = wxT("rarArc");\r
175         _fiInfo->nTypeId      = 0;\r
176         _fiInfo->eSupportedCommand = TPI_COMMAND_EXTRACT | TPI_COMMAND_TEST;\r
177         _fiInfo->fArchive     = true;\r
178         _fiInfo->fComment     = true;\r
179         _fiInfo->fSFX         = true;\r
180         _fiInfo->fSolid       = true;\r
181         _fiInfo->fEncryptPassword = true;\r
182         _fiInfo->fMultiVolume = true;\r
183 \r
184         return TPI_ERROR_SUCCESS;\r
185 }\r
186 \r
187 int __stdcall LoadPlugin\r
188 (\r
189         const wxString &,\r
190         wxULongLong_t\r
191 )\r
192 {\r
193         ::RemoveCwdFromSearchPath();\r
194         g_hLib.Load(g_hLib.CanonicalizeName(wxT("unrar")));\r
195         if (! g_hLib.IsLoaded())\r
196         {\r
197                 g_hLib.Unload();\r
198                 return TPI_ERROR_U_LOAD_LIBRARY;\r
199         }\r
200 \r
201         return TPI_ERROR_SUCCESS;\r
202 }\r
203 \r
204 int __stdcall FreePlugin\r
205 (\r
206         void * // _pReserved\r
207 )\r
208 {\r
209         g_hLib.Unload();\r
210         return TPI_ERROR_SUCCESS;\r
211 }\r
212 \r
213 int __stdcall CheckArchive\r
214 (\r
215         const wxString & _szArcName,\r
216         wxULongLong_t * _llFileCount\r
217 )\r
218 {\r
219         void * _hArchive;\r
220         int nErrorCode = OpenArchive(_szArcName, & _hArchive);\r
221         if (nErrorCode != TPI_ERROR_SUCCESS)\r
222         {\r
223                 return nErrorCode;\r
224         }\r
225 \r
226         if (_llFileCount != NULL)\r
227         {\r
228                 * _llFileCount = 1;\r
229         }\r
230 \r
231         return CloseArchive(_hArchive);\r
232 }\r
233 \r
234 int __stdcall OpenArchive\r
235 (\r
236         const wxString & _szArcName,\r
237         void * * _hArchive\r
238 )\r
239 {\r
240         if (! g_hLib.HasSymbol(wxT("RAROpenArchiveEx")))\r
241         {\r
242                 return TPI_ERROR_U_USE_LIBRARY;\r
243         }\r
244         void * p = g_hLib.GetSymbol(wxT("RAROpenArchiveEx"));\r
245         if (! p)\r
246         {\r
247                 return TPI_ERROR_U_USE_LIBRARY;\r
248         }\r
249 \r
250         memset(& g_oaInfo, 0, sizeof(g_oaInfo));\r
251         g_oaInfo.ArcName    = NULL;\r
252         g_oaInfo.ArcNameW   = (wchar_t *) malloc((_szArcName.Len() + 1) * sizeof(wchar_t));\r
253         wcscpy(g_oaInfo.ArcNameW, _szArcName.wchar_str());\r
254         g_oaInfo.OpenMode   = RAR_OM_EXTRACT;\r
255         g_oaInfo.CmtBuf     = g_szComment;\r
256         g_oaInfo.CmtBufSize = sizeof(g_szComment) - 1;\r
257         * _hArchive = ((void * (__stdcall *)(RAROpenArchiveDataEx *)) p)(& g_oaInfo);\r
258         free(g_oaInfo.ArcNameW);\r
259         if (* _hArchive == NULL)\r
260         {\r
261                 return TPI_ERROR_UNDEFINED;\r
262         }\r
263         int nErrorCode = ErrorCodeConvert(g_oaInfo.OpenResult);\r
264         if (nErrorCode != TPI_ERROR_SUCCESS)\r
265         {\r
266                 return nErrorCode;\r
267         }\r
268 \r
269         // コールバック関数を設定。\r
270         if (! g_hLib.HasSymbol(wxT("RARSetCallback")))\r
271         {\r
272                 return TPI_ERROR_U_USE_LIBRARY;\r
273         }\r
274         p = g_hLib.GetSymbol(wxT("RARSetCallback"));\r
275         if (! p)\r
276         {\r
277                 return TPI_ERROR_U_USE_LIBRARY;\r
278         }\r
279         ((void (__stdcall *)(void *, void *, long)) p)(* _hArchive, (void *) CallbackProc, (long) & g_hdInfo);\r
280 \r
281         return TPI_ERROR_SUCCESS;\r
282 }\r
283 \r
284 int __stdcall CloseArchive\r
285 (\r
286         void * _hArchive\r
287 )\r
288 {\r
289         if (! g_hLib.HasSymbol(wxT("RARCloseArchive")))\r
290         {\r
291                 return TPI_ERROR_U_USE_LIBRARY;\r
292         }\r
293         void * p = g_hLib.GetSymbol(wxT("RARCloseArchive"));\r
294         return (! p || _hArchive == NULL) ? TPI_ERROR_U_USE_LIBRARY : ErrorCodeConvert(((int (__stdcall *)(void *)) p)(_hArchive));\r
295 }\r
296 \r
297 int __stdcall GetFileInformation\r
298 (\r
299         void * _hArchive,\r
300         TPI_FILEINFO * _fiInfo,\r
301         bool _bFirst\r
302 )\r
303 {\r
304         static wxULongLong_t s_nFileId;\r
305         static void * pR, * pP;\r
306         int nErrorCode;\r
307 \r
308         if (_bFirst)\r
309         {\r
310                 s_nFileId = 0;\r
311                 pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL;\r
312                 pP = g_hLib.HasSymbol(wxT("RARProcessFileW"))  ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
313                 if (! pR || ! pP)\r
314                 {\r
315                         return TPI_ERROR_U_USE_LIBRARY;\r
316                 }\r
317         }\r
318 \r
319         RARHeaderDataEx hdInfo;\r
320         char szComment[64001];\r
321         hdInfo.CmtBuf     = szComment;\r
322         hdInfo.CmtBufSize = sizeof(szComment) - 1;\r
323         nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(_hArchive, & hdInfo));\r
324         if (nErrorCode == TPI_ERROR_SUCCESS)\r
325         {\r
326                 _fiInfo->dwAttribute    = hdInfo.FileAttr;\r
327                 if (hdInfo.Flags & 0x04)\r
328                 {\r
329                         _fiInfo->dwAttribute |= TPI_ATTRIBUTE_ENCRYPTED;\r
330                 }\r
331                 _fiInfo->dwCRC32        = hdInfo.FileCRC;\r
332                 _fiInfo->nPackedSize    = hdInfo.PackSizeHigh;\r
333                 _fiInfo->nPackedSize    = _fiInfo->nPackedSize << 32;\r
334                 _fiInfo->nPackedSize   += hdInfo.PackSize;\r
335                 _fiInfo->nUnpackedSize  = hdInfo.UnpSizeHigh;\r
336                 _fiInfo->nUnpackedSize  = _fiInfo->nUnpackedSize << 32;\r
337                 _fiInfo->nUnpackedSize += hdInfo.UnpSize;\r
338                 _fiInfo->tmModified.SetFromDOS(hdInfo.FileTime);\r
339                 _fiInfo->eOSType        = hdInfo.HostOS;\r
340                 _fiInfo->szStoredName   = WC2String(hdInfo.FileNameW);\r
341                 _fiInfo->szMethod.Printf(wxT("%x"), hdInfo.Method);\r
342                 _fiInfo->szComment      = UTF82String(hdInfo.CmtBuf);\r
343                 _fiInfo->nFileId        = s_nFileId++;\r
344                 _fiInfo->fnFileName     = wxFileName(_fiInfo->szStoredName);\r
345 \r
346                 // 次のファイルへ。\r
347                 nErrorCode = ErrorCodeConvert(((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(_hArchive, RAR_SKIP, NULL, NULL));\r
348         }\r
349 \r
350         return nErrorCode;\r
351 }\r
352 \r
353 int __stdcall GetArchiveInformation\r
354 (\r
355         void *,\r
356         TPI_ARCHIVEINFO * _aiInfo\r
357 )\r
358 {\r
359         _aiInfo->fSolid         = (g_oaInfo.Flags & 0x0008) == 1;\r
360         _aiInfo->fEncryptHeader = (g_oaInfo.Flags & 0x0080) == 1;\r
361         _aiInfo->szComment      = UTF82String(g_szComment);\r
362         GetFormatInformation(& _aiInfo->fiInfo, true);\r
363         return TPI_ERROR_SUCCESS;\r
364 }\r
365 \r
366 int __stdcall Command\r
367 (\r
368         wxULongLong_t _eCommand,\r
369         TPI_SWITCHES * _swInfo,\r
370         const wxString & _szArcName,\r
371         const wxArrayString & _szFiles\r
372 )\r
373 {\r
374         if (_eCommand != TPI_COMMAND_EXTRACT && _eCommand != TPI_COMMAND_TEST)\r
375         {\r
376                 return TPI_ERROR_U_USE_LIBRARY;\r
377         }\r
378 \r
379         // 開きなおす。\r
380         void * hArc;\r
381         int nErrorCode = OpenArchive(_szArcName, & hArc);\r
382         if (nErrorCode != TPI_ERROR_SUCCESS)\r
383         {\r
384                 return nErrorCode;\r
385         }\r
386 \r
387         void\r
388                 * pS = g_hLib.HasSymbol(wxT("RARSetPassword"))  ? g_hLib.GetSymbol(wxT("RARSetPassword"))  : NULL,\r
389                 * pR = g_hLib.HasSymbol(wxT("RARReadHeaderEx")) ? g_hLib.GetSymbol(wxT("RARReadHeaderEx")) : NULL,\r
390                 * pP = g_hLib.HasSymbol(wxT("RARProcessFileW")) ? g_hLib.GetSymbol(wxT("RARProcessFileW")) : NULL;\r
391         if (! pR || ! pP)\r
392         {\r
393                 return TPI_ERROR_U_USE_LIBRARY;\r
394         }\r
395         if (pS)\r
396         {\r
397                 ((void (__stdcall *)(void *, char *)) pS)(hArc, _swInfo->szPassword.char_str());\r
398         }\r
399 \r
400         RARHeaderDataEx hdInfo;\r
401         g_hdInfo = & hdInfo;\r
402         while (nErrorCode == TPI_ERROR_SUCCESS && ErrorCodeConvert(((int (__stdcall *)(void *, RARHeaderDataEx *)) pR)(hArc, & hdInfo)) == TPI_ERROR_SUCCESS)\r
403         {\r
404                 nErrorCode =\r
405                         ErrorCodeConvert(\r
406                                 ((int (__stdcall *)(void *, int, wchar_t *, wchar_t *)) pP)(\r
407                                         hArc,\r
408                                         (_szFiles.GetCount() != 0 && _szFiles.Index(wxString(hdInfo.FileNameW)) == wxNOT_FOUND) ? RAR_SKIP : _eCommand == TPI_COMMAND_EXTRACT ? RAR_EXTRACT : RAR_TEST,\r
409                                         _swInfo->fStoreDirectoryPathes ? _swInfo->fnDestinationDirectory.GetFullPath().wchar_str() : NULL,\r
410                                         _swInfo->fStoreDirectoryPathes ? NULL : (_swInfo->fnDestinationDirectory.GetPathWithSep() + wxFileName(hdInfo.FileNameW).GetFullName()).wchar_str()\r
411                                 )\r
412                         );\r
413         }\r
414         CloseArchive(hArc);\r
415         return nErrorCode;\r
416 }\r
417 \r
418 int __stdcall SetCallbackProc\r
419 (\r
420         TPI_PROC _prArcProc\r
421 )\r
422 {\r
423         // ポインタを保存。\r
424         if (_prArcProc == NULL)\r
425         {\r
426                 return TPI_ERROR_D_PARAMETER;\r
427         }\r
428         g_prProc = * _prArcProc;\r
429 \r
430         return TPI_ERROR_SUCCESS;\r
431 }\r
432 \r
433 #ifdef __cplusplus\r
434 }\r
435 #endif\r