summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/app.c4
-rw-r--r--src/app.h4
-rw-r--r--src/gemini.h43
-rw-r--r--src/gmcerts.c15
-rw-r--r--src/gmcerts.h6
-rw-r--r--src/gmrequest.c6
-rw-r--r--src/gmrequest.h7
-rw-r--r--src/gmutil.h39
-rw-r--r--src/ui/documentwidget.c15
10 files changed, 82 insertions, 60 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index de97bf0a..c6a8c666 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -41,7 +41,8 @@ set (SOURCES
41 src/main.c 41 src/main.c
42 src/app.c 42 src/app.c
43 src/app.h 43 src/app.h
44 src/gemini.h 44 src/gmcerts.c
45 src/gmcerts.h
45 src/gmdocument.c 46 src/gmdocument.c
46 src/gmdocument.h 47 src/gmdocument.h
47 src/gmrequest.c 48 src/gmrequest.c
diff --git a/src/app.c b/src/app.c
index 5d29da5b..46235206 100644
--- a/src/app.c
+++ b/src/app.c
@@ -1,5 +1,6 @@
1#include "app.h" 1#include "app.h"
2#include "embedded.h" 2#include "embedded.h"
3#include "gmcerts.h"
3#include "history.h" 4#include "history.h"
4#include "ui/command.h" 5#include "ui/command.h"
5#include "ui/window.h" 6#include "ui/window.h"
@@ -51,6 +52,7 @@ struct Impl_App {
51 iWindow * window; 52 iWindow * window;
52 iSortedArray tickers; 53 iSortedArray tickers;
53 iBool pendingRefresh; 54 iBool pendingRefresh;
55 iGmCerts * certs;
54 iHistory * history; 56 iHistory * history;
55 /* Preferences: */ 57 /* Preferences: */
56 iBool retainWindowSize; 58 iBool retainWindowSize;
@@ -144,6 +146,7 @@ static void init_App_(iApp *d, int argc, char **argv) {
144 d->window = NULL; 146 d->window = NULL;
145 d->retainWindowSize = iTrue; 147 d->retainWindowSize = iTrue;
146 d->pendingRefresh = iFalse; 148 d->pendingRefresh = iFalse;
149 d->certs = new_GmCerts(dataDir_App_);
147 d->history = new_History(); 150 d->history = new_History();
148 loadPrefs_App_(d); 151 loadPrefs_App_(d);
149 load_History(d->history, dataDir_App_); 152 load_History(d->history, dataDir_App_);
@@ -165,6 +168,7 @@ static void deinit_App(iApp *d) {
165 savePrefs_App_(d); 168 savePrefs_App_(d);
166 save_History(d->history, dataDir_App_); 169 save_History(d->history, dataDir_App_);
167 delete_History(d->history); 170 delete_History(d->history);
171 delete_GmCerts(d->certs);
168 deinit_SortedArray(&d->tickers); 172 deinit_SortedArray(&d->tickers);
169 delete_Window(d->window); 173 delete_Window(d->window);
170 d->window = NULL; 174 d->window = NULL;
diff --git a/src/app.h b/src/app.h
index 777692b0..23e30ea5 100644
--- a/src/app.h
+++ b/src/app.h
@@ -5,8 +5,9 @@
5#include <the_Foundation/string.h> 5#include <the_Foundation/string.h>
6#include <the_Foundation/time.h> 6#include <the_Foundation/time.h>
7 7
8iDeclareType(Window) 8iDeclareType(GmCerts)
9iDeclareType(History) 9iDeclareType(History)
10iDeclareType(Window)
10 11
11enum iAppEventMode { 12enum iAppEventMode {
12 waitForNewEvents_AppEventMode, 13 waitForNewEvents_AppEventMode,
@@ -25,6 +26,7 @@ void processEvents_App (enum iAppEventMode mode);
25iBool handleCommand_App (const char *cmd); 26iBool handleCommand_App (const char *cmd);
26void refresh_App (void); 27void refresh_App (void);
27 28
29iGmCerts * certs_App (void);
28const iHistory *history_App (void); 30const iHistory *history_App (void);
29 31
30iAny * findWidget_App (const char *id); 32iAny * findWidget_App (const char *id);
diff --git a/src/gemini.h b/src/gemini.h
deleted file mode 100644
index 564de65b..00000000
--- a/src/gemini.h
+++ /dev/null
@@ -1,43 +0,0 @@
1#pragma once
2
3#include <the_Foundation/string.h>
4
5/* Response status codes. */
6enum iGmStatusCode {
7 clientSide_GmStatusCode = -100, /* clientside status codes */
8 invalidRedirect_GmStatusCode,
9 invalidHeader_GmStatusCode,
10 unsupportedMimeType_GmStatusCode,
11 failedToOpenFile_GmStatusCode,
12 unknownStatusCode_GmStatusCode,
13 none_GmStatusCode = 0,
14 input_GmStatusCode = 10,
15 sensitiveInput_GmStatusCode = 11,
16 success_GmStatusCode = 20,
17 redirectTemporary_GmStatusCode = 30,
18 redirectPermanent_GmStatusCode = 31,
19 temporaryFailure_GmStatusCode = 40,
20 serverUnavailable_GmStatusCode = 41,
21 cgiError_GmStatusCode = 42,
22 proxyError_GmStatusCode = 43,
23 slowDown_GmStatusCode = 44,
24 permanentFailure_GmStatusCode = 50,
25 notFound_GmStatusCode = 51,
26 gone_GmStatusCode = 52,
27 proxyRequestRefused_GmStatusCode = 53,
28 badRequest_GmStatusCode = 59,
29 clientCertificateRequired_GmStatusCode = 60,
30 certificateNotAuthorized_GmStatusCode = 61,
31 certificateNotValid_GmStatusCode = 62,
32};
33
34iDeclareType(GmError)
35
36struct Impl_GmError {
37 iChar icon;
38 const char *title;
39 const char *info;
40};
41
42iBool isDefined_GmError (enum iGmStatusCode code);
43const iGmError * get_GmError (enum iGmStatusCode code);
diff --git a/src/gmcerts.c b/src/gmcerts.c
new file mode 100644
index 00000000..cb4d8477
--- /dev/null
+++ b/src/gmcerts.c
@@ -0,0 +1,15 @@
1#include "gmcerts.h"
2
3struct Impl_GmCerts {
4 iString saveDir;
5};
6
7iDefineTypeConstructionArgs(GmCerts, (const char *saveDir), saveDir)
8
9void init_GmCerts(iGmCerts *d, const char *saveDir) {
10 initCStr_String(&d->saveDir, saveDir);
11}
12
13void deinit_GmCerts(iGmCerts *d) {
14 deinit_String(&d->saveDir);
15}
diff --git a/src/gmcerts.h b/src/gmcerts.h
new file mode 100644
index 00000000..1990463c
--- /dev/null
+++ b/src/gmcerts.h
@@ -0,0 +1,6 @@
1#pragma once
2
3#include <the_Foundation/tlsrequest.h>
4
5iDeclareType(GmCerts)
6iDeclareTypeConstructionArgs(GmCerts, const char *saveDir)
diff --git a/src/gmrequest.c b/src/gmrequest.c
index f43e4220..32b386b2 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -20,6 +20,7 @@ struct Impl_GmRequest {
20 iObject object; 20 iObject object;
21 iMutex mutex; 21 iMutex mutex;
22 enum iGmRequestState state; 22 enum iGmRequestState state;
23 enum iGmRequestCertification certState;
23 iString url; 24 iString url;
24 iTlsRequest *req; 25 iTlsRequest *req;
25 enum iGmStatusCode code; 26 enum iGmStatusCode code;
@@ -37,6 +38,7 @@ iDefineAudienceGetter(GmRequest, finished)
37void init_GmRequest(iGmRequest *d) { 38void init_GmRequest(iGmRequest *d) {
38 init_Mutex(&d->mutex); 39 init_Mutex(&d->mutex);
39 d->state = initialized_GmRequestState; 40 d->state = initialized_GmRequestState;
41 d->certState = notApplicable_GmRequestCertification;
40 init_String(&d->url); 42 init_String(&d->url);
41 d->req = NULL; 43 d->req = NULL;
42 d->code = none_GmStatusCode; 44 d->code = none_GmStatusCode;
@@ -166,6 +168,7 @@ static void requestFinished_GmRequest_(iAnyObject *obj) {
166 d->state = finished_GmRequestState; 168 d->state = finished_GmRequestState;
167#if 1 169#if 1
168 /* Check the server certificate. */ { 170 /* Check the server certificate. */ {
171 d->certState = invalid_GmRequestCertification; /* check trust */
169 const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req); 172 const iTlsCertificate *cert = serverCertificate_TlsRequest(d->req);
170 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert))); 173 printf("Server certificate:\n%s\n", cstrLocal_String(pem_TlsCertificate(cert)));
171 iBlock *sha = fingerprint_TlsCertificate(cert); 174 iBlock *sha = fingerprint_TlsCertificate(cert);
@@ -208,6 +211,7 @@ void submit_GmRequest(iGmRequest *d) {
208 /* TODO: Check supported file types: images, audio */ 211 /* TODO: Check supported file types: images, audio */
209 /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */ 212 /* TODO: Detect text files based on contents? E.g., is the content valid UTF-8. */
210 d->code = success_GmStatusCode; 213 d->code = success_GmStatusCode;
214 d->certState = notApplicable_GmRequestCertification;
211 if (endsWithCase_String(path, ".gmi")) { 215 if (endsWithCase_String(path, ".gmi")) {
212 setCStr_String(&d->header, "text/gemini; charset=utf-8"); 216 setCStr_String(&d->header, "text/gemini; charset=utf-8");
213 } 217 }
@@ -235,11 +239,13 @@ void submit_GmRequest(iGmRequest *d) {
235 } 239 }
236 iRelease(f); 240 iRelease(f);
237 d->state = finished_GmRequestState; 241 d->state = finished_GmRequestState;
242 d->certState = notApplicable_GmRequestCertification;
238 iNotifyAudience(d, finished, GmRequestFinished); 243 iNotifyAudience(d, finished, GmRequestFinished);
239 return; 244 return;
240 } 245 }
241 else if (equalCase_Rangecc(&url.protocol, "data")) { 246 else if (equalCase_Rangecc(&url.protocol, "data")) {
242 d->code = success_GmStatusCode; 247 d->code = success_GmStatusCode;
248 d->certState = notApplicable_GmRequestCertification;
243 iString *src = collectNewCStr_String(url.protocol.start + 5); 249 iString *src = collectNewCStr_String(url.protocol.start + 5);
244 iRangecc header = { constBegin_String(src), constBegin_String(src) }; 250 iRangecc header = { constBegin_String(src), constBegin_String(src) };
245 while (header.end < constEnd_String(src) && *header.end != ',') { 251 while (header.end < constEnd_String(src) && *header.end != ',') {
diff --git a/src/gmrequest.h b/src/gmrequest.h
index 270f976a..37f324eb 100644
--- a/src/gmrequest.h
+++ b/src/gmrequest.h
@@ -16,6 +16,13 @@ iDeclareAudienceGetter(GmRequest, finished)
16void setUrl_GmRequest (iGmRequest *, const iString *url); 16void setUrl_GmRequest (iGmRequest *, const iString *url);
17void submit_GmRequest (iGmRequest *); 17void submit_GmRequest (iGmRequest *);
18 18
19enum iGmRequestCertification {
20 notApplicable_GmRequestCertification,
21 invalid_GmRequestCertification,
22 valid_GmRequestCertification,
23 expired_GmRequestCertification,
24};
25
19iBool isFinished_GmRequest (const iGmRequest *); 26iBool isFinished_GmRequest (const iGmRequest *);
20enum iGmStatusCode status_GmRequest (const iGmRequest *); 27enum iGmStatusCode status_GmRequest (const iGmRequest *);
21const iString * meta_GmRequest (const iGmRequest *); 28const iString * meta_GmRequest (const iGmRequest *);
diff --git a/src/gmutil.h b/src/gmutil.h
index 4a1fdee9..3342b262 100644
--- a/src/gmutil.h
+++ b/src/gmutil.h
@@ -3,8 +3,47 @@
3#include <the_Foundation/range.h> 3#include <the_Foundation/range.h>
4#include <the_Foundation/string.h> 4#include <the_Foundation/string.h>
5 5
6iDeclareType(GmError)
6iDeclareType(Url) 7iDeclareType(Url)
7 8
9/* Response status codes. */
10enum iGmStatusCode {
11 clientSide_GmStatusCode = -100, /* clientside status codes */
12 invalidRedirect_GmStatusCode,
13 invalidHeader_GmStatusCode,
14 unsupportedMimeType_GmStatusCode,
15 failedToOpenFile_GmStatusCode,
16 unknownStatusCode_GmStatusCode,
17 none_GmStatusCode = 0,
18 input_GmStatusCode = 10,
19 sensitiveInput_GmStatusCode = 11,
20 success_GmStatusCode = 20,
21 redirectTemporary_GmStatusCode = 30,
22 redirectPermanent_GmStatusCode = 31,
23 temporaryFailure_GmStatusCode = 40,
24 serverUnavailable_GmStatusCode = 41,
25 cgiError_GmStatusCode = 42,
26 proxyError_GmStatusCode = 43,
27 slowDown_GmStatusCode = 44,
28 permanentFailure_GmStatusCode = 50,
29 notFound_GmStatusCode = 51,
30 gone_GmStatusCode = 52,
31 proxyRequestRefused_GmStatusCode = 53,
32 badRequest_GmStatusCode = 59,
33 clientCertificateRequired_GmStatusCode = 60,
34 certificateNotAuthorized_GmStatusCode = 61,
35 certificateNotValid_GmStatusCode = 62,
36};
37
38struct Impl_GmError {
39 iChar icon;
40 const char *title;
41 const char *info;
42};
43
44iBool isDefined_GmError (enum iGmStatusCode code);
45const iGmError * get_GmError (enum iGmStatusCode code);
46
8struct Impl_Url { 47struct Impl_Url {
9 iRangecc protocol; 48 iRangecc protocol;
10 iRangecc host; 49 iRangecc host;
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index f8a2e330..954ded0c 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -145,21 +145,6 @@ void deinit_DocumentWidget(iDocumentWidget *d) {
145 SDL_FreeCursor(d->handCursor); 145 SDL_FreeCursor(d->handCursor);
146} 146}
147 147
148#if 0
149static iString *cleanUrl_(const iString *url) {
150 iString *clean = copy_String(url);
151 if (startsWith_String(url, "//")) {
152 prependCStr_String(clean, "gemini:");
153 }
154 else if (indexOfCStr_String(url, "://") == iInvalidPos && !startsWithCase_String(url, "gemini:")
155 && !startsWithCase_String(url, "data:")) {
156 /* Prepend default protocol. */
157 prependCStr_String(clean, "gemini://");
158 }
159 return clean;
160}
161#endif
162
163static int documentWidth_DocumentWidget_(const iDocumentWidget *d) { 148static int documentWidth_DocumentWidget_(const iDocumentWidget *d) {
164 const iWidget *w = constAs_Widget(d); 149 const iWidget *w = constAs_Widget(d);
165 const iRect bounds = bounds_Widget(w); 150 const iRect bounds = bounds_Widget(w);