summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-11-08 07:50:17 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-11-08 07:50:17 +0200
commitc0280998be065ab075581e46c52c6cc27e4b21a9 (patch)
tree9f4156beb6ef6a01605bafb8c81ae6885e8eced7
parent0e03a97ba89bb9e8fccf6978250addc14799c5c1 (diff)
Gopher improvements
Asking for query text with item type 7. Enhanced ASCII art detection.
-rw-r--r--src/gmrequest.c8
-rw-r--r--src/gopher.c38
-rw-r--r--src/gopher.h1
3 files changed, 39 insertions, 8 deletions
diff --git a/src/gmrequest.c b/src/gmrequest.c
index d143e8da..e65847e1 100644
--- a/src/gmrequest.c
+++ b/src/gmrequest.c
@@ -373,7 +373,7 @@ static void gopherError_GmRequest_(iGmRequest *d, iSocket *socket, int error, co
373 lock_Mutex(&d->mutex); 373 lock_Mutex(&d->mutex);
374 d->state = failure_GmRequestState; 374 d->state = failure_GmRequestState;
375 d->resp.statusCode = tlsFailure_GmStatusCode; 375 d->resp.statusCode = tlsFailure_GmStatusCode;
376 format_String(&d->resp.meta, "(%d) %s", error, msg); 376 format_String(&d->resp.meta, "%s (errno %d)", msg, error);
377 clear_Block(&d->resp.body); 377 clear_Block(&d->resp.body);
378 unlock_Mutex(&d->mutex); 378 unlock_Mutex(&d->mutex);
379 iNotifyAudience(d, finished, GmRequestFinished); 379 iNotifyAudience(d, finished, GmRequestFinished);
@@ -392,6 +392,12 @@ static void beginGopherConnection_GmRequest_(iGmRequest *d, const iString *host,
392 iConnect(Socket, d->gopher.socket, disconnected, d, gopherDisconnected_GmRequest_); 392 iConnect(Socket, d->gopher.socket, disconnected, d, gopherDisconnected_GmRequest_);
393 iConnect(Socket, d->gopher.socket, error, d, gopherError_GmRequest_); 393 iConnect(Socket, d->gopher.socket, error, d, gopherError_GmRequest_);
394 open_Gopher(&d->gopher, &d->url); 394 open_Gopher(&d->gopher, &d->url);
395 if (d->gopher.needQueryArgs) {
396 d->resp.statusCode = input_GmStatusCode;
397 setCStr_String(&d->resp.meta, "Enter query:");
398 d->state = finished_GmRequestState;
399 iNotifyAudience(d, finished, GmRequestFinished);
400 }
395} 401}
396 402
397/*----------------------------------------------------------------------------------------------*/ 403/*----------------------------------------------------------------------------------------------*/
diff --git a/src/gopher.c b/src/gopher.c
index 9a503442..dfdcf672 100644
--- a/src/gopher.c
+++ b/src/gopher.c
@@ -30,16 +30,20 @@ iLocalDef iBool isLineTerminator_(const char *str) {
30 return str[0] == '\r' && str[1] == '\n'; 30 return str[0] == '\r' && str[1] == '\n';
31} 31}
32 32
33iLocalDef iBool isDiagram_(char ch) {
34 return strchr("^*_-=~/|\\<>()[]{}", ch) != NULL;
35}
36
33static iBool isPreformatted_(iRangecc text) { 37static iBool isPreformatted_(iRangecc text) {
34 int numPunct = 0; 38 int numDiag = 0;
35 int numSpace = 0; 39 int numSpace = 0;
36 for (const char *ch = text.start; ch != text.end; ch++) { 40 for (const char *ch = text.start; ch != text.end; ch++) {
37 if (*ch > 32 && ispunct(*ch)) { 41 if (isDiagram_(*ch)) {
38 if (++numPunct == 4) 42 if (++numDiag == 3)
39 return iTrue; 43 return iTrue;
40 } 44 }
41 else { 45 else {
42 numPunct = 0; 46 numDiag = 0;
43 } 47 }
44 if (*ch == ' ' || *ch == '\n') { 48 if (*ch == ' ' || *ch == '\n') {
45 if (++numSpace == 3) return iTrue; 49 if (++numSpace == 3) return iTrue;
@@ -131,6 +135,7 @@ void init_Gopher(iGopher *d) {
131 d->socket = NULL; 135 d->socket = NULL;
132 d->type = 0; 136 d->type = 0;
133 init_Block(&d->source, 0); 137 init_Block(&d->source, 0);
138 d->needQueryArgs = iFalse;
134 d->isPre = iFalse; 139 d->isPre = iFalse;
135 d->meta = NULL; 140 d->meta = NULL;
136 d->output = NULL; 141 d->output = NULL;
@@ -142,9 +147,9 @@ void deinit_Gopher(iGopher *d) {
142} 147}
143 148
144void open_Gopher(iGopher *d, const iString *url) { 149void open_Gopher(iGopher *d, const iString *url) {
145 open_Socket(d->socket);
146 iUrl parts; 150 iUrl parts;
147 init_Url(&parts, url); 151 init_Url(&parts, url);
152 /* Determine Gopher item type. */
148 d->type = '1'; 153 d->type = '1';
149 if (!isEmpty_Range(&parts.path)) { 154 if (!isEmpty_Range(&parts.path)) {
150 if (*parts.path.start == '/') { 155 if (*parts.path.start == '/') {
@@ -155,12 +160,18 @@ void open_Gopher(iGopher *d, const iString *url) {
155 parts.path.start++; 160 parts.path.start++;
156 } 161 }
157 } 162 }
158 /* MIME type determined by the URI. */ 163 if (d->type == '7' && isEmpty_Range(&parts.query)) {
164 /* Ask for the query parameters first. */
165 d->needQueryArgs = iTrue;
166 return;
167 }
168 /* MIME type determined by the item type. */
159 switch (d->type) { 169 switch (d->type) {
160 case '0': 170 case '0':
161 setCStr_String(d->meta, "text/plain"); 171 setCStr_String(d->meta, "text/plain");
162 break; 172 break;
163 case '1': 173 case '1':
174 case '7':
164 setCStr_String(d->meta, "text/gemini"); 175 setCStr_String(d->meta, "text/gemini");
165 break; 176 break;
166 case '4': 177 case '4':
@@ -169,6 +180,12 @@ void open_Gopher(iGopher *d, const iString *url) {
169 case 'g': 180 case 'g':
170 setCStr_String(d->meta, "image/gif"); 181 setCStr_String(d->meta, "image/gif");
171 break; 182 break;
183 case 'h':
184 setCStr_String(d->meta, "text/html");
185 break;
186 case 'M':
187 setCStr_String(d->meta, "multipart/mixed");
188 break;
172 case 'I': 189 case 'I':
173 setCStr_String(d->meta, "image/generic"); 190 setCStr_String(d->meta, "image/generic");
174 break; 191 break;
@@ -180,7 +197,14 @@ void open_Gopher(iGopher *d, const iString *url) {
180 break; 197 break;
181 } 198 }
182 d->isPre = iFalse; 199 d->isPre = iFalse;
200 open_Socket(d->socket);
183 writeData_Socket(d->socket, parts.path.start, size_Range(&parts.path)); 201 writeData_Socket(d->socket, parts.path.start, size_Range(&parts.path));
202 if (!isEmpty_Range(&parts.query)) {
203 iAssert(*parts.query.start == '?');
204 parts.query.start++;
205 writeData_Socket(d->socket, "\t", 1);
206 writeData_Socket(d->socket, parts.query.start, size_Range(&parts.query));
207 }
184 writeData_Socket(d->socket, "\r\n", 2); 208 writeData_Socket(d->socket, "\r\n", 2);
185} 209}
186 210
@@ -192,7 +216,7 @@ void cancel_Gopher(iGopher *d) {
192 216
193iBool processResponse_Gopher(iGopher *d, const iBlock *data) { 217iBool processResponse_Gopher(iGopher *d, const iBlock *data) {
194 iBool changed = iFalse; 218 iBool changed = iFalse;
195 if (d->type == '1') { 219 if (d->type == '1' || d->type == '7') {
196 append_Block(&d->source, data); 220 append_Block(&d->source, data);
197 if (convertSource_Gopher_(d)) { 221 if (convertSource_Gopher_(d)) {
198 changed = iTrue; 222 changed = iTrue;
diff --git a/src/gopher.h b/src/gopher.h
index c085267b..3ad7e374 100644
--- a/src/gopher.h
+++ b/src/gopher.h
@@ -34,6 +34,7 @@ struct Impl_Gopher {
34 char type; 34 char type;
35 iBlock source; 35 iBlock source;
36 iBool isPre; 36 iBool isPre;
37 iBool needQueryArgs;
37 iString *meta; 38 iString *meta;
38 iBlock * output; 39 iBlock * output;
39}; 40};