summaryrefslogtreecommitdiff
path: root/src/mimehooks.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-12-02 07:26:33 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-12-02 07:26:33 +0200
commitcface45b7cfd084f65ead1d5bfa6ecdc639d7017 (patch)
tree0c2b7f900ee3f116474f9789173b60423b98cf4f /src/mimehooks.c
parent5b147a3976fcf007a75e9b16cc0cea96011f2e9b (diff)
Added MimeHooks
This is a very powerful mechanism: translate the contents of any request to something else when the original MIME type matches a configured regexp. The external hook command may still elect not to process the request.
Diffstat (limited to 'src/mimehooks.c')
-rw-r--r--src/mimehooks.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/mimehooks.c b/src/mimehooks.c
new file mode 100644
index 00000000..3d999aba
--- /dev/null
+++ b/src/mimehooks.c
@@ -0,0 +1,139 @@
1#include "mimehooks.h"
2
3#include <the_Foundation/file.h>
4#include <the_Foundation/path.h>
5#include <the_Foundation/process.h>
6#include <the_Foundation/stringlist.h>
7
8iDefineTypeConstruction(FilterHook)
9
10void init_FilterHook(iFilterHook *d) {
11 init_String(&d->label);
12 init_String(&d->mimePattern);
13 init_String(&d->command);
14 d->mimeRegex = NULL;
15}
16
17void deinit_FilterHook(iFilterHook *d) {
18 iRelease(d->mimeRegex);
19 deinit_String(&d->command);
20 deinit_String(&d->mimePattern);
21 deinit_String(&d->label);
22}
23
24void setMimePattern_FilterHook(iFilterHook *d, const iString *pattern) {
25 iReleasePtr(&d->mimeRegex);
26 d->mimeRegex = new_RegExp(cstr_String(pattern), caseInsensitive_RegExpOption);
27}
28
29void setCommand_FilterHook(iFilterHook *d, const iString *command) {
30 set_String(&d->command, command);
31}
32
33iBlock *run_FilterHook_(const iFilterHook *d, const iString *mime, const iBlock *body) {
34 iProcess * proc = new_Process();
35 iStringList *args = new_StringList();
36 iRangecc seg = iNullRange;
37 while (nextSplit_Rangecc(range_String(&d->command), ";", &seg)) {
38 pushBackRange_StringList(args, seg);
39 }
40 seg = iNullRange;
41 while (nextSplit_Rangecc(range_String(mime), ";", &seg)) {
42 pushBackRange_StringList(args, seg);
43 }
44 setArguments_Process(proc, args);
45 iRelease(args);
46 start_Process(proc);
47 writeInput_Process(proc, body);
48 waitForFinished_Process(proc);
49 iBlock *output = readOutput_Process(proc);
50 if (!startsWith_Rangecc(range_Block(output), "20")) {
51 /* Didn't produce valid output. */
52 delete_Block(output);
53 output = NULL;
54 }
55 iRelease(proc);
56 return output;
57}
58
59/*----------------------------------------------------------------------------------------------*/
60
61struct Impl_MimeHooks {
62 iPtrArray filters;
63};
64
65iDefineTypeConstruction(MimeHooks)
66
67void init_MimeHooks(iMimeHooks *d) {
68 init_PtrArray(&d->filters);
69}
70
71void deinit_MimeHooks(iMimeHooks *d) {
72 iForEach(PtrArray, i, &d->filters) {
73 delete_FilterHook(i.ptr);
74 }
75 deinit_PtrArray(&d->filters);
76}
77
78iBool willTryFilter_MimeHooks(const iMimeHooks *d, const iString *mime) {
79 /* TODO: Combine this function with tryFilter_MimeHooks? */
80 iRegExpMatch m;
81 iConstForEach(PtrArray, i, &d->filters) {
82 const iFilterHook *xc = i.ptr;
83 init_RegExpMatch(&m);
84 if (matchString_RegExp(xc->mimeRegex, mime, &m)) {
85 return iTrue;
86 }
87 }
88 return iFalse;
89}
90
91iBlock *tryFilter_MimeHooks(const iMimeHooks *d, const iString *mime, const iBlock *body) {
92 iRegExpMatch m;
93 iConstForEach(PtrArray, i, &d->filters) {
94 const iFilterHook *xc = i.ptr;
95 init_RegExpMatch(&m);
96 if (matchString_RegExp(xc->mimeRegex, mime, &m)) {
97 iBlock *result = run_FilterHook_(xc, mime, body);
98 if (result) {
99 return result;
100 }
101 }
102 }
103 return NULL;
104}
105
106static const char *mimeHooksFilename_MimeHooks_ = "mimehooks.txt";
107
108void load_MimeHooks(iMimeHooks *d, const char *saveDir) {
109 iFile *f = newCStr_File(concatPath_CStr(saveDir, mimeHooksFilename_MimeHooks_));
110 if (open_File(f, read_FileMode | text_FileMode)) {
111 iBlock * src = readAll_File(f);
112 iRangecc srcLine = iNullRange;
113 int pos = 0;
114 iRangecc lines[3];
115 iZap(lines);
116 while (nextSplit_Rangecc(range_Block(src), "\n", &srcLine)) {
117 iRangecc line = srcLine;
118 trim_Rangecc(&line);
119 if (isEmpty_Range(&line)) {
120 continue;
121 }
122 lines[pos++] = line;
123 if (pos == 3) {
124 iFilterHook *hook = new_FilterHook();
125 setRange_String(&hook->label, lines[0]);
126 setMimePattern_FilterHook(hook, collect_String(newRange_String(lines[1])));
127 setCommand_FilterHook(hook, collect_String(newRange_String(lines[2])));
128 pushBack_PtrArray(&d->filters, hook);
129 }
130 }
131 delete_Block(src);
132 }
133 iRelease(f);
134}
135
136void save_MimeHooks(const iMimeHooks *d) {
137 iUnused(d);
138}
139