1 // Plugin.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/IntToString.h"
6 #include "../../../Common/StringConvert.h"
7 #include "../../../Common/Wildcard.h"
8
9 #include "../../../Windows/FileDir.h"
10 #include "../../../Windows/PropVariantConv.h"
11
12 #include "../Common/PropIDUtils.h"
13
14 #include "FarUtils.h"
15 #include "Messages.h"
16 #include "Plugin.h"
17
18 using namespace NWindows;
19 using namespace NFile;
20 using namespace NDir;
21 using namespace NFar;
22
23 // This function is used by CAgentFolder
24 int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2);
CompareFileNames_ForFolderList(const wchar_t * s1,const wchar_t * s2)25 int CompareFileNames_ForFolderList(const wchar_t *s1, const wchar_t *s2)
26 {
27 return MyStringCompareNoCase(s1, s2);
28 }
29
CPlugin(const FString & fileName,CAgent * agent,UString archiveTypeName)30 CPlugin::CPlugin(const FString &fileName, CAgent *agent, UString archiveTypeName):
31 _agent(agent),
32 m_FileName(fileName),
33 _archiveTypeName(archiveTypeName),
34 PasswordIsDefined(false)
35 {
36 m_ArchiveHandler = agent;
37 if (!m_FileInfo.Find(m_FileName))
38 throw "error";
39 m_ArchiveHandler->BindToRootFolder(&_folder);
40 }
41
~CPlugin()42 CPlugin::~CPlugin() {}
43
MyGetFileTime(IFolderFolder * folder,UInt32 itemIndex,PROPID propID,FILETIME & fileTime)44 static void MyGetFileTime(IFolderFolder *folder, UInt32 itemIndex,
45 PROPID propID, FILETIME &fileTime)
46 {
47 NCOM::CPropVariant prop;
48 if (folder->GetProperty(itemIndex, propID, &prop) != S_OK)
49 throw 271932;
50 if (prop.vt == VT_EMPTY)
51 {
52 fileTime.dwHighDateTime = 0;
53 fileTime.dwLowDateTime = 0;
54 }
55 else
56 {
57 if (prop.vt != VT_FILETIME)
58 throw 4191730;
59 fileTime = prop.filetime;
60 }
61 }
62
63 #define kDotsReplaceString "[[..]]"
64 #define kDotsReplaceStringU L"[[..]]"
65
CopyStrLimited(char * dest,const AString & src,unsigned len)66 static void CopyStrLimited(char *dest, const AString &src, unsigned len)
67 {
68 len--;
69 if (src.Len() < len)
70 len = src.Len();
71 memcpy(dest, src, sizeof(dest[0]) * len);
72 dest[len] = 0;
73 }
74
75 #define COPY_STR_LIMITED(dest, src) CopyStrLimited(dest, src, Z7_ARRAY_SIZE(dest))
76
ReadPluginPanelItem(PluginPanelItem & panelItem,UInt32 itemIndex)77 void CPlugin::ReadPluginPanelItem(PluginPanelItem &panelItem, UInt32 itemIndex)
78 {
79 NCOM::CPropVariant prop;
80 if (_folder->GetProperty(itemIndex, kpidName, &prop) != S_OK)
81 throw 271932;
82
83 if (prop.vt != VT_BSTR)
84 throw 272340;
85
86 AString oemString (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP));
87 if (oemString == "..")
88 oemString = kDotsReplaceString;
89
90 COPY_STR_LIMITED(panelItem.FindData.cFileName, oemString);
91 panelItem.FindData.cAlternateFileName[0] = 0;
92
93 if (_folder->GetProperty(itemIndex, kpidAttrib, &prop) != S_OK)
94 throw 271932;
95 if (prop.vt == VT_UI4)
96 panelItem.FindData.dwFileAttributes = prop.ulVal;
97 else if (prop.vt == VT_EMPTY)
98 panelItem.FindData.dwFileAttributes = m_FileInfo.Attrib;
99 else
100 throw 21631;
101
102 if (_folder->GetProperty(itemIndex, kpidIsDir, &prop) != S_OK)
103 throw 271932;
104 if (prop.vt == VT_BOOL)
105 {
106 if (VARIANT_BOOLToBool(prop.boolVal))
107 panelItem.FindData.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
108 }
109 else if (prop.vt != VT_EMPTY)
110 throw 21632;
111
112 if (_folder->GetProperty(itemIndex, kpidSize, &prop) != S_OK)
113 throw 271932;
114 UInt64 length = 0;
115 ConvertPropVariantToUInt64(prop, length);
116 panelItem.FindData.nFileSizeLow = (UInt32)length;
117 panelItem.FindData.nFileSizeHigh = (UInt32)(length >> 32);
118
119 MyGetFileTime(_folder, itemIndex, kpidCTime, panelItem.FindData.ftCreationTime);
120 MyGetFileTime(_folder, itemIndex, kpidATime, panelItem.FindData.ftLastAccessTime);
121 MyGetFileTime(_folder, itemIndex, kpidMTime, panelItem.FindData.ftLastWriteTime);
122
123 if (panelItem.FindData.ftLastWriteTime.dwHighDateTime == 0 &&
124 panelItem.FindData.ftLastWriteTime.dwLowDateTime == 0)
125 panelItem.FindData.ftLastWriteTime = m_FileInfo.MTime;
126
127 if (_folder->GetProperty(itemIndex, kpidPackSize, &prop) != S_OK)
128 throw 271932;
129 length = 0;
130 ConvertPropVariantToUInt64(prop, length);
131 panelItem.PackSize = UInt32(length);
132 panelItem.PackSizeHigh = UInt32(length >> 32);
133
134 panelItem.Flags = 0;
135 panelItem.NumberOfLinks = 0;
136
137 panelItem.Description = NULL;
138 panelItem.Owner = NULL;
139 panelItem.CustomColumnData = NULL;
140 panelItem.CustomColumnNumber = 0;
141
142 panelItem.CRC32 = 0;
143 panelItem.Reserved[0] = 0;
144 panelItem.Reserved[1] = 0;
145 }
146
GetFindData(PluginPanelItem ** panelItems,int * itemsNumber,int opMode)147 int CPlugin::GetFindData(PluginPanelItem **panelItems, int *itemsNumber, int opMode)
148 {
149 // CScreenRestorer screenRestorer;
150 if ((opMode & OPM_SILENT) == 0 && (opMode & OPM_FIND ) == 0)
151 {
152 /*
153 screenRestorer.Save();
154 const char *msgItems[]=
155 {
156 g_StartupInfo.GetMsgString(NMessageID::kWaitTitle),
157 g_StartupInfo.GetMsgString(NMessageID::kReadingList)
158 };
159 g_StartupInfo.ShowMessage(0, NULL, msgItems, Z7_ARRAY_SIZE(msgItems), 0);
160 */
161 }
162
163 UInt32 numItems;
164 _folder->GetNumberOfItems(&numItems);
165 *panelItems = new PluginPanelItem[numItems];
166 try
167 {
168 for (UInt32 i = 0; i < numItems; i++)
169 {
170 PluginPanelItem &panelItem = (*panelItems)[i];
171 ReadPluginPanelItem(panelItem, i);
172 panelItem.UserData = i;
173 }
174 }
175 catch(...)
176 {
177 delete [](*panelItems);
178 throw;
179 }
180 *itemsNumber = (int)numItems;
181 return(TRUE);
182 }
183
FreeFindData(struct PluginPanelItem * panelItems,int itemsNumber)184 void CPlugin::FreeFindData(struct PluginPanelItem *panelItems, int itemsNumber)
185 {
186 for (int i = 0; i < itemsNumber; i++)
187 if (panelItems[i].Description != NULL)
188 delete []panelItems[i].Description;
189 delete []panelItems;
190 }
191
EnterToDirectory(const UString & dirName)192 void CPlugin::EnterToDirectory(const UString &dirName)
193 {
194 CMyComPtr<IFolderFolder> newFolder;
195 UString s = dirName;
196 if (dirName == kDotsReplaceStringU)
197 s = "..";
198 _folder->BindToFolder(s, &newFolder);
199 if (!newFolder)
200 {
201 if (dirName.IsEmpty())
202 return;
203 else
204 throw 40325;
205 }
206 _folder = newFolder;
207 }
208
SetDirectory(const char * aszDir,int)209 int CPlugin::SetDirectory(const char *aszDir, int /* opMode */)
210 {
211 UString path = MultiByteToUnicodeString(aszDir, CP_OEMCP);
212 if (path == WSTRING_PATH_SEPARATOR)
213 {
214 _folder.Release();
215 m_ArchiveHandler->BindToRootFolder(&_folder);
216 }
217 else if (path == L"..")
218 {
219 CMyComPtr<IFolderFolder> newFolder;
220 _folder->BindToParentFolder(&newFolder);
221 if (!newFolder)
222 throw 40312;
223 _folder = newFolder;
224 }
225 else if (path.IsEmpty())
226 EnterToDirectory(path);
227 else
228 {
229 if (path[0] == WCHAR_PATH_SEPARATOR)
230 {
231 _folder.Release();
232 m_ArchiveHandler->BindToRootFolder(&_folder);
233 path.DeleteFrontal(1);
234 }
235 UStringVector pathParts;
236 SplitPathToParts(path, pathParts);
237 FOR_VECTOR (i, pathParts)
238 EnterToDirectory(pathParts[i]);
239 }
240 SetCurrentDirVar();
241 return TRUE;
242 }
243
GetPathParts(UStringVector & pathParts)244 void CPlugin::GetPathParts(UStringVector &pathParts)
245 {
246 pathParts.Clear();
247 CMyComPtr<IFolderFolder> folderItem = _folder;
248 for (;;)
249 {
250 CMyComPtr<IFolderFolder> newFolder;
251 folderItem->BindToParentFolder(&newFolder);
252 if (!newFolder)
253 break;
254 NCOM::CPropVariant prop;
255 if (folderItem->GetFolderProperty(kpidName, &prop) == S_OK)
256 if (prop.vt == VT_BSTR)
257 pathParts.Insert(0, (const wchar_t *)prop.bstrVal);
258 folderItem = newFolder;
259 }
260 }
261
SetCurrentDirVar()262 void CPlugin::SetCurrentDirVar()
263 {
264 m_CurrentDir.Empty();
265
266 /*
267 // kpidPath path has tail slash, but we don't need it for compatibility with default FAR style
268 NCOM::CPropVariant prop;
269 if (_folder->GetFolderProperty(kpidPath, &prop) == S_OK)
270 if (prop.vt == VT_BSTR)
271 {
272 m_CurrentDir = (wchar_t *)prop.bstrVal;
273 // if (!m_CurrentDir.IsEmpty())
274 }
275 m_CurrentDir.InsertAtFront(WCHAR_PATH_SEPARATOR);
276 */
277
278 UStringVector pathParts;
279 GetPathParts(pathParts);
280 FOR_VECTOR (i, pathParts)
281 {
282 m_CurrentDir.Add_PathSepar();
283 m_CurrentDir += pathParts[i];
284 }
285 }
286
287 static const char * const kPluginFormatName = "7-ZIP";
288
289
FindPropNameID(PROPID propID)290 static int FindPropNameID(PROPID propID)
291 {
292 if (propID > NMessageID::k_Last_PropId_supported_by_plugin)
293 return -1;
294 return NMessageID::kNoProperty + (int)propID;
295 }
296
297 /*
298 struct CPropertyIDInfo
299 {
300 PROPID PropID;
301 const char *FarID;
302 int Width;
303 // char CharID;
304 };
305
306 static CPropertyIDInfo kPropertyIDInfos[] =
307 {
308 { kpidName, "N", 0},
309 { kpidSize, "S", 8},
310 { kpidPackSize, "P", 8},
311 { kpidAttrib, "A", 0},
312 { kpidCTime, "DC", 14},
313 { kpidATime, "DA", 14},
314 { kpidMTime, "DM", 14},
315
316 { kpidSolid, NULL, 0, 'S'},
317 { kpidEncrypted, NULL, 0, 'P'},
318
319 { kpidDictionarySize, IDS_PROPERTY_DICTIONARY_SIZE },
320 { kpidSplitBefore, NULL, 'B'},
321 { kpidSplitAfter, NULL, 'A'},
322 { kpidComment, NULL, 'C'},
323 { kpidCRC, IDS_PROPERTY_CRC }
324 // { kpidType, L"Type" }
325 };
326
327 static const int kNumPropertyIDInfos = Z7_ARRAY_SIZE(kPropertyIDInfos);
328
329 static int FindPropertyInfo(PROPID propID)
330 {
331 for (int i = 0; i < kNumPropertyIDInfos; i++)
332 if (kPropertyIDInfos[i].PropID == propID)
333 return i;
334 return -1;
335 }
336 */
337
338 // char *g_Titles[] = { "a", "f", "v" };
339 /*
340 static void SmartAddToString(AString &destString, const char *srcString)
341 {
342 if (!destString.IsEmpty())
343 destString += ',';
344 destString += srcString;
345 }
346 */
347
348 /*
349 void CPlugin::AddColumn(PROPID propID)
350 {
351 int index = FindPropertyInfo(propID);
352 if (index >= 0)
353 {
354 for (int i = 0; i < m_ProxyHandler->m_InternalProperties.Size(); i++)
355 {
356 const CArchiveItemProperty &aHandlerProperty = m_ProxyHandler->m_InternalProperties[i];
357 if (aHandlerProperty.ID == propID)
358 break;
359 }
360 if (i == m_ProxyHandler->m_InternalProperties.Size())
361 return;
362
363 const CPropertyIDInfo &propertyIDInfo = kPropertyIDInfos[index];
364 SmartAddToString(PanelModeColumnTypes, propertyIDInfo.FarID);
365 char tmp[32];
366 itoa(propertyIDInfo.Width, tmp, 10);
367 SmartAddToString(PanelModeColumnWidths, tmp);
368 return;
369 }
370 }
371 */
372
GetNameOfProp(PROPID propID,const wchar_t * name)373 static AString GetNameOfProp(PROPID propID, const wchar_t *name)
374 {
375 int farID = FindPropNameID(propID);
376 if (farID >= 0)
377 return (AString)g_StartupInfo.GetMsgString(farID);
378 if (name)
379 return UnicodeStringToMultiByte(name, CP_OEMCP);
380 char s[16];
381 ConvertUInt32ToString(propID, s);
382 return (AString)s;
383 }
384
GetNameOfProp2(PROPID propID,const wchar_t * name)385 static AString GetNameOfProp2(PROPID propID, const wchar_t *name)
386 {
387 AString s (GetNameOfProp(propID, name));
388 if (s.Len() > (kInfoPanelLineSize - 1))
389 s.DeleteFrom(kInfoPanelLineSize - 1);
390 return s;
391 }
392
ConvertSizeToString(UInt64 value)393 static AString ConvertSizeToString(UInt64 value)
394 {
395 char s[32];
396 ConvertUInt64ToString(value, s);
397 unsigned i = MyStringLen(s);
398 unsigned pos = Z7_ARRAY_SIZE(s);
399 s[--pos] = 0;
400 while (i > 3)
401 {
402 s[--pos] = s[--i];
403 s[--pos] = s[--i];
404 s[--pos] = s[--i];
405 s[--pos] = ' ';
406 }
407 while (i > 0)
408 s[--pos] = s[--i];
409 return (AString)(s + pos);
410 }
411
PropToString(const NCOM::CPropVariant & prop,PROPID propID)412 static AString PropToString(const NCOM::CPropVariant &prop, PROPID propID)
413 {
414 if (prop.vt == VT_BSTR)
415 {
416 AString s (UnicodeStringToMultiByte(prop.bstrVal, CP_OEMCP));
417 s.Replace((char)0xA, ' ');
418 s.Replace((char)0xD, ' ');
419 return s;
420 }
421 if (prop.vt == VT_BOOL)
422 {
423 int messageID = VARIANT_BOOLToBool(prop.boolVal) ?
424 NMessageID::kYes : NMessageID::kNo;
425 return (AString)g_StartupInfo.GetMsgString(messageID);
426 }
427 if (prop.vt != VT_EMPTY)
428 {
429 if ((prop.vt == VT_UI8 || prop.vt == VT_UI4) && (
430 propID == kpidSize ||
431 propID == kpidPackSize ||
432 propID == kpidNumSubDirs ||
433 propID == kpidNumSubFiles ||
434 propID == kpidNumBlocks ||
435 propID == kpidPhySize ||
436 propID == kpidHeadersSize ||
437 propID == kpidClusterSize ||
438 propID == kpidUnpackSize
439 ))
440 {
441 UInt64 v = 0;
442 ConvertPropVariantToUInt64(prop, v);
443 return ConvertSizeToString(v);
444 }
445 {
446 char sz[64];
447 ConvertPropertyToShortString2(sz, prop, propID);
448 return (AString)sz;
449 }
450 }
451 return AString();
452 }
453
PropToString2(const NCOM::CPropVariant & prop,PROPID propID)454 static AString PropToString2(const NCOM::CPropVariant &prop, PROPID propID)
455 {
456 AString s (PropToString(prop, propID));
457 if (s.Len() > (kInfoPanelLineSize - 1))
458 s.DeleteFrom(kInfoPanelLineSize - 1);
459 return s;
460 }
461
AddPropertyString(InfoPanelLine * lines,unsigned & numItems,PROPID propID,const wchar_t * name,const NCOM::CPropVariant & prop)462 static void AddPropertyString(InfoPanelLine *lines, unsigned &numItems, PROPID propID, const wchar_t *name,
463 const NCOM::CPropVariant &prop)
464 {
465 if (prop.vt != VT_EMPTY)
466 {
467 AString val (PropToString2(prop, propID));
468 if (!val.IsEmpty())
469 {
470 InfoPanelLine &item = lines[numItems++];
471 COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));
472 COPY_STR_LIMITED(item.Data, val);
473 }
474 }
475 }
476
InsertSeparator(InfoPanelLine * lines,unsigned & numItems)477 static void InsertSeparator(InfoPanelLine *lines, unsigned &numItems)
478 {
479 if (numItems < kNumInfoLinesMax)
480 {
481 InfoPanelLine &item = lines[numItems++];
482 *item.Text = 0;
483 *item.Data = 0;
484 item.Separator = TRUE;
485 }
486 }
487
GetOpenPluginInfo(struct OpenPluginInfo * info)488 void CPlugin::GetOpenPluginInfo(struct OpenPluginInfo *info)
489 {
490 info->StructSize = sizeof(*info);
491 info->Flags = OPIF_USEFILTER | OPIF_USESORTGROUPS | OPIF_USEHIGHLIGHTING |
492 OPIF_ADDDOTS | OPIF_COMPAREFATTIME;
493
494 COPY_STR_LIMITED(m_FileNameBuffer, UnicodeStringToMultiByte(fs2us(m_FileName), CP_OEMCP));
495 info->HostFile = m_FileNameBuffer; // test it it is not static
496
497 COPY_STR_LIMITED(m_CurrentDirBuffer, UnicodeStringToMultiByte(m_CurrentDir, CP_OEMCP));
498 info->CurDir = m_CurrentDirBuffer;
499
500 info->Format = kPluginFormatName;
501
502 {
503 UString name;
504 {
505 FString dirPrefix, fileName;
506 GetFullPathAndSplit(m_FileName, dirPrefix, fileName);
507 name = fs2us(fileName);
508 }
509
510 m_PannelTitle = ' ';
511 m_PannelTitle += _archiveTypeName;
512 m_PannelTitle.Add_Colon();
513 m_PannelTitle += name;
514 m_PannelTitle.Add_Space();
515 if (!m_CurrentDir.IsEmpty())
516 {
517 // m_PannelTitle += '\\';
518 m_PannelTitle += m_CurrentDir;
519 }
520
521 COPY_STR_LIMITED(m_PannelTitleBuffer, UnicodeStringToMultiByte(m_PannelTitle, CP_OEMCP));
522 info->PanelTitle = m_PannelTitleBuffer;
523
524 }
525
526 memset(m_InfoLines, 0, sizeof(m_InfoLines));
527 m_InfoLines[0].Text[0] = 0;
528 m_InfoLines[0].Separator = TRUE;
529
530 MyStringCopy(m_InfoLines[1].Text, g_StartupInfo.GetMsgString(NMessageID::kArchiveType));
531 MyStringCopy(m_InfoLines[1].Data, (const char *)UnicodeStringToMultiByte(_archiveTypeName, CP_OEMCP));
532
533 unsigned numItems = 2;
534
535 {
536 CMyComPtr<IFolderProperties> folderProperties;
537 _folder.QueryInterface(IID_IFolderProperties, &folderProperties);
538 if (folderProperties)
539 {
540 UInt32 numProps;
541 if (folderProperties->GetNumberOfFolderProperties(&numProps) == S_OK)
542 {
543 for (UInt32 i = 0; i < numProps && numItems < kNumInfoLinesMax; i++)
544 {
545 CMyComBSTR name;
546 PROPID propID;
547 VARTYPE vt;
548 if (folderProperties->GetFolderPropertyInfo(i, &name, &propID, &vt) != S_OK)
549 continue;
550 NCOM::CPropVariant prop;
551 if (_folder->GetFolderProperty(propID, &prop) != S_OK || prop.vt == VT_EMPTY)
552 continue;
553
554 InfoPanelLine &item = m_InfoLines[numItems++];
555 COPY_STR_LIMITED(item.Text, GetNameOfProp2(propID, name));
556 COPY_STR_LIMITED(item.Data, PropToString2(prop, propID));
557 }
558 }
559 }
560 }
561
562 /*
563 if (numItems < kNumInfoLinesMax)
564 {
565 InsertSeparator(m_InfoLines, numItems);
566 }
567 */
568
569 {
570 CMyComPtr<IGetFolderArcProps> getFolderArcProps;
571 _folder.QueryInterface(IID_IGetFolderArcProps, &getFolderArcProps);
572 if (getFolderArcProps)
573 {
574 CMyComPtr<IFolderArcProps> getProps;
575 getFolderArcProps->GetFolderArcProps(&getProps);
576 if (getProps)
577 {
578 UInt32 numLevels;
579 if (getProps->GetArcNumLevels(&numLevels) != S_OK)
580 numLevels = 0;
581 for (UInt32 level2 = 0; level2 < numLevels; level2++)
582 {
583 {
584 UInt32 level = numLevels - 1 - level2;
585 UInt32 numProps;
586 if (getProps->GetArcNumProps(level, &numProps) == S_OK)
587 {
588 InsertSeparator(m_InfoLines, numItems);
589 for (Int32 i = -3; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)
590 {
591 CMyComBSTR name;
592 PROPID propID;
593 VARTYPE vt;
594 switch (i)
595 {
596 case -3: propID = kpidPath; break;
597 case -2: propID = kpidType; break;
598 case -1: propID = kpidError; break;
599 default:
600 if (getProps->GetArcPropInfo(level, (UInt32)i, &name, &propID, &vt) != S_OK)
601 continue;
602 }
603 NCOM::CPropVariant prop;
604 if (getProps->GetArcProp(level, propID, &prop) != S_OK)
605 continue;
606 AddPropertyString(m_InfoLines, numItems, propID, name, prop);
607 }
608 }
609 }
610 if (level2 != numLevels - 1)
611 {
612 UInt32 level = numLevels - 1 - level2;
613 UInt32 numProps;
614 if (getProps->GetArcNumProps2(level, &numProps) == S_OK)
615 {
616 InsertSeparator(m_InfoLines, numItems);
617 for (Int32 i = 0; i < (Int32)numProps && numItems < kNumInfoLinesMax; i++)
618 {
619 CMyComBSTR name;
620 PROPID propID;
621 VARTYPE vt;
622 if (getProps->GetArcPropInfo2(level, (UInt32)i, &name, &propID, &vt) != S_OK)
623 continue;
624 NCOM::CPropVariant prop;
625 if (getProps->GetArcProp2(level, propID, &prop) != S_OK)
626 continue;
627 AddPropertyString(m_InfoLines, numItems, propID, name, prop);
628 }
629 }
630 }
631 }
632 }
633 }
634 }
635
636 //m_InfoLines[1].Separator = 0;
637
638 info->InfoLines = m_InfoLines;
639 info->InfoLinesNumber = (int)numItems;
640
641
642 info->DescrFiles = NULL;
643 info->DescrFilesNumber = 0;
644
645 PanelModeColumnTypes.Empty();
646 PanelModeColumnWidths.Empty();
647
648 /*
649 AddColumn(kpidName);
650 AddColumn(kpidSize);
651 AddColumn(kpidPackSize);
652 AddColumn(kpidMTime);
653 AddColumn(kpidCTime);
654 AddColumn(kpidATime);
655 AddColumn(kpidAttrib);
656
657 _panelMode.ColumnTypes = (char *)(const char *)PanelModeColumnTypes;
658 _panelMode.ColumnWidths = (char *)(const char *)PanelModeColumnWidths;
659 _panelMode.ColumnTitles = NULL;
660 _panelMode.FullScreen = TRUE;
661 _panelMode.DetailedStatus = FALSE;
662 _panelMode.AlignExtensions = FALSE;
663 _panelMode.CaseConversion = FALSE;
664 _panelMode.StatusColumnTypes = "N";
665 _panelMode.StatusColumnWidths = "0";
666 _panelMode.Reserved[0] = 0;
667 _panelMode.Reserved[1] = 0;
668
669 info->PanelModesArray = &_panelMode;
670 info->PanelModesNumber = 1;
671 */
672
673 info->PanelModesArray = NULL;
674 info->PanelModesNumber = 0;
675
676 info->StartPanelMode = 0;
677 info->StartSortMode = 0;
678 info->KeyBar = NULL;
679 info->ShortcutData = NULL;
680 }
681
682 struct CArchiveItemProperty
683 {
684 AString Name;
685 PROPID ID;
686 VARTYPE Type;
687 };
688
GetHex_A_minus10(unsigned v,unsigned a10)689 static inline char GetHex_A_minus10(unsigned v, unsigned a10)
690 {
691 return (char)(v < 10 ? v + '0' : v + a10);
692 }
693
ShowAttributesWindow()694 HRESULT CPlugin::ShowAttributesWindow()
695 {
696 PluginPanelItem pluginPanelItem;
697 if (!g_StartupInfo.ControlGetActivePanelCurrentItemInfo(pluginPanelItem))
698 return S_FALSE;
699 if (strcmp(pluginPanelItem.FindData.cFileName, "..") == 0 &&
700 NFind::NAttributes::IsDir(pluginPanelItem.FindData.dwFileAttributes))
701 return S_FALSE;
702 const UInt32 itemIndex = (UInt32)pluginPanelItem.UserData;
703
704 CObjectVector<CArchiveItemProperty> properties;
705 UInt32 numProps;
706 RINOK(_folder->GetNumberOfProperties(&numProps))
707 unsigned i;
708 for (i = 0; i < numProps; i++)
709 {
710 CMyComBSTR name;
711 PROPID propID;
712 VARTYPE vt;
713 RINOK(_folder->GetPropertyInfo(i, &name, &propID, &vt))
714 CArchiveItemProperty prop;
715 prop.Type = vt;
716 prop.ID = propID;
717 if (prop.ID == kpidPath)
718 prop.ID = kpidName;
719 prop.Name = GetNameOfProp(propID, name);
720 properties.Add(prop);
721 }
722
723 int size = 2;
724 CRecordVector<CInitDialogItem> initDialogItems;
725
726 int xSize = 70;
727 {
728 const CInitDialogItem idi =
729 { DI_DOUBLEBOX, 3, 1, xSize - 4, size - 2, false, false, 0, false, NMessageID::kProperties, NULL, NULL };
730 initDialogItems.Add(idi);
731 }
732
733 AStringVector values;
734
735 const int kStartY = 3;
736
737 for (i = 0; i < properties.Size(); i++)
738 {
739 const CArchiveItemProperty &property = properties[i];
740
741 const int startY = kStartY + (int)values.Size();
742
743 {
744 CInitDialogItem idi =
745 { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL };
746 idi.DataMessageId = FindPropNameID(property.ID);
747 if (idi.DataMessageId < 0)
748 idi.DataString = property.Name;
749 initDialogItems.Add(idi);
750 }
751
752 NCOM::CPropVariant prop;
753 RINOK(_folder->GetProperty(itemIndex, property.ID, &prop))
754 values.Add(PropToString(prop, property.ID));
755
756 {
757 const CInitDialogItem idi =
758 { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL };
759 initDialogItems.Add(idi);
760 }
761 }
762
763 CMyComPtr<IArchiveGetRawProps> _folderRawProps;
764 _folder.QueryInterface(IID_IArchiveGetRawProps, &_folderRawProps);
765
766 CObjectVector<CArchiveItemProperty> properties2;
767
768 if (_folderRawProps)
769 {
770 _folderRawProps->GetNumRawProps(&numProps);
771
772 for (i = 0; i < numProps; i++)
773 {
774 CMyComBSTR name;
775 PROPID propID;
776 if (_folderRawProps->GetRawPropInfo(i, &name, &propID) != S_OK)
777 continue;
778 CArchiveItemProperty prop;
779 prop.Type = VT_EMPTY;
780 prop.ID = propID;
781 if (prop.ID == kpidPath)
782 prop.ID = kpidName;
783 prop.Name = GetNameOfProp(propID, name);
784 properties2.Add(prop);
785 }
786
787 for (i = 0; i < properties2.Size(); i++)
788 {
789 const CArchiveItemProperty &property = properties2[i];
790 CMyComBSTR name;
791
792 const void *data;
793 UInt32 dataSize;
794 UInt32 propType;
795 if (_folderRawProps->GetRawProp(itemIndex, property.ID, &data, &dataSize, &propType) != S_OK)
796 continue;
797
798 if (dataSize != 0)
799 {
800 AString s;
801 if (property.ID == kpidNtSecure)
802 ConvertNtSecureToString((const Byte *)data, dataSize, s);
803 else
804 {
805 const UInt32 kMaxDataSize = 64;
806 if (dataSize > kMaxDataSize)
807 {
808 s += "data:";
809 s.Add_UInt32(dataSize);
810 }
811 else
812 {
813 const unsigned a = dataSize <= 8
814 && (property.ID == kpidCRC || property.ID == kpidChecksum)
815 ? 'A' - 10 : 'a' - 10;
816 for (UInt32 k = 0; k < dataSize; k++)
817 {
818 const unsigned b = ((const Byte *)data)[k];
819 s += GetHex_A_minus10(b >> 4, a);
820 s += GetHex_A_minus10(b & 15, a);
821 }
822 }
823 }
824
825 const int startY = kStartY + (int)values.Size();
826
827 {
828 CInitDialogItem idi =
829 { DI_TEXT, 5, startY, 0, 0, false, false, 0, false, 0, NULL, NULL };
830 idi.DataMessageId = FindPropNameID(property.ID);
831 if (idi.DataMessageId < 0)
832 idi.DataString = property.Name;
833 initDialogItems.Add(idi);
834 }
835
836 values.Add(s);
837
838 {
839 const CInitDialogItem idi =
840 { DI_TEXT, 30, startY, 0, 0, false, false, 0, false, -1, NULL, NULL };
841 initDialogItems.Add(idi);
842 }
843 }
844 }
845 }
846
847 const unsigned numLines = values.Size();
848 for (i = 0; i < numLines; i++)
849 {
850 CInitDialogItem &idi = initDialogItems[1 + i * 2 + 1];
851 idi.DataString = values[i];
852 }
853
854 const unsigned numDialogItems = initDialogItems.Size();
855
856 CObjArray<FarDialogItem> dialogItems(numDialogItems);
857 g_StartupInfo.InitDialogItems(initDialogItems.ConstData(), dialogItems, numDialogItems);
858
859 unsigned maxLen = 0;
860
861 for (i = 0; i < numLines; i++)
862 {
863 FarDialogItem &dialogItem = dialogItems[1 + i * 2];
864 unsigned len = (unsigned)strlen(dialogItem.Data);
865 if (len > maxLen)
866 maxLen = len;
867 }
868
869 unsigned maxLen2 = 0;
870 const unsigned kSpace = 10;
871
872 for (i = 0; i < numLines; i++)
873 {
874 FarDialogItem &dialogItem = dialogItems[1 + i * 2 + 1];
875 const unsigned len = (unsigned)strlen(dialogItem.Data);
876 if (len > maxLen2)
877 maxLen2 = len;
878 dialogItem.X1 = (int)(maxLen + kSpace);
879 }
880
881 size = (int)numLines + 6;
882 xSize = (int)(maxLen + kSpace + maxLen2 + 5);
883 FarDialogItem &firstDialogItem = dialogItems[0];
884 firstDialogItem.Y2 = size - 2;
885 firstDialogItem.X2 = xSize - 4;
886
887 /* int askCode = */ g_StartupInfo.ShowDialog(xSize, size, NULL, dialogItems, numDialogItems);
888 return S_OK;
889 }
890
ProcessKey(int key,unsigned controlState)891 int CPlugin::ProcessKey(int key, unsigned controlState)
892 {
893 if (key == VK_F7 && controlState == 0)
894 {
895 CreateFolder();
896 return TRUE;
897 }
898
899 if (controlState == PKF_CONTROL && key == 'A')
900 {
901 HRESULT result = ShowAttributesWindow();
902 if (result == S_OK)
903 return TRUE;
904 if (result == S_FALSE)
905 return FALSE;
906 throw "Error";
907 }
908
909 if ((controlState & PKF_ALT) != 0 && key == VK_F6)
910 {
911 FString folderPath;
912 if (!GetOnlyDirPrefix(m_FileName, folderPath))
913 return FALSE;
914 PanelInfo panelInfo;
915 g_StartupInfo.ControlGetActivePanelInfo(panelInfo);
916 GetFilesReal(panelInfo.SelectedItems,
917 (unsigned)panelInfo.SelectedItemsNumber, FALSE,
918 UnicodeStringToMultiByte(fs2us(folderPath), CP_OEMCP), OPM_SILENT, true);
919 g_StartupInfo.Control(this, FCTL_UPDATEPANEL, NULL);
920 g_StartupInfo.Control(this, FCTL_REDRAWPANEL, NULL);
921 g_StartupInfo.Control(this, FCTL_UPDATEANOTHERPANEL, NULL);
922 g_StartupInfo.Control(this, FCTL_REDRAWANOTHERPANEL, NULL);
923 return TRUE;
924 }
925
926 return FALSE;
927 }
928