draft `far:about`: separate FarAbout() function
[far2l.git] / inside / src / inside.cpp
blobdeb9695251ce70ed63463a3f032816a8f0694b40
1 #include "Globals.h"
2 #include "plain/PluginImplPlain.h"
3 #include <fcntl.h>
4 #ifndef __APPLE__
5 # include "elf/PluginImplELF.h"
6 # include <elf.h>
7 #endif
8 # include "Storage.h"
9 #include <sudo.h>
10 #include <utils.h>
12 SHAREDSYMBOL void PluginModuleOpen(const char *path)
14 G.plugin_path = path;
15 // fprintf(stderr, "Inside::PluginModuleOpen\n");
18 SHAREDSYMBOL int WINAPI _export GetMinFarVersion(void)
20 #define MAKEFARVERSION(major,minor) ( ((major)<<16) | (minor))
21 return MAKEFARVERSION(2, 1);
25 SHAREDSYMBOL void WINAPI _export SetStartupInfo(const struct PluginStartupInfo *Info)
27 G.Startup(Info);
28 // fprintf(stderr, "Inside::SetStartupInfo\n");
31 #define MINIMAL_LEN 0x34
33 static bool HasElvenEars(const unsigned char *Data, int DataSize)
35 #ifndef __APPLE__
36 //FAR reads at least 0x1000 bytes if possible, so may assume full ELF header available if its there
37 if (DataSize < MINIMAL_LEN || Data[0] != 0x7F || Data[1] != 'E'|| Data[2] != 'L'|| Data[3] != 'F')
38 return false;
39 if (Data[4] != 1 && Data[4] != 2) // Bitness: 32/64
40 return false;
41 if (Data[5] != 0 && Data[5] != 1 && Data[5] != 2) // Endianess: None(?)/LSB/MSB
42 return false;
43 if (Data[6] != 1) // Version: 1
44 return false;
46 return true;
47 #else
48 return false;
49 #endif
52 static const char *DetectPlainKind(const char *Name, const unsigned char *Data, int DataSize)
54 const char *ext = Name ? strrchr(Name, '.') : nullptr;
55 // %PDF-1.2
56 if (DataSize >= 8 && Data[0] == '%' && Data[1] == 'P' && Data[2] == 'D' && Data[3] == 'F' &&
57 Data[4] == '-' && Data[5] >= '0' && Data[5] <= '9' && Data[6] == '.' && Data[7] >= '0' && Data[7] <= '9') {
58 return "PDF";
60 } else if (DataSize >= 8 && Data[0] == 0xd0 && Data[1] == 0xcf && Data[2] == 0x11 && Data[3] == 0xE0 &&
61 Data[4] == 0xA1 && Data[5] == 0xB1 && Data[6] == 0x1A && Data[7] == 0xE1) {
62 if (!ext || strcasecmp(ext, ".doc") == 0) { // disinct from excel/ppt etc
63 return "DOC";
66 if (strcasecmp(ext, ".ppt") == 0) {
67 return "PPT";
70 if (strcasecmp(ext, ".xls") == 0) {
71 return "XLS";
74 } else if (DataSize >= 8 && Data[0] == '{' && Data[1] == '\\' && Data[2] == 'r' && Data[3] == 't' && Data[4] == 'f'
75 && ext && strcasecmp(ext, ".rtf") == 0) { // ensure
76 return "RTF";
78 } else if (DataSize >= 8 && Data[0] == 0xff && Data[1] == 0xd8 && Data[2] == 0xff
79 && ext && (strcasecmp(ext, ".jpg") == 0 || strcasecmp(ext, ".jpeg") == 0)) {
80 return "JPG";
82 } else if (DataSize >= 8 && Data[0] == 'A' && Data[1] == 'T' && Data[2] == '&' && Data[3] == 'T'
83 && Data[4] == 'F' && Data[5] == 'O' && Data[6] == 'R' && Data[7] == 'M'
84 && ext && strcasecmp(ext, ".djvu") == 0) { // Ensure
86 return "DJVU";
88 } else if (DataSize >= 8 && ext && strcasecmp(ext, ".mp3") == 0) {
89 return "MP3";
91 } else if (DataSize >= 8 && Data[0] == 'M' && Data[1] == 'A' && Data[2] == 'C'
92 && ext && strcasecmp(ext, ".ape") == 0) {
93 return "APE";
95 } else if (DataSize >= 8 && Data[0] == 'w' && Data[1] == 'v' && Data[2] == 'p' && Data[3] == 'k'
96 && ext && strcasecmp(ext, ".vw") == 0) {
97 return "WV";
99 } else if (DataSize >= 8 && Data[0] == 'f' && Data[1] == 'L' && Data[2] == 'a' && Data[3] == 'C'
100 && ext && strcasecmp(ext, ".flac") == 0) {
101 return "FLAC";
104 return nullptr;
108 SHAREDSYMBOL HANDLE WINAPI _export OpenFilePlugin(const char *Name, const unsigned char *Data, int DataSize, int OpMode)
110 if (!G.IsStarted())
111 return INVALID_HANDLE_VALUE;
113 const bool elf = HasElvenEars(Data, DataSize);
114 const char *plain = elf ? nullptr : DetectPlainKind(Name, Data, DataSize);
116 // fprintf(stderr, "Inside: OpenFilePlugin('%s' .. 0x%x): %s %s\n", Name, OpMode, elf ? "ELF" : "", plain ? plain : "");
118 if (!elf && !plain)
119 return INVALID_HANDLE_VALUE;
121 // Well, it really looks like valid ELF or some plain document file
123 if ( (OpMode & OPM_FIND) != 0) {
124 // In case of open from find file dialog - allow digging into plain document files,
125 // but not ELFs - there is nothing interesting to search inside of disasm etc.
126 if (elf)
127 return INVALID_HANDLE_VALUE;
129 } else if ((OpMode & (OPM_PGDN | OPM_COMMANDS)) == 0) {
130 // If user called us with Ctrl+PgDn - then proceed for any file
131 // Otherwise proceed only for ELF file and only if its not eXecutable, to allow user execute it by Enter
132 if (!elf)
133 return INVALID_HANDLE_VALUE;
135 struct stat s = {};
136 if (sdc_stat(Name, &s) == -1) // in case of any uncertainlity...
137 return INVALID_HANDLE_VALUE;
139 if ((s.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)
140 return INVALID_HANDLE_VALUE;
143 PluginImpl *out = nullptr;
144 #ifndef __APPLE__
145 if (elf) {
146 out = new PluginImplELF(Name, Data[4], Data[5]);
148 } else
149 #endif
150 if (plain) {
151 out = new PluginImplPlain(Name, plain);
152 } else {
153 ABORT();
156 return out ? (HANDLE)out : INVALID_HANDLE_VALUE;
160 SHAREDSYMBOL HANDLE WINAPI _export OpenPlugin(int OpenFrom, INT_PTR Item)
162 if (!G.IsStarted() || OpenFrom != OPEN_COMMANDLINE)
163 return INVALID_HANDLE_VALUE;
165 if (strncmp((const char *)Item, G.command_prefix.c_str(), G.command_prefix.size()) != 0
166 || ((const char *)Item)[G.command_prefix.size()] != ':') {
167 return INVALID_HANDLE_VALUE;
170 std::string path( &((const char *)Item)[G.command_prefix.size() + 1] );
171 if (path.size() >1 && path[0] == '\"' && path[path.size() - 1] == '\"')
172 path = path.substr(1, path.size() - 2);
173 if (path.empty())
174 return INVALID_HANDLE_VALUE;
176 int fd = sdc_open(path.c_str(), O_RDONLY);
177 if (fd == -1)
178 return INVALID_HANDLE_VALUE;
180 unsigned char data[MINIMAL_LEN];
181 int data_len = sdc_read(fd, data, sizeof(data));
182 sdc_close(fd);
183 return OpenFilePlugin(path.c_str(), data, data_len, OPM_COMMANDS);
186 SHAREDSYMBOL void WINAPI _export ClosePlugin(HANDLE hPlugin)
188 delete (PluginImpl *)hPlugin;
192 SHAREDSYMBOL int WINAPI _export GetFindData(HANDLE hPlugin,struct PluginPanelItem **pPanelItem,int *pItemsNumber,int OpMode)
194 return ((PluginImpl *)hPlugin)->GetFindData(pPanelItem, pItemsNumber, OpMode);
198 SHAREDSYMBOL void WINAPI _export FreeFindData(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber)
200 ((PluginImpl *)hPlugin)->FreeFindData(PanelItem, ItemsNumber);
204 SHAREDSYMBOL int WINAPI _export SetDirectory(HANDLE hPlugin,const char *Dir,int OpMode)
206 return ((PluginImpl *)hPlugin)->SetDirectory(Dir, OpMode);
210 SHAREDSYMBOL int WINAPI _export DeleteFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode)
212 return ((PluginImpl *)hPlugin)->DeleteFiles(PanelItem, ItemsNumber, OpMode);
216 SHAREDSYMBOL int WINAPI _export GetFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,
217 int ItemsNumber,int Move,char *DestPath,int OpMode)
219 return ((PluginImpl *)hPlugin)->GetFiles(PanelItem, ItemsNumber, Move, DestPath, OpMode);
223 SHAREDSYMBOL int WINAPI _export PutFiles(HANDLE hPlugin,struct PluginPanelItem *PanelItem,
224 int ItemsNumber,int Move,int OpMode)
226 return ((PluginImpl *)hPlugin)->PutFiles(PanelItem, ItemsNumber, Move, OpMode);
230 SHAREDSYMBOL void WINAPI _export ExitFAR()
235 SHAREDSYMBOL void WINAPI _export GetPluginInfo(struct PluginInfo *Info)
237 Info->StructSize = sizeof(*Info);
239 Info->Flags = PF_FULLCMDLINE;
240 static const char *PluginCfgStrings[1];
241 PluginCfgStrings[0] = (char*)G.GetMsg(MTitle);
242 Info->PluginConfigStrings = PluginCfgStrings;
243 Info->PluginConfigStringsNumber = ARRAYSIZE(PluginCfgStrings);
245 static char s_command_prefix[G.MAX_COMMAND_PREFIX + 1] = {}; // WHY?
246 strncpy(s_command_prefix, G.command_prefix.c_str(), sizeof(s_command_prefix));
247 Info->CommandPrefix = s_command_prefix;
250 SHAREDSYMBOL void WINAPI _export GetOpenPluginInfo(HANDLE hPlugin,struct OpenPluginInfo *Info)
252 ((PluginImpl *)hPlugin)->GetOpenPluginInfo(Info);
255 SHAREDSYMBOL int WINAPI _export ProcessHostFile(HANDLE hPlugin,struct PluginPanelItem *PanelItem,int ItemsNumber,int OpMode)
257 return ((PluginImpl *)hPlugin)->ProcessHostFile(PanelItem, ItemsNumber, OpMode);
260 SHAREDSYMBOL int WINAPI _export ProcessKey(HANDLE hPlugin,int Key,unsigned int ControlState)
262 return ((PluginImpl *)hPlugin)->ProcessKey(Key, ControlState);
265 SHAREDSYMBOL int WINAPI _export Configure(int ItemNumber)
267 if (!G.IsStarted())
268 return 0;
270 struct FarDialogItem fdi[] = {
271 {DI_DOUBLEBOX, 3, 1, 70, 5, 0, {}, 0, 0, {}},
272 {DI_TEXT, -1, 2, 0, 2, 0, {}, 0, 0, {}},
273 {DI_BUTTON, 0, 4, 0, 4, 0, {}, DIF_CENTERGROUP, 0, {}},
274 {DI_BUTTON, 0, 4, 0, 4, 0, {}, DIF_CENTERGROUP, 0, {}}
277 ArrayCpyZ(fdi[0].Data, G.GetMsg(MTitle));
278 ArrayCpyZ(fdi[1].Data, G.GetMsg(MDescription));
279 ArrayCpyZ(fdi[2].Data, G.GetMsg(MOK));
280 ArrayCpyZ(fdi[3].Data, G.GetMsg(MCleanup));
282 if (G.info.Dialog(G.info.ModuleNumber, -1, -1, 74, 7, NULL, fdi, ARRAYSIZE(fdi)) == 3) {
283 Storage::Clear();
285 return 1;