summaryrefslogtreecommitdiff
path: root/src/gmrequest.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/gmrequest.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/gmrequest.c')
-rw-r--r--src/gmrequest.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c
index b51d3b1f..572e6a5c 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -25,6 +25,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
25#include "gmcerts.h" 25#include "gmcerts.h"
26#include "gopher.h" 26#include "gopher.h"
27#include "app.h" /* dataDir_App() */ 27#include "app.h" /* dataDir_App() */
28#include "mimehooks.h"
28#include "feeds.h" 29#include "feeds.h"
29#include "ui/text.h" 30#include "ui/text.h"
30#include "embedded.h" 31#include "embedded.h"
@@ -131,7 +132,8 @@ struct Impl_GmRequest {
131 iTlsRequest * req; 132 iTlsRequest * req;
132 iGopher gopher; 133 iGopher gopher;
133 iGmResponse * resp; 134 iGmResponse * resp;
134 iBool respLocked; 135 iBool isRespLocked;
136 iBool isRespFiltered;
135 iAtomicInt allowUpdate; 137 iAtomicInt allowUpdate;
136 iAudience * updated; 138 iAudience * updated;
137 iAudience * finished; 139 iAudience * finished;
@@ -164,13 +166,10 @@ static void checkServerCertificate_GmRequest_(iGmRequest *d) {
164 } 166 }
165} 167}
166 168
167static void readIncoming_GmRequest_(iGmRequest *d, iTlsRequest *req) { 169static int processIncomingData_GmRequest_(iGmRequest *d, const iBlock *data) {
168 iBool notifyUpdate = iFalse; 170 iBool notifyUpdate = iFalse;
169 iBool notifyDone = iFalse; 171 iBool notifyDone = iFalse;
170 lock_Mutex(d->mtx); 172 iGmResponse *resp = d->resp;
171 iGmResponse *resp =d->resp;
172 iAssert(d->state != finished_GmRequestState); /* notifications out of order? */
173 iBlock *data = readAll_TlsRequest(req);
174 if (d->state == receivingHeader_GmRequestState) { 173 if (d->state == receivingHeader_GmRequestState) {
175 appendCStrN_String(&resp->meta, constData_Block(data), size_Block(data)); 174 appendCStrN_String(&resp->meta, constData_Block(data), size_Block(data));
176 /* Check if the header line is complete. */ 175 /* Check if the header line is complete. */
@@ -208,6 +207,9 @@ static void readIncoming_GmRequest_(iGmRequest *d, iTlsRequest *req) {
208 resp->statusCode = code; 207 resp->statusCode = code;
209 d->state = receivingBody_GmRequestState; 208 d->state = receivingBody_GmRequestState;
210 notifyUpdate = iTrue; 209 notifyUpdate = iTrue;
210 if (willTryFilter_MimeHooks(mimeHooks_App(), &resp->meta)) {
211 d->isRespFiltered = iTrue;
212 }
211 } 213 }
212 checkServerCertificate_GmRequest_(d); 214 checkServerCertificate_GmRequest_(d);
213 iRelease(metaPattern); 215 iRelease(metaPattern);
@@ -217,10 +219,21 @@ static void readIncoming_GmRequest_(iGmRequest *d, iTlsRequest *req) {
217 append_Block(&resp->body, data); 219 append_Block(&resp->body, data);
218 notifyUpdate = iTrue; 220 notifyUpdate = iTrue;
219 } 221 }
222 return (notifyUpdate ? 1 : 0) | (notifyDone ? 2 : 0);
223}
224
225static void readIncoming_GmRequest_(iGmRequest *d, iTlsRequest *req) {
226 lock_Mutex(d->mtx);
227 iGmResponse *resp = d->resp;
228 iAssert(d->state != finished_GmRequestState); /* notifications out of order? */
229 iBlock * data = readAll_TlsRequest(req);
230 const int ubits = processIncomingData_GmRequest_(d, data);
231 iBool notifyUpdate = (ubits & 1) != 0;
232 iBool notifyDone = (ubits & 2) != 0;
220 initCurrent_Time(&resp->when); 233 initCurrent_Time(&resp->when);
221 delete_Block(data); 234 delete_Block(data);
222 unlock_Mutex(d->mtx); 235 unlock_Mutex(d->mtx);
223 if (notifyUpdate) { 236 if (notifyUpdate && !d->isRespFiltered) {
224 const iBool allowed = exchange_Atomic(&d->allowUpdate, iFalse); 237 const iBool allowed = exchange_Atomic(&d->allowUpdate, iFalse);
225 if (allowed) { 238 if (allowed) {
226 iNotifyAudience(d, updated, GmRequestUpdated); 239 iNotifyAudience(d, updated, GmRequestUpdated);
@@ -247,7 +260,18 @@ static void requestFinished_GmRequest_(iGmRequest *d, iTlsRequest *req) {
247 set_String(&d->resp->meta, errorMessage_TlsRequest(req)); 260 set_String(&d->resp->meta, errorMessage_TlsRequest(req));
248 } 261 }
249 checkServerCertificate_GmRequest_(d); 262 checkServerCertificate_GmRequest_(d);
250 unlock_Mutex(d->mtx); 263 /* Check for mimehooks. */
264 if (d->isRespFiltered && d->state == finished_GmRequestState) {
265 iBlock *xbody = tryFilter_MimeHooks(mimeHooks_App(), &d->resp->meta, &d->resp->body);
266 if (xbody) {
267 clear_String(&d->resp->meta);
268 clear_Block(&d->resp->body);
269 d->state = receivingHeader_GmRequestState;
270 processIncomingData_GmRequest_(d, xbody);
271 d->state = finished_GmRequestState;
272 }
273 }
274 unlock_Mutex(d->mtx);
251 iNotifyAudience(d, finished, GmRequestFinished); 275 iNotifyAudience(d, finished, GmRequestFinished);
252} 276}
253 277
@@ -425,7 +449,8 @@ static void beginGopherConnection_GmRequest_(iGmRequest *d, const iString *host,
425void init_GmRequest(iGmRequest *d, iGmCerts *certs) { 449void init_GmRequest(iGmRequest *d, iGmCerts *certs) {
426 d->mtx = new_Mutex(); 450 d->mtx = new_Mutex();
427 d->resp = new_GmResponse(); 451 d->resp = new_GmResponse();
428 d->respLocked = iFalse; 452 d->isRespLocked = iFalse;
453 d->isRespFiltered = iFalse;
429 set_Atomic(&d->allowUpdate, iTrue); 454 set_Atomic(&d->allowUpdate, iTrue);
430 init_String(&d->url); 455 init_String(&d->url);
431 init_Gopher(&d->gopher); 456 init_Gopher(&d->gopher);
@@ -623,16 +648,16 @@ void cancel_GmRequest(iGmRequest *d) {
623} 648}
624 649
625iGmResponse *lockResponse_GmRequest(iGmRequest *d) { 650iGmResponse *lockResponse_GmRequest(iGmRequest *d) {
626 iAssert(!d->respLocked); 651 iAssert(!d->isRespLocked);
627 lock_Mutex(d->mtx); 652 lock_Mutex(d->mtx);
628 d->respLocked = iTrue; 653 d->isRespLocked = iTrue;
629 return d->resp; 654 return d->resp;
630} 655}
631 656
632void unlockResponse_GmRequest(iGmRequest *d) { 657void unlockResponse_GmRequest(iGmRequest *d) {
633 if (d) { 658 if (d) {
634 iAssert(d->respLocked); 659 iAssert(d->isRespLocked);
635 d->respLocked = iFalse; 660 d->isRespLocked = iFalse;
636 set_Atomic(&d->allowUpdate, iTrue); 661 set_Atomic(&d->allowUpdate, iTrue);
637 unlock_Mutex(d->mtx); 662 unlock_Mutex(d->mtx);
638 } 663 }