summaryrefslogtreecommitdiff
path: root/src/mimehooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mimehooks.c')
-rw-r--r--src/mimehooks.c112
1 files changed, 10 insertions, 102 deletions
diff --git a/src/mimehooks.c b/src/mimehooks.c
index 931c8138..364449ec 100644
--- a/src/mimehooks.c
+++ b/src/mimehooks.c
@@ -23,9 +23,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
23#include "mimehooks.h" 23#include "mimehooks.h"
24#include "defs.h" 24#include "defs.h"
25#include "gmutil.h" 25#include "gmutil.h"
26#include "gempub.h"
26#include "app.h" 27#include "app.h"
27 28
28#include <the_Foundation/archive.h>
29#include <the_Foundation/file.h> 29#include <the_Foundation/file.h>
30#include <the_Foundation/fileinfo.h> 30#include <the_Foundation/fileinfo.h>
31#include <the_Foundation/path.h> 31#include <the_Foundation/path.h>
@@ -203,112 +203,20 @@ finished:
203 return output; 203 return output;
204} 204}
205 205
206static void appendGemPubProperty_(iString *out, const char *key, const iString *value) { 206iBlock *translateGemPubCoverPage_(const iBlock *source, const iString *requestUrl) {
207 if (!isEmpty_String(value)) {
208 appendFormat_String(out, "%s %s\n", key, cstr_String(value));
209 }
210}
211
212iBlock *translateGemPubCoverPage_(const iString *mime, const iBlock *source,
213 const iString *requestUrl) {
214 iBlock *output = NULL; 207 iBlock *output = NULL;
215 iArchive *arch = new_Archive(); 208 iGempub *gempub = new_Gempub();
216 if (openData_Archive(arch, source)) { 209 if (open_Gempub(gempub, source)) {
217 /* Parse the metadata and check if the required contents are present. */ 210 setBaseUrl_Gempub(gempub, requestUrl);
218 const iBlock *metadata = dataCStr_Archive(arch, "metadata.txt"); 211 output = newCStr_Block("20 text/gemini; charset=utf-8\r\n");
219 if (!metadata) { 212 append_Block(output, collect_Block(coverPageSource_Gempub(gempub)));
220 goto cleanup;
221 }
222 enum iGemPubProperty {
223 title_GemPubProperty,
224 index_GemPubProperty,
225 author_GemPubProperty,
226 language_GemPubProperty,
227 description_GemPubProperty,
228 published_GemPubProperty,
229 publishDate_GemPubProperty,
230 revisionDate_GemPubProperty,
231 copyright_GemPubProperty,
232 license_GemPubProperty,
233 version_GemPubProperty,
234 cover_GemPubProperty,
235 max_GemPubProperty
236 };
237 static const char *labels[max_GemPubProperty] = {
238 "title:",
239 "index:",
240 "author:",
241 "language:",
242 "description:",
243 "published:",
244 "publishDate:",
245 "revisionDate:",
246 "copyright:",
247 "license:",
248 "version:",
249 "cover:",
250 };
251 iString *props[max_GemPubProperty];
252 iForIndices(i, props) {
253 props[i] = collectNew_String();
254 }
255 /* Default values. */
256 setCStr_String(props[title_GemPubProperty], "Untitled Book");
257 setCStr_String(props[cover_GemPubProperty],
258 entryCStr_Archive(arch, "cover.jpg") ? "cover.jpg" :
259 entryCStr_Archive(arch, "cover.png") ? "cover.png" : "");
260 setCStr_String(props[index_GemPubProperty], "index.gmi");
261 iRangecc line = iNullRange;
262 while (nextSplit_Rangecc(range_Block(metadata), "\n", &line)) {
263 iRangecc clean = line;
264 trim_Rangecc(&clean);
265 iForIndices(i, props) {
266 if (startsWithCase_Rangecc(clean, labels[i])) {
267 setRange_String(props[i], (iRangecc){ clean.start + strlen(labels[i]), clean.end });
268 trim_String(props[i]);
269 }
270 }
271 }
272 const iString *baseUrl = withSpacesEncoded_String(requestUrl);
273 iString *out = new_String();
274 format_String(out, "20 text/gemini; charset=utf-8\r\n"
275 "# %s\n",
276 cstr_String(props[title_GemPubProperty]));
277 if (!isEmpty_String(props[description_GemPubProperty])) {
278 appendFormat_String(out, "%s\n", cstr_String(props[description_GemPubProperty]));
279 }
280 appendCStr_String(out, "\n");
281 appendGemPubProperty_(out, "Author:", props[author_GemPubProperty]);
282 appendFormat_String(out, "\n=> %s " book_Icon " Book index page\n",
283 cstrCollect_String(concat_Path(baseUrl, props[index_GemPubProperty])));
284 if (!isEmpty_String(props[cover_GemPubProperty])) {
285 appendFormat_String(out, "\n=> %s/%s Cover image\n",
286 cstr_String(baseUrl),
287 cstr_String(props[cover_GemPubProperty]));
288 }
289 appendCStr_String(out, "\n## About this book\n");
290 appendGemPubProperty_(out, "Version:", props[version_GemPubProperty]);
291 appendGemPubProperty_(out, "Revision date:", props[revisionDate_GemPubProperty]);
292 if (!isEmpty_String(props[publishDate_GemPubProperty])) {
293 appendGemPubProperty_(out, "Publish date:", props[publishDate_GemPubProperty]);
294 }
295 else {
296 appendGemPubProperty_(out, "Published:", props[published_GemPubProperty]);
297 }
298 appendGemPubProperty_(out, "Language:", props[language_GemPubProperty]);
299 appendGemPubProperty_(out, "License:", props[license_GemPubProperty]);
300 appendGemPubProperty_(out, "\u00a9", props[copyright_GemPubProperty]);
301 output = copy_Block(utf8_String(out));
302 delete_String(out);
303 } 213 }
304cleanup: 214 delete_Gempub(gempub);
305 iRelease(arch);
306 return output; 215 return output;
307} 216}
308 217
309/*----------------------------------------------------------------------------------------------*/ 218/*----------------------------------------------------------------------------------------------*/
310 219
311static const char *gpubMimeType_MimeHooks_ = "application/gpub+zip";
312static const char *mimeHooksFilename_MimeHooks_ = "mimehooks.txt"; 220static const char *mimeHooksFilename_MimeHooks_ = "mimehooks.txt";
313 221
314struct Impl_MimeHooks { 222struct Impl_MimeHooks {
@@ -331,7 +239,7 @@ void deinit_MimeHooks(iMimeHooks *d) {
331static iBool checkGemPub_(const iString *mime, const iString *requestUrl) { 239static iBool checkGemPub_(const iString *mime, const iString *requestUrl) {
332 /* Only process GemPub in local files. */ 240 /* Only process GemPub in local files. */
333 return (equalCase_Rangecc(urlScheme_String(requestUrl), "file") && 241 return (equalCase_Rangecc(urlScheme_String(requestUrl), "file") &&
334 startsWithCase_String(mime, gpubMimeType_MimeHooks_)); 242 startsWithCase_String(mime, mimeType_Gempub));
335} 243}
336 244
337iBool willTryFilter_MimeHooks(const iMimeHooks *d, const iString *mime) { 245iBool willTryFilter_MimeHooks(const iMimeHooks *d, const iString *mime) {
@@ -367,7 +275,7 @@ iBlock *tryFilter_MimeHooks(const iMimeHooks *d, const iString *mime, const iBlo
367 } 275 }
368 /* Built-in filters. */ 276 /* Built-in filters. */
369 if (checkGemPub_(mime, requestUrl)) { 277 if (checkGemPub_(mime, requestUrl)) {
370 iBlock *result = translateGemPubCoverPage_(mime, body, requestUrl); 278 iBlock *result = translateGemPubCoverPage_(body, requestUrl);
371 if (result) { 279 if (result) {
372 return result; 280 return result;
373 } 281 }