summaryrefslogtreecommitdiff
path: root/src/gopher.c
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 /src/gopher.c
parent0e03a97ba89bb9e8fccf6978250addc14799c5c1 (diff)
Gopher improvements
Asking for query text with item type 7. Enhanced ASCII art detection.
Diffstat (limited to 'src/gopher.c')
-rw-r--r--src/gopher.c38
1 files changed, 31 insertions, 7 deletions
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;