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; charset=utf-8"))
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,
253 "<html><head>"
254 "<title>%s</title>"
255 "<link rel=\"stylesheet\" type=\"text/css\" "
256 "href=\"resource:internal.css\">\n"
257 "</head>"
258 "<body class=\"ns-even-bg ns-even-fg ns-border\" "
259 "id =\"fetcherror\">\n"
260 "<h1 class=\"ns-border ns-odd-fg-bad\">%s</h1>\n"
261 "<p>%s %d %s %s</p>\n"
262 "</body>\n</html>\n",
263 title, title,
264 messages_get("FetchErrorCode"), code,
265 messages_get("FetchFile"), nsurl_access(ctx->url));
266
267 msg.type = FETCH_DATA;
268 msg.data.header_or_data.buf = (const uint8_t *) buffer;
269 msg.data.header_or_data.len = strlen(buffer);
270 if (fetch_file_send_callback(&msg, ctx))
271 goto fetch_file_process_error_aborted;
272
273 msg.type = FETCH_FINISHED;
274 fetch_file_send_callback(&msg, ctx);
275
276fetch_file_process_error_aborted:
277 return;
278}
279
280
281/** Process object as a regular file */
283 struct stat *fdstat)
284{
285#ifdef HAVE_MMAP
286 fetch_msg msg;
287 char *buf = NULL;
288 size_t buf_size;
289
290 int fd; /**< The file descriptor of the object */
291
292 /* Check if we can just return not modified */
293 if (ctx->file_etag != 0 && ctx->file_etag == fdstat->st_mtime) {
294 fetch_set_http_code(ctx->fetchh, 304);
296 fetch_file_send_callback(&msg, ctx);
297 return;
298 }
299
300 fd = open(ctx->path, O_RDONLY);
301 if (fd < 0) {
302 /* process errors as appropriate */
305 return;
306 }
307
308 /* set buffer size */
309 buf_size = fdstat->st_size;
310
311 /* allocate the buffer storage */
312 if (buf_size > 0) {
313 buf = mmap(NULL, buf_size, PROT_READ, MAP_SHARED, fd, 0);
314 if (buf == MAP_FAILED) {
315 msg.type = FETCH_ERROR;
316 msg.data.error = "Unable to map memory for file data buffer";
317 fetch_file_send_callback(&msg, ctx);
318 close(fd);
319 return;
320 }
321 }
322
323 /* fetch is going to be successful */
324 fetch_set_http_code(ctx->fetchh, 200);
325
326 /* Any callback can result in the fetch being aborted.
327 * Therefore, we _must_ check for this after _every_ call to
328 * fetch_file_send_callback().
329 */
330
331 /* content type */
332 if (fetch_file_send_header(ctx, "Content-Type: %s",
333 guit->fetch->filetype(ctx->path))) {
334 goto fetch_file_process_aborted;
335 }
336
337 /* content length */
338 if (fetch_file_send_header(ctx, "Content-Length: %" PRIsizet,
339 fdstat->st_size)) {
340 goto fetch_file_process_aborted;
341 }
342
343 /* create etag */
344 if (fetch_file_send_header(ctx, "ETag: \"%10" PRId64 "\"",
345 (int64_t) fdstat->st_mtime)) {
346 goto fetch_file_process_aborted;
347 }
348
349 msg.type = FETCH_DATA;
350 msg.data.header_or_data.buf = (const uint8_t *) buf;
351 msg.data.header_or_data.len = buf_size;
352 fetch_file_send_callback(&msg, ctx);
353
354 if (ctx->aborted == false) {
355 msg.type = FETCH_FINISHED;
356 fetch_file_send_callback(&msg, ctx);
357 }
358
359fetch_file_process_aborted:
360
361 if (buf != NULL)
362 munmap(buf, buf_size);
363 close(fd);
364#else
365 fetch_msg msg;
366 char *buf;
367 size_t buf_size;
368
369 ssize_t tot_read = 0;
370 ssize_t res;
371
372 FILE *infile;
373
374 /* Check if we can just return not modified */
375 if (ctx->file_etag != 0 && ctx->file_etag == fdstat->st_mtime) {
376 fetch_set_http_code(ctx->fetchh, 304);
378 fetch_file_send_callback(&msg, ctx);
379 return;
380 }
381
382 infile = fopen(ctx->path, "rb");
383 if (infile == NULL) {
384 /* process errors as appropriate */
387 return;
388 }
389
390 /* set buffer size */
391 buf_size = fdstat->st_size;
392 if (buf_size > FETCH_FILE_MAX_BUF_SIZE)
393 buf_size = FETCH_FILE_MAX_BUF_SIZE;
394
395 /* allocate the buffer storage */
396 buf = malloc(buf_size);
397 if (buf == NULL) {
398 msg.type = FETCH_ERROR;
399 msg.data.error =
400 "Unable to allocate memory for file data buffer";
401 fetch_file_send_callback(&msg, ctx);
402 fclose(infile);
403 return;
404 }
405
406 /* fetch is going to be successful */
407 fetch_set_http_code(ctx->fetchh, 200);
408
409 /* Any callback can result in the fetch being aborted.
410 * Therefore, we _must_ check for this after _every_ call to
411 * fetch_file_send_callback().
412 */
413
414 /* content type */
415 if (fetch_file_send_header(ctx, "Content-Type: %s",
416 guit->fetch->filetype(ctx->path))) {
417 goto fetch_file_process_aborted;
418 }
419
420 /* content length */
421 if (fetch_file_send_header(ctx, "Content-Length: %" PRIsizet,
422 fdstat->st_size)) {
423 goto fetch_file_process_aborted;
424 }
425
426 /* create etag */
427 if (fetch_file_send_header(ctx, "ETag: \"%10" PRId64 "\"",
428 (int64_t) fdstat->st_mtime)) {
429 goto fetch_file_process_aborted;
430 }
431
432 /* main data loop */
433 while (tot_read < fdstat->st_size) {
434 res = fread(buf, 1, buf_size, infile);
435 if (res == 0) {
436 if (feof(infile)) {
437 msg.type = FETCH_ERROR;
438 msg.data.error = "Unexpected EOF reading file";
439 fetch_file_send_callback(&msg, ctx);
440 goto fetch_file_process_aborted;
441 } else {
442 msg.type = FETCH_ERROR;
443 msg.data.error = "Error reading file";
444 fetch_file_send_callback(&msg, ctx);
445 goto fetch_file_process_aborted;
446 }
447 }
448 tot_read += res;
449
450 msg.type = FETCH_DATA;
451 msg.data.header_or_data.buf = (const uint8_t *) buf;
452 msg.data.header_or_data.len = res;
453 if (fetch_file_send_callback(&msg, ctx))
454 break;
455 }
456
457 if (ctx->aborted == false) {
458 msg.type = FETCH_FINISHED;
459 fetch_file_send_callback(&msg, ctx);
460 }
461
462fetch_file_process_aborted:
463
464 fclose(infile);
465 free(buf);
466#endif
467 return;
468}
469
470static char *gen_nice_title(char *path)
471{
472 char *nice_path, *cnv, *tmp;
473 char *title;
474 int title_length;
475
476 /* Convert path for display */
477 nice_path = malloc(strlen(path) * SLEN("&amp;") + 1);
478 if (nice_path == NULL) {
479 return NULL;
480 }
481
482 /* Escape special HTML characters */
483 for (cnv = nice_path, tmp = path; *tmp != '\0'; tmp++) {
484 if (*tmp == '<') {
485 *cnv++ = '&';
486 *cnv++ = 'l';
487 *cnv++ = 't';
488 *cnv++ = ';';
489 } else if (*tmp == '>') {
490 *cnv++ = '&';
491 *cnv++ = 'g';
492 *cnv++ = 't';
493 *cnv++ = ';';
494 } else if (*tmp == '&') {
495 *cnv++ = '&';
496 *cnv++ = 'a';
497 *cnv++ = 'm';
498 *cnv++ = 'p';
499 *cnv++ = ';';
500 } else {
501 *cnv++ = *tmp;
502 }
503 }
504 *cnv = '\0';
505
506 /* Construct a localised title string */
507 title_length = (cnv - nice_path) + strlen(messages_get("FileIndex"));
508 title = malloc(title_length + 1);
509
510 if (title == NULL) {
511 free(nice_path);
512 return NULL;
513 }
514
515 /* Set title to localised "Index of <nice_path>" */
516 snprintf(title, title_length, messages_get("FileIndex"), nice_path);
517
518 free(nice_path);
519
520 return title;
521}
522
523/**
524 * Generate an output row of the directory listing.
525 *
526 * \param ctx The file fetching context.
527 * \param ent current directory entry.
528 * \param even is the row an even row.
529 * \param buffer The output buffer.
530 * \param buffer_len The space available in the output buffer.
531 * \return NSERROR_OK or error code on faliure.
532 */
533static nserror
535 struct dirent *ent,
536 bool even,
537 char *buffer,
538 size_t buffer_len)
539{
540 nserror ret;
541 char *urlpath = NULL; /* buffer for leaf entry path */
542 struct stat ent_stat; /* stat result of leaf entry */
543 char datebuf[64]; /* buffer for date text */
544 char timebuf[64]; /* buffer for time text */
545 nsurl *url;
546
547 /* skip hidden files */
548 if (ent->d_name[0] == '.') {
550 }
551
552 ret = netsurf_mkpath(&urlpath, NULL, 2, ctx->path, ent->d_name);
553 if (ret != NSERROR_OK) {
554 return ret;
555 }
556
557 if (stat(urlpath, &ent_stat) != 0) {
558 ent_stat.st_mode = 0;
559 datebuf[0] = 0;
560 timebuf[0] = 0;
561 } else {
562 /* Get date in output format. a (day of week) and b
563 * (month) are both affected by the locale
564 */
565 if (strftime((char *)&datebuf, sizeof datebuf, "%a %d %b %Y",
566 localtime(&ent_stat.st_mtime)) == 0) {
567 datebuf[0] = '-';
568 datebuf[1] = 0;
569 }
570
571 /* Get time in output format */
572 if (strftime((char *)&timebuf, sizeof timebuf, "%H:%M",
573 localtime(&ent_stat.st_mtime)) == 0) {
574 timebuf[0] = '-';
575 timebuf[1] = 0;
576 }
577 }
578
579 ret = guit->file->path_to_nsurl(urlpath, &url);
580 if (ret != NSERROR_OK) {
581 free(urlpath);
582 return ret;
583 }
584
585 if (S_ISREG(ent_stat.st_mode)) {
586 /* regular file */
588 false,
589 url,
590 ent->d_name,
591 guit->fetch->filetype(urlpath),
592 ent_stat.st_size,
593 datebuf, timebuf,
594 buffer, buffer_len);
595 } else if (S_ISDIR(ent_stat.st_mode)) {
596 /* directory */
598 true,
599 url,
600 ent->d_name,
601 messages_get("FileDirectory"),
602 -1,
603 datebuf, timebuf,
604 buffer, buffer_len);
605 } else {
606 /* something else */
608 false,
609 url,
610 ent->d_name,
611 "",
612 -1,
613 datebuf, timebuf,
614 buffer, buffer_len);
615 }
616
617 nsurl_unref(url);
618 free(urlpath);
619
620 return NSERROR_OK;
621}
622
623/**
624 * Comparison function for sorting directories.
625 *
626 * Correctly orders non zero-padded numerical parts.
627 * ie. produces "file1, file2, file10" rather than "file1, file10, file2".
628 *
629 * \param d1 first directory entry
630 * \param d2 second directory entry
631 */
632static int dir_sort_alpha(const struct dirent **d1, const struct dirent **d2)
633{
634 const char *s1 = (*d1)->d_name;
635 const char *s2 = (*d2)->d_name;
636
637 while (*s1 != '\0' && *s2 != '\0') {
638 if ((*s1 >= '0' && *s1 <= '9') &&
639 (*s2 >= '0' && *s2 <= '9')) {
640 int n1 = 0, n2 = 0;
641 while (*s1 >= '0' && *s1 <= '9') {
642 n1 = n1 * 10 + (*s1) - '0';
643 s1++;
644 }
645 while (*s2 >= '0' && *s2 <= '9') {
646 n2 = n2 * 10 + (*s2) - '0';
647 s2++;
648 }
649 if (n1 != n2) {
650 return n1 - n2;
651 }
652 if (*s1 == '\0' || *s2 == '\0')
653 break;
654 }
655 if (tolower(*s1) != tolower(*s2))
656 break;
657
658 s1++;
659 s2++;
660 }
661
662 return tolower(*s1) - tolower(*s2);
663}
664
666 struct stat *fdstat)
667{
668 fetch_msg msg;
669 char buffer[1024]; /* Output buffer */
670 bool even = false; /* formatting flag */
671 char *title; /* pretty printed title */
672 nserror err; /* result from url routines */
673 nsurl *up; /* url of parent */
674
675 struct dirent **listing = NULL; /* directory entry listing */
676 int i; /* directory entry index */
677 int n; /* number of directory entries */
678
679 n = scandir(ctx->path, &listing, 0, dir_sort_alpha);
680 if (n < 0) {
683 return;
684 }
685
686 /* fetch is going to be successful */
687 fetch_set_http_code(ctx->fetchh, 200);
688
689 /* force no-cache */
690 if (fetch_file_send_header(ctx, "Cache-Control: no-cache"))
691 goto fetch_file_process_dir_aborted;
692
693 /* content type */
694 if (fetch_file_send_header(ctx, "Content-Type: text/html; charset=utf-8"))
695 goto fetch_file_process_dir_aborted;
696
697 msg.type = FETCH_DATA;
698 msg.data.header_or_data.buf = (const uint8_t *) buffer;
699
700 /* directory listing top */
702 msg.data.header_or_data.len = strlen(buffer);
703 if (fetch_file_send_callback(&msg, ctx))
704 goto fetch_file_process_dir_aborted;
705
706 /* directory listing title */
707 title = gen_nice_title(ctx->path);
708 dirlist_generate_title(title, buffer, sizeof buffer);
709 free(title);
710 msg.data.header_or_data.len = strlen(buffer);
711 if (fetch_file_send_callback(&msg, ctx))
712 goto fetch_file_process_dir_aborted;
713
714 /* Print parent directory link */
715 err = nsurl_parent(ctx->url, &up);
716 if (err == NSERROR_OK) {
717 if (nsurl_compare(ctx->url, up, NSURL_COMPLETE) == false) {
718 /* different URL; have parent */
720 buffer, sizeof buffer);
721
722 msg.data.header_or_data.len = strlen(buffer);
723 fetch_file_send_callback(&msg, ctx);
724 }
725 nsurl_unref(up);
726
727 if (ctx->aborted)
728 goto fetch_file_process_dir_aborted;
729
730 }
731
732 /* directory list headings */
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 for (i = 0; i < n; i++) {
739
740 err = process_dir_ent(ctx, listing[i], even, buffer,
741 sizeof(buffer));
742
743 if (err == NSERROR_OK) {
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 even = !even;
749 }
750 }
751
752 /* directory listing bottom */
754 msg.data.header_or_data.len = strlen(buffer);
755 if (fetch_file_send_callback(&msg, ctx))
756 goto fetch_file_process_dir_aborted;
757
758 msg.type = FETCH_FINISHED;
759 fetch_file_send_callback(&msg, ctx);
760
761fetch_file_process_dir_aborted:
762
763 if (listing != NULL) {
764 for (i = 0; i < n; i++) {
765 free(listing[i]);
766 }
767 free(listing);
768 }
769}
770
771
772/* process a file fetch */
774{
775 struct stat fdstat; /**< The objects stat */
776
777 if (stat(ctx->path, &fdstat) != 0) {
778 /* process errors as appropriate */
781 return;
782 }
783
784 if (S_ISDIR(fdstat.st_mode)) {
785 /* directory listing */
786 fetch_file_process_dir(ctx, &fdstat);
787 return;
788 } else if (S_ISREG(fdstat.st_mode)) {
789 /* regular file */
790 fetch_file_process_plain(ctx, &fdstat);
791 return;
792 } else {
793 /* unhandled type of file */
794 fetch_file_process_error(ctx, 501);
795 }
796
797 return;
798}
799
800/** callback to poll for additional file fetch contents */
801static void fetch_file_poll(lwc_string *scheme)
802{
803 struct fetch_file_context *c, *save_ring = NULL;
804
805 while (ring != NULL) {
806 /* Take the first entry from the ring */
807 c = ring;
808 RING_REMOVE(ring, c);
809
810 /* Ignore fetches that have been flagged as locked.
811 * This allows safe re-entrant calls to this function.
812 * Re-entrancy can occur if, as a result of a callback,
813 * the interested party causes fetch_poll() to be called
814 * again.
815 */
816 if (c->locked == true) {
817 RING_INSERT(save_ring, c);
818 continue;
819 }
820
821 /* Only process non-aborted fetches */
822 if (c->aborted == false) {
823 /* file fetches can be processed in one go */
825 }
826
827 /* And now finish */
829 fetch_free(c->fetchh);
830
831 }
832
833 /* Finally, if we saved any fetches which were locked, put them back
834 * into the ring for next time
835 */
836 ring = save_ring;
837}
838
840{
841 lwc_string *scheme = lwc_string_ref(corestring_lwc_file);
842 const struct fetcher_operation_table fetcher_ops = {
844 .acceptable = fetch_file_can_fetch,
845 .setup = fetch_file_setup,
846 .start = fetch_file_start,
847 .abort = fetch_file_abort,
848 .free = fetch_file_free,
849 .poll = fetch_file_poll,
850 .finalise = fetch_file_finalise
851 };
852
853 return fetcher_add(scheme, &fetcher_ops);
854}
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:773
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:801
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:665
static char * gen_nice_title(char *path)
Definition: file.c:470
nserror fetch_file_register(void)
Register file scheme handler.
Definition: file.c:839
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:632
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:282
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:534
#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