NetSurf
file.c
Go to the documentation of this file.
1/*
2 * Copyright 2010 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf.
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19/**
20 * \file
21 *
22 * file scheme URL handling. Based on the data fetcher by Rob Kendrick
23 *
24 * output dates and directory ordering are affected by the current locale
25 */
26
27#include "utils/config.h"
28
29#include <stdlib.h>
30#include <ctype.h>
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
35#include <errno.h>
36#include <stdbool.h>
37#include <string.h>
38#include <strings.h>
39#include <time.h>
40#include <stdio.h>
41#include <stdarg.h>
42#ifdef HAVE_MMAP
43#include <sys/mman.h>
44#endif
45#include <libwapcaplet/libwapcaplet.h>
46
47#include "netsurf/inttypes.h"
48#include "utils/nsurl.h"
49#include "utils/dirent.h"
50#include "utils/corestrings.h"
51#include "utils/messages.h"
52#include "utils/utils.h"
53#include "utils/log.h"
54#include "utils/time.h"
55#include "utils/ring.h"
56#include "utils/file.h"
57#include "netsurf/fetch.h"
59
60#include "content/fetch.h"
61#include "content/fetchers.h"
62#include "dirlist.h"
63#include "file.h"
64
65/* Maximum size of read buffer */
66#define FETCH_FILE_MAX_BUF_SIZE (1024 * 1024)
67
68/** Context for a fetch */
71
72 struct fetch *fetchh; /**< Handle for this fetch */
73
74 bool aborted; /**< Flag indicating fetch has been aborted */
75 bool locked; /**< Flag indicating entry is already entered */
76
77 nsurl *url; /**< The full url the fetch refers to */
78 char *path; /**< The actual path to be used with open() */
79
80 time_t file_etag; /**< Request etag for file (previous st.m_time) */
81};
82
83static struct fetch_file_context *ring = NULL;
84
85/** issue fetch callbacks with locking */
86static inline bool fetch_file_send_callback(const fetch_msg *msg,
87 struct fetch_file_context *ctx)
88{
89 ctx->locked = true;
90 fetch_send_callback(msg, ctx->fetchh);
91 ctx->locked = false;
92
93 return ctx->aborted;
94}
95
97 const char *fmt, ...)
98{
99 fetch_msg msg;
100 char header[64];
101 va_list ap;
102 int len;
103
104 va_start(ap, fmt);
105 len = vsnprintf(header, sizeof header, fmt, ap);
106 va_end(ap);
107
108 if (len >= (int)sizeof(header) || len < 0) {
109 return false;
110 }
111
112 msg.type = FETCH_HEADER;
113 msg.data.header_or_data.buf = (const uint8_t *) header;
114 msg.data.header_or_data.len = len;
115
116 return fetch_file_send_callback(&msg, ctx);
117}
118
119/** callback to initialise the file fetcher. */
120static bool fetch_file_initialise(lwc_string *scheme)
121{
122 return true;
123}
124
125/** callback to initialise the file fetcher. */
126static void fetch_file_finalise(lwc_string *scheme)
127{
128}
129
130static bool fetch_file_can_fetch(const nsurl *url)
131{
132 return true;
133}
134
135/** callback to set up a file fetch context. */
136static void *
138 nsurl *url,
139 bool only_2xx,
140 bool downgrade_tls,
141 const char *post_urlenc,
142 const struct fetch_multipart_data *post_multipart,
143 const char **headers)
144{
145 struct fetch_file_context *ctx;
146 int i;
147 nserror ret;
148
149 ctx = calloc(1, sizeof(*ctx));
150 if (ctx == NULL)
151 return NULL;
152
153 ret = guit->file->nsurl_to_path(url, &ctx->path);
154 if (ret != NSERROR_OK) {
155 free(ctx);
156 return NULL;
157 }
158
159 ctx->url = nsurl_ref(url);
160
161 /* Scan request headers looking for If-None-Match */
162 for (i = 0; headers[i] != NULL; i++) {
163 if (strncasecmp(headers[i], "If-None-Match:",
164 SLEN("If-None-Match:")) != 0) {
165 continue;
166 }
167
168 /* If-None-Match: "12345678" */
169 const char *d = headers[i] + SLEN("If-None-Match:");
170
171 /* Scan to first digit, if any */
172 while (*d != '\0' && (*d < '0' || '9' < *d))
173 d++;
174
175 /* Convert to time_t */
176 if (*d != '\0') {
177 ret = nsc_snptimet(d, strlen(d), &ctx->file_etag);
178 if (ret != NSERROR_OK) {
179 NSLOG(fetch, WARNING,
180 "Bad If-None-Match value");
181 }
182 }
183 }
184
185 ctx->fetchh = fetchh;
186
187 RING_INSERT(ring, ctx);
188
189 return ctx;
190}
191
192/** callback to free a file fetch */
193static void fetch_file_free(void *ctx)
194{
195 struct fetch_file_context *c = ctx;
196 nsurl_unref(c->url);
197 free(c->path);
198 free(ctx);
199}
200
201/** callback to start a file fetch */
202static bool fetch_file_start(void *ctx)
203{
204 return true;
205}
206
207/** callback to abort a file fetch */
208static void fetch_file_abort(void *ctx)
209{
210 struct fetch_file_context *c = ctx;
211
212 /* To avoid the poll loop having to deal with the fetch context
213 * disappearing from under it, we simply flag the abort here.
214 * The poll loop itself will perform the appropriate cleanup.
215 */
216 c->aborted = true;
217}
218
219static int fetch_file_errno_to_http_code(int error_no)
220{
221 switch (error_no) {
222 case ENAMETOOLONG:
223 return 400;
224 case EACCES:
225 return 403;
226 case ENOENT:
227 return 404;
228 default:
229 break;
230 }
231
232 return 500;
233}
234
235static void fetch_file_process_error(struct fetch_file_context *ctx, int code)
236{
237 fetch_msg msg;
238 char buffer[1024];
239 const char *title;
240 char key[8];
241
242 /* content is going to return error code */
243 fetch_set_http_code(ctx->fetchh, code);
244
245 /* content type */
246 if (fetch_file_send_header(ctx, "Content-Type: text/html"))
247 goto fetch_file_process_error_aborted;
248
249 snprintf(key, sizeof key, "HTTP%03d", code);
250 title = messages_get(key);
251
252 snprintf(buffer, sizeof buffer, "<html><head><title>%s</title></head>"
253 "<body><h1>%s</h1>"
254 "<p>Error %d while fetching file %s</p></body></html>",
255 title, title, code, nsurl_access(ctx->url));
256
257 msg.type = FETCH_DATA;
258 msg.data.header_or_data.buf = (const uint8_t *) buffer;
259 msg.data.header_or_data.len = strlen(buffer);
260 if (fetch_file_send_callback(&msg, ctx))
261 goto fetch_file_process_error_aborted;
262
263 msg.type = FETCH_FINISHED;
264 fetch_file_send_callback(&msg, ctx);
265
266fetch_file_process_error_aborted:
267 return;
268}
269
270
271/** Process object as a regular file */
273 struct stat *fdstat)
274{
275#ifdef HAVE_MMAP
276 fetch_msg msg;
277 char *buf = NULL;
278 size_t buf_size;
279
280 int fd; /**< The file descriptor of the object */
281
282 /* Check if we can just return not modified */
283 if (ctx->file_etag != 0 && ctx->file_etag == fdstat->st_mtime) {
284 fetch_set_http_code(ctx->fetchh, 304);
286 fetch_file_send_callback(&msg, ctx);
287 return;
288 }
289
290 fd = open(ctx->path, O_RDONLY);
291 if (fd < 0) {
292 /* process errors as appropriate */
295 return;
296 }
297
298 /* set buffer size */
299 buf_size = fdstat->st_size;
300
301 /* allocate the buffer storage */
302 if (buf_size > 0) {
303 buf = mmap(NULL, buf_size, PROT_READ, MAP_SHARED, fd, 0);
304 if (buf == MAP_FAILED) {
305 msg.type = FETCH_ERROR;
306 msg.data.error = "Unable to map memory for file data buffer";
307 fetch_file_send_callback(&msg, ctx);
308 close(fd);
309 return;
310 }
311 }
312
313 /* fetch is going to be successful */
314 fetch_set_http_code(ctx->fetchh, 200);
315
316 /* Any callback can result in the fetch being aborted.
317 * Therefore, we _must_ check for this after _every_ call to
318 * fetch_file_send_callback().
319 */
320
321 /* content type */
322 if (fetch_file_send_header(ctx, "Content-Type: %s",
323 guit->fetch->filetype(ctx->path))) {
324 goto fetch_file_process_aborted;
325 }
326
327 /* content length */
328 if (fetch_file_send_header(ctx, "Content-Length: %" PRIsizet,
329 fdstat->st_size)) {
330 goto fetch_file_process_aborted;
331 }
332
333 /* create etag */
334 if (fetch_file_send_header(ctx, "ETag: \"%10" PRId64 "\"",
335 (int64_t) fdstat->st_mtime)) {
336 goto fetch_file_process_aborted;
337 }
338
339 msg.type = FETCH_DATA;
340 msg.data.header_or_data.buf = (const uint8_t *) buf;
341 msg.data.header_or_data.len = buf_size;
342 fetch_file_send_callback(&msg, ctx);
343
344 if (ctx->aborted == false) {
345 msg.type = FETCH_FINISHED;
346 fetch_file_send_callback(&msg, ctx);
347 }
348
349fetch_file_process_aborted:
350
351 if (buf != NULL)
352 munmap(buf, buf_size);
353 close(fd);
354#else
355 fetch_msg msg;
356 char *buf;
357 size_t buf_size;
358
359 ssize_t tot_read = 0;
360 ssize_t res;
361
362 FILE *infile;
363
364 /* Check if we can just return not modified */
365 if (ctx->file_etag != 0 && ctx->file_etag == fdstat->st_mtime) {
366 fetch_set_http_code(ctx->fetchh, 304);
368 fetch_file_send_callback(&msg, ctx);
369 return;
370 }
371
372 infile = fopen(ctx->path, "rb");
373 if (infile == NULL) {
374 /* process errors as appropriate */
377 return;
378 }
379
380 /* set buffer size */
381 buf_size = fdstat->st_size;
382 if (buf_size > FETCH_FILE_MAX_BUF_SIZE)
383 buf_size = FETCH_FILE_MAX_BUF_SIZE;
384
385 /* allocate the buffer storage */
386 buf = malloc(buf_size);
387 if (buf == NULL) {
388 msg.type = FETCH_ERROR;
389 msg.data.error =
390 "Unable to allocate memory for file data buffer";
391 fetch_file_send_callback(&msg, ctx);
392 fclose(infile);
393 return;
394 }
395
396 /* fetch is going to be successful */
397 fetch_set_http_code(ctx->fetchh, 200);
398
399 /* Any callback can result in the fetch being aborted.
400 * Therefore, we _must_ check for this after _every_ call to
401 * fetch_file_send_callback().
402 */
403
404 /* content type */
405 if (fetch_file_send_header(ctx, "Content-Type: %s",
406 guit->fetch->filetype(ctx->path))) {
407 goto fetch_file_process_aborted;
408 }
409
410 /* content length */
411 if (fetch_file_send_header(ctx, "Content-Length: %" PRIsizet,
412 fdstat->st_size)) {
413 goto fetch_file_process_aborted;
414 }
415
416 /* create etag */
417 if (fetch_file_send_header(ctx, "ETag: \"%10" PRId64 "\"",
418 (int64_t) fdstat->st_mtime)) {
419 goto fetch_file_process_aborted;
420 }
421
422 /* main data loop */
423 while (tot_read < fdstat->st_size) {
424 res = fread(buf, 1, buf_size, infile);
425 if (res == 0) {
426 if (feof(infile)) {
427 msg.type = FETCH_ERROR;
428 msg.data.error = "Unexpected EOF reading file";
429 fetch_file_send_callback(&msg, ctx);
430 goto fetch_file_process_aborted;
431 } else {
432 msg.type = FETCH_ERROR;
433 msg.data.error = "Error reading file";
434 fetch_file_send_callback(&msg, ctx);
435 goto fetch_file_process_aborted;
436 }
437 }
438 tot_read += res;
439
440 msg.type = FETCH_DATA;
441 msg.data.header_or_data.buf = (const uint8_t *) buf;
442 msg.data.header_or_data.len = res;
443 if (fetch_file_send_callback(&msg, ctx))
444 break;
445 }
446
447 if (ctx->aborted == false) {
448 msg.type = FETCH_FINISHED;
449 fetch_file_send_callback(&msg, ctx);
450 }
451
452fetch_file_process_aborted:
453
454 fclose(infile);
455 free(buf);
456#endif
457 return;
458}
459
460static char *gen_nice_title(char *path)
461{
462 char *nice_path, *cnv, *tmp;
463 char *title;
464 int title_length;
465
466 /* Convert path for display */
467 nice_path = malloc(strlen(path) * SLEN("&amp;") + 1);
468 if (nice_path == NULL) {
469 return NULL;
470 }
471
472 /* Escape special HTML characters */
473 for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
474 if (*tmp == '<') {
475 *cnv++ = '&';
476 *cnv++ = 'l';
477 *cnv++ = 't';
478 *cnv++ = ';';
479 } else if (*tmp == '>') {
480 *cnv++ = '&';
481 *cnv++ = 'g';
482 *cnv++ = 't';
483 *cnv++ = ';';
484 } else if (*tmp == '&') {
485 *cnv++ = '&';
486 *cnv++ = 'a';
487 *cnv++ = 'm';
488 *cnv++ = 'p';
489 *cnv++ = ';';
490 } else {
491 *cnv++ = *tmp;
492 }
493 }
494 *cnv = '\0';
495
496 /* Construct a localised title string */
497 title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
498 title = malloc(title_length + 1);
499
500 if (title == NULL) {
501 free(nice_path);
502 return NULL;
503 }
504
505 /* Set title to localised "Index of <nice_path>" */
506 snprintf(title, title_length, messages_get("FileIndex"), nice_path);
507
508 free(nice_path);
509
510 return title;
511}
512
513/**
514 * Generate an output row of the directory listing.
515 *
516 * \param ctx The file fetching context.
517 * \param ent current directory entry.
518 * \param even is the row an even row.
519 * \param buffer The output buffer.
520 * \param buffer_len The space available in the output buffer.
521 * \return NSERROR_OK or error code on faliure.
522 */
523static nserror
525 struct dirent *ent,
526 bool even,
527 char *buffer,
528 size_t buffer_len)
529{
530 nserror ret;
531 char *urlpath = NULL; /* buffer for leaf entry path */
532 struct stat ent_stat; /* stat result of leaf entry */
533 char datebuf[64]; /* buffer for date text */
534 char timebuf[64]; /* buffer for time text */
535 nsurl *url;
536
537 /* skip hidden files */
538 if (ent->d_name[0] == '.') {
540 }
541
542 ret = netsurf_mkpath(&urlpath, NULL, 2, ctx->path, ent->d_name);
543 if (ret != NSERROR_OK) {
544 return ret;
545 }
546
547 if (stat(urlpath, &ent_stat) != 0) {
548 ent_stat.st_mode = 0;
549 datebuf[0] = 0;
550 timebuf[0] = 0;
551 } else {
552 /* Get date in output format. a (day of week) and b
553 * (month) are both affected by the locale
554 */
555 if (strftime((char *)&datebuf, sizeof datebuf, "%a %d %b %Y",
556 localtime(&ent_stat.st_mtime)) == 0) {
557 datebuf[0] = '-';
558 datebuf[1] = 0;
559 }
560
561 /* Get time in output format */
562 if (strftime((char *)&timebuf, sizeof timebuf, "%H:%M",
563 localtime(&ent_stat.st_mtime)) == 0) {
564 timebuf[0] = '-';
565 timebuf[1] = 0;
566 }
567 }
568
569 ret = guit->file->path_to_nsurl(urlpath, &url);
570 if (ret != NSERROR_OK) {
571 free(urlpath);
572 return ret;
573 }
574
575 if (S_ISREG(ent_stat.st_mode)) {
576 /* regular file */
578 false,
579 url,
580 ent->d_name,
581 guit->fetch->filetype(urlpath),
582 ent_stat.st_size,
583 datebuf, timebuf,
584 buffer, buffer_len);
585 } else if (S_ISDIR(ent_stat.st_mode)) {
586 /* directory */
588 true,
589 url,
590 ent->d_name,
591 messages_get("FileDirectory"),
592 -1,
593 datebuf, timebuf,
594 buffer, buffer_len);
595 } else {
596 /* something else */
598 false,
599 url,
600 ent->d_name,
601 "",
602 -1,
603 datebuf, timebuf,
604 buffer, buffer_len);
605 }
606
607 nsurl_unref(url);
608 free(urlpath);
609
610 return NSERROR_OK;
611}
612
613/**
614 * Comparison function for sorting directories.
615 *
616 * Correctly orders non zero-padded numerical parts.
617 * ie. produces "file1, file2, file10" rather than "file1, file10, file2".
618 *
619 * \param d1 first directory entry
620 * \param d2 second directory entry
621 */
622static int dir_sort_alpha(const struct dirent **d1, const struct dirent **d2)
623{
624 const char *s1 = (*d1)->d_name;
625 const char *s2 = (*d2)->d_name;
626
627 while (*s1 != '\0' && *s2 != '\0') {
628 if ((*s1 >= '0' && *s1 <= '9') &&
629 (*s2 >= '0' && *s2 <= '9')) {
630 int n1 = 0, n2 = 0;
631 while (*s1 >= '0' && *s1 <= '9') {
632 n1 = n1 * 10 + (*s1) - '0';
633 s1++;
634 }
635 while (*s2 >= '0' && *s2 <= '9') {
636 n2 = n2 * 10 + (*s2) - '0';
637 s2++;
638 }
639 if (n1 != n2) {
640 return n1 - n2;
641 }
642 if (*s1 == '\0' || *s2 == '\0')
643 break;
644 }
645 if (tolower(*s1) != tolower(*s2))
646 break;
647
648 s1++;
649 s2++;
650 }
651
652 return tolower(*s1) - tolower(*s2);
653}
654
656 struct stat *fdstat)
657{
658 fetch_msg msg;
659 char buffer[1024]; /* Output buffer */
660 bool even = false; /* formatting flag */
661 char *title; /* pretty printed title */
662 nserror err; /* result from url routines */
663 nsurl *up; /* url of parent */
664
665 struct dirent **listing = NULL; /* directory entry listing */
666 int i; /* directory entry index */
667 int n; /* number of directory entries */
668
669 n = scandir(ctx->path, &listing, 0, dir_sort_alpha);
670 if (n < 0) {
673 return;
674 }
675
676 /* fetch is going to be successful */
677 fetch_set_http_code(ctx->fetchh, 200);
678
679 /* force no-cache */
680 if (fetch_file_send_header(ctx, "Cache-Control: no-cache"))
681 goto fetch_file_process_dir_aborted;
682
683 /* content type */
684 if (fetch_file_send_header(ctx, "Content-Type: text/html"))
685 goto fetch_file_process_dir_aborted;
686
687 msg.type = FETCH_DATA;
688 msg.data.header_or_data.buf = (const uint8_t *) buffer;
689
690 /* directory listing top */
692 msg.data.header_or_data.len = strlen(buffer);
693 if (fetch_file_send_callback(&msg, ctx))
694 goto fetch_file_process_dir_aborted;
695
696 /* directory listing title */
697 title = gen_nice_title(ctx->path);
698 dirlist_generate_title(title, buffer, sizeof buffer);
699 free(title);
700 msg.data.header_or_data.len = strlen(buffer);
701 if (fetch_file_send_callback(&msg, ctx))
702 goto fetch_file_process_dir_aborted;
703
704 /* Print parent directory link */
705 err = nsurl_parent(ctx->url, &up);
706 if (err == NSERROR_OK) {
707 if (nsurl_compare(ctx->url, up, NSURL_COMPLETE) == false) {
708 /* different URL; have parent */
710 buffer, sizeof buffer);
711
712 msg.data.header_or_data.len = strlen(buffer);
713 fetch_file_send_callback(&msg, ctx);
714 }
715 nsurl_unref(up);
716
717 if (ctx->aborted)
718 goto fetch_file_process_dir_aborted;
719
720 }
721
722 /* directory list headings */
724 msg.data.header_or_data.len = strlen(buffer);
725 if (fetch_file_send_callback(&msg, ctx))
726 goto fetch_file_process_dir_aborted;
727
728 for (i = 0; i < n; i++) {
729
730 err = process_dir_ent(ctx, listing[i], even, buffer,
731 sizeof(buffer));
732
733 if (err == NSERROR_OK) {
734 msg.data.header_or_data.len = strlen(buffer);
735 if (fetch_file_send_callback(&msg, ctx))
736 goto fetch_file_process_dir_aborted;
737
738 even = !even;
739 }
740 }
741
742 /* directory listing bottom */
744 msg.data.header_or_data.len = strlen(buffer);
745 if (fetch_file_send_callback(&msg, ctx))
746 goto fetch_file_process_dir_aborted;
747
748 msg.type = FETCH_FINISHED;
749 fetch_file_send_callback(&msg, ctx);
750
751fetch_file_process_dir_aborted:
752
753 if (listing != NULL) {
754 for (i = 0; i < n; i++) {
755 free(listing[i]);
756 }
757 free(listing);
758 }
759}
760
761
762/* process a file fetch */
764{
765 struct stat fdstat; /**< The objects stat */
766
767 if (stat(ctx->path, &fdstat) != 0) {
768 /* process errors as appropriate */
771 return;
772 }
773
774 if (S_ISDIR(fdstat.st_mode)) {
775 /* directory listing */
776 fetch_file_process_dir(ctx, &fdstat);
777 return;
778 } else if (S_ISREG(fdstat.st_mode)) {
779 /* regular file */
780 fetch_file_process_plain(ctx, &fdstat);
781 return;
782 } else {
783 /* unhandled type of file */
784 fetch_file_process_error(ctx, 501);
785 }
786
787 return;
788}
789
790/** callback to poll for additional file fetch contents */
791static void fetch_file_poll(lwc_string *scheme)
792{
793 struct fetch_file_context *c, *save_ring = NULL;
794
795 while (ring != NULL) {
796 /* Take the first entry from the ring */
797 c = ring;
798 RING_REMOVE(ring, c);
799
800 /* Ignore fetches that have been flagged as locked.
801 * This allows safe re-entrant calls to this function.
802 * Re-entrancy can occur if, as a result of a callback,
803 * the interested party causes fetch_poll() to be called
804 * again.
805 */
806 if (c->locked == true) {
807 RING_INSERT(save_ring, c);
808 continue;
809 }
810
811 /* Only process non-aborted fetches */
812 if (c->aborted == false) {
813 /* file fetches can be processed in one go */
815 }
816
817 /* And now finish */
819 fetch_free(c->fetchh);
820
821 }
822
823 /* Finally, if we saved any fetches which were locked, put them back
824 * into the ring for next time
825 */
826 ring = save_ring;
827}
828
830{
831 lwc_string *scheme = lwc_string_ref(corestring_lwc_file);
832 const struct fetcher_operation_table fetcher_ops = {
834 .acceptable = fetch_file_can_fetch,
835 .setup = fetch_file_setup,
836 .start = fetch_file_start,
837 .abort = fetch_file_abort,
838 .free = fetch_file_free,
839 .poll = fetch_file_poll,
840 .finalise = fetch_file_finalise
841 };
842
843 return fetcher_add(scheme, &fetcher_ops);
844}
static osspriteop_area * buffer
The buffer characteristics.
Definition: buffer.c:55
void fetch_set_http_code(struct fetch *fetch, long http_code)
set the http code of a fetch
Definition: fetch.c:794
nserror fetcher_add(lwc_string *scheme, const struct fetcher_operation_table *ops)
Register a fetcher for a scheme.
Definition: fetch.c:357
void fetch_send_callback(const fetch_msg *msg, struct fetch *fetch)
send message to fetch
Definition: fetch.c:757
void fetch_free(struct fetch *f)
Free a fetch structure and associated resources.
Definition: fetch.c:548
void fetch_remove_from_queues(struct fetch *fetch)
remove a queued fetch
Definition: fetch.c:767
Fetching of data from a URL (interface).
@ FETCH_DATA
Definition: fetch.h:44
@ FETCH_HEADER
Definition: fetch.h:43
@ FETCH_NOTMODIFIED
Definition: fetch.h:50
@ FETCH_FINISHED
Definition: fetch.h:46
@ FETCH_ERROR
Definition: fetch.h:48
static void fetch_file_abort(void *ctx)
callback to abort a file fetch
Definition: file.c:208
static void fetch_file_process_error(struct fetch_file_context *ctx, int code)
Definition: file.c:235
static int fetch_file_errno_to_http_code(int error_no)
Definition: file.c:219
static void * fetch_file_setup(struct fetch *fetchh, nsurl *url, bool only_2xx, bool downgrade_tls, const char *post_urlenc, const struct fetch_multipart_data *post_multipart, const char **headers)
callback to set up a file fetch context.
Definition: file.c:137
static bool fetch_file_start(void *ctx)
callback to start a file fetch
Definition: file.c:202
static void fetch_file_process(struct fetch_file_context *ctx)
Definition: file.c:763
static bool fetch_file_initialise(lwc_string *scheme)
callback to initialise the file fetcher.
Definition: file.c:120
static void fetch_file_poll(lwc_string *scheme)
callback to poll for additional file fetch contents
Definition: file.c:791
static struct fetch_file_context * ring
Definition: file.c:83
static void fetch_file_process_dir(struct fetch_file_context *ctx, struct stat *fdstat)
Definition: file.c:655
static char * gen_nice_title(char *path)
Definition: file.c:460
nserror fetch_file_register(void)
Register file scheme handler.
Definition: file.c:829
static bool fetch_file_send_header(struct fetch_file_context *ctx, const char *fmt,...)
Definition: file.c:96
static int dir_sort_alpha(const struct dirent **d1, const struct dirent **d2)
Comparison function for sorting directories.
Definition: file.c:622
static void fetch_file_free(void *ctx)
callback to free a file fetch
Definition: file.c:193
static bool fetch_file_can_fetch(const nsurl *url)
Definition: file.c:130
static void fetch_file_finalise(lwc_string *scheme)
callback to initialise the file fetcher.
Definition: file.c:126
static void fetch_file_process_plain(struct fetch_file_context *ctx, struct stat *fdstat)
Process object as a regular file.
Definition: file.c:272
static nserror process_dir_ent(struct fetch_file_context *ctx, struct dirent *ent, bool even, char *buffer, size_t buffer_len)
Generate an output row of the directory listing.
Definition: file.c:524
#define FETCH_FILE_MAX_BUF_SIZE
Definition: file.c:66
static bool fetch_file_send_callback(const fetch_msg *msg, struct fetch_file_context *ctx)
issue fetch callbacks with locking
Definition: file.c:86
Useful interned string pointers (interface).
directory traversal and entry
bool dirlist_generate_row(bool even, bool directory, nsurl *url, char *name, const char *mimetype, long long size, char *date, char *time, char *buffer, int buffer_length)
Generates the part of an HTML directory listing page that displays a row in the directory contents ta...
Definition: dirlist.c:289
bool dirlist_generate_bottom(char *buffer, int buffer_length)
Generates the bottom part of an HTML directory listing page.
Definition: dirlist.c:344
bool dirlist_generate_title(const char *title, char *buffer, int buffer_length)
Generates the part of an HTML directory listing page that contains the title.
Definition: dirlist.c:143
bool dirlist_generate_parent_link(const char *parent, char *buffer, int buffer_length)
Generates the part of an HTML directory listing page that links to the parent directory.
Definition: dirlist.c:202
bool dirlist_generate_top(char *buffer, int buffer_length)
Generates the top part of an HTML directory listing page.
Definition: dirlist.c:61
bool dirlist_generate_headings(char *buffer, int buffer_length)
Generates the part of an HTML directory listing page that displays the column headings.
Definition: dirlist.c:237
interface to generate HTML content for displaying directory listings.
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_BAD_PARAMETER
Bad Parameter.
Definition: errors.h:48
@ NSERROR_OK
No error.
Definition: errors.h:30
Interface for fetchers factory.
struct netsurf_table * guit
The global interface table.
Definition: gui_factory.c:50
Interface to core interface table.
Interface to platform-specific fetcher operations.
Netsurf additional integer type formatting macros.
#define PRIsizet
c99 standard printf formatting for size_t type
Definition: inttypes.h:53
#define PRId64
Definition: inttypes.h:34
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get(const char *key)
Fast lookup of a message by key from the standard Messages hash.
Definition: messages.c:241
Localised message support (interface).
NetSurf URL handling (interface).
bool nsurl_compare(const nsurl *url1, const nsurl *url2, nsurl_component parts)
Compare two URLs.
void nsurl_unref(nsurl *url)
Drop a reference to a NetSurf URL object.
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
nsurl * nsurl_ref(nsurl *url)
Increment the reference count to a NetSurf URL object.
@ NSURL_COMPLETE
Definition: nsurl.h:54
struct nsurl nsurl
NetSurf URL object.
Definition: nsurl.h:31
nserror nsurl_parent(const nsurl *url, nsurl **new_url)
Create a NetSurf URL object for URL with parent location of an existing URL.
int scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
Definition: os3support.c:190
Ring list structure.
#define RING_REMOVE(ring, element)
Remove the given element from the specified ring.
Definition: ring.h:53
#define RING_INSERT(ring, element)
Insert the given item into the specified ring.
Definition: ring.h:40
Interface to utility string handling.
Context for a fetch.
Definition: file.c:69
nsurl * url
The full url the fetch refers to.
Definition: file.c:77
time_t file_etag
Request etag for file (previous st.m_time)
Definition: file.c:80
char * path
The actual path to be used with open()
Definition: file.c:78
bool locked
Flag indicating entry is already entered.
Definition: file.c:75
struct fetch * fetchh
Handle for this fetch.
Definition: file.c:72
struct fetch_file_context * r_next
Definition: file.c:70
bool aborted
Flag indicating fetch has been aborted.
Definition: file.c:74
struct fetch_file_context * r_prev
Definition: file.c:70
Fetcher message data.
Definition: fetch.h:72
const uint8_t * buf
Definition: fetch.h:79
fetch_msg_type type
Definition: fetch.h:73
struct fetch_msg::@118::@119 header_or_data
size_t len
Definition: fetch.h:80
union fetch_msg::@118 data
const char * error
Definition: fetch.h:83
Fetch POST multipart data.
Definition: fetch.h:109
Information for a single fetch.
Definition: fetch.c:89
Fetcher operations API.
Definition: fetchers.h:49
bool(* initialise)(lwc_string *scheme)
The initialiser for the fetcher.
Definition: fetchers.h:55
const char *(* filetype)(const char *unix_path)
Determine the MIME type of a local file.
Definition: fetch.h:45
nserror(* nsurl_to_path)(struct nsurl *url, char **path)
Create a path from a nsurl.
Definition: file.h:95
nserror(* path_to_nsurl)(const char *path, struct nsurl **url)
Create a nsurl from a path.
Definition: file.h:108
struct gui_file_table * file
File table.
Definition: gui_table.h:104
struct gui_fetch_table * fetch
Fetcher table.
Definition: gui_table.h:94
nserror nsc_snptimet(const char *str, size_t size, time_t *timep)
Parse time in seconds since epoc.
Definition: time.c:147
Interface to time operations.
nserror netsurf_mkpath(char **str, size_t *size, size_t nelm,...)
Generate a path from one or more component elemnts.
Definition: file.c:288
Default operations table for files.
Interface to a number of general purpose functionality.
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:88
static nserror path(const struct redraw_context *ctx, const plot_style_t *pstyle, const float *p, unsigned int n, const float transform[6])
Plots a path.
Definition: plot.c:821