diff options
Diffstat (limited to 'src/gopher.c')
-rw-r--r-- | src/gopher.c | 38 |
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 | ||
33 | iLocalDef iBool isDiagram_(char ch) { | ||
34 | return strchr("^*_-=~/|\\<>()[]{}", ch) != NULL; | ||
35 | } | ||
36 | |||
33 | static iBool isPreformatted_(iRangecc text) { | 37 | static 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 | ||
144 | void open_Gopher(iGopher *d, const iString *url) { | 149 | void 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 | ||
193 | iBool processResponse_Gopher(iGopher *d, const iBlock *data) { | 217 | iBool 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; |